Skip to content

Fix UdpClient.EnableBroadcast not preventing broadcast sends#124482

Merged
liveans merged 4 commits intodotnet:mainfrom
matantsach:fix/118055-udpclient-enable-broadcast
Mar 16, 2026
Merged

Fix UdpClient.EnableBroadcast not preventing broadcast sends#124482
liveans merged 4 commits intodotnet:mainfrom
matantsach:fix/118055-udpclient-enable-broadcast

Conversation

@matantsach
Copy link
Contributor

Summary

Fixes #118055

UdpClient.CheckForBroadcast() unconditionally auto-enables the Broadcast socket option when sending to IPAddress.Broadcast, even when the user has explicitly set EnableBroadcast = false. This PR makes CheckForBroadcast() respect the user's explicit choice.

Changes

  • Added _isBroadcastSetByUser field to track whether EnableBroadcast has been explicitly set by the user
  • Modified CheckForBroadcast() to skip auto-enable when the user has explicitly set EnableBroadcast
  • Backward-compatible: auto-enable behavior is preserved when users have not explicitly set the property

Note: The pre-existing _isBroadcast flag is not reset when the Client socket is replaced via the property setter. The new _isBroadcastSetByUser flag follows this same pattern for consistency. Resetting state on socket replacement could be a follow-up improvement.

Testing

  • EnableBroadcast_ExplicitlyDisabled_NotAutoEnabled — verifies that explicitly disabling broadcast prevents auto-enable on broadcast send
  • EnableBroadcast_ExplicitlyEnabledThenDisabled_NotAutoEnabled — verifies the toggle case (enable → disable) also prevents auto-enable
  • EnableBroadcast_NotExplicitlySet_AutoEnabled — verifies backward compatibility: auto-enable still works when the user hasn't set the property

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Feb 16, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

@stephentoub
Copy link
Member

🤖 Copilot Code Review — PR #124482

Holistic Assessment

Motivation: The issue is real and well-documented (#118055). UdpClient.CheckForBroadcast() silently overrides an explicit EnableBroadcast = false by auto-enabling broadcast when sending to IPAddress.Broadcast. This violates user expectations — if you explicitly disable a feature, it should stay disabled.

Approach: Tracking whether the user explicitly set EnableBroadcast via a private _isBroadcastSetByUser field is a simple, correct, and minimal fix. It follows the same pattern as the existing _isBroadcast field.

Summary: ⚠️ Needs Changes. The core logic is correct and the approach is sound, but the tests won't compile due to a non-existent PlatformDetection property, and there are a few test convention issues.


Detailed Findings

❌ Test compilation error — PlatformDetection.IsThreadingSupported does not exist

All three new test methods use:

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]

This property does not exist on PlatformDetection. The correct property is IsMultithreadingSupported, which is what every other test in this file uses. This will cause a compile error.

Flagged independently by all review models (high confidence).

⚠️ Redundant [SkipOnPlatform(TestPlatforms.Wasi)] attribute

The new tests use both [ConditionalFact(...IsMultithreadingSupported)] and [SkipOnPlatform(TestPlatforms.Wasi)]. Since WASI does not support multithreading, IsMultithreadingSupported already handles the WASI skip. Existing Send-based tests in this file (e.g., BeginSend_AsyncOperationCompletes_Success, Send_InvalidArguments_Throws) use only [ConditionalFact(...IsMultithreadingSupported)] without the Wasi skip. The new tests should follow the same pattern for consistency.

💡 Test consolidation — prefer [Theory] over duplicate [Fact] methods

EnableBroadcast_ExplicitlyDisabled_NotAutoEnabled and EnableBroadcast_ExplicitlyEnabledThenDisabled_NotAutoEnabled test the same outcome with slightly different setup. These could be consolidated into a single [Theory]:

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsMultithreadingSupported))]
[InlineData(false)] // Set false only
[InlineData(true)]  // Set true then false
public void EnableBroadcast_ExplicitlyDisabled_NotAutoEnabled(bool setTrueFirst)
{
    using (var udpClient = new UdpClient())
    {
        if (setTrueFirst) udpClient.EnableBroadcast = true;
        udpClient.EnableBroadcast = false;

        try
        {
            udpClient.Send(new byte[1], 1, new IPEndPoint(IPAddress.Broadcast, UnusedPort));
        }
        catch (SocketException) { }

        Assert.False(udpClient.EnableBroadcast);
    }
}

✅ Implementation logic — correct and minimal

The _isBroadcastSetByUser flag correctly distinguishes between "user never touched EnableBroadcast" (auto-enable preserved for backward compatibility) and "user explicitly set EnableBroadcast" (user's choice respected). The flag is checked in the right place — CheckForBroadcast, which is called from all 7 send/connect paths.

✅ Backward compatibility — preserved for default case

When EnableBroadcast is never explicitly set by the user, the auto-enable behavior is unchanged. The test EnableBroadcast_NotExplicitlySet_AutoEnabled correctly validates this.

💡 Note on Client property replacement

As the PR description mentions, neither _isBroadcast nor _isBroadcastSetByUser is reset when the underlying socket is replaced via the Client property setter. This is a pre-existing gap, and keeping consistent behavior is reasonable. A follow-up could address both fields together.

matantsach and others added 3 commits March 5, 2026 16:03
When a user explicitly sets EnableBroadcast to false, CheckForBroadcast()
should respect that choice and not auto-enable the broadcast socket option.

Fixes dotnet#118055

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Group related broadcast fields together, following the existing
convention in UDPClient.cs.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…butes

- Consolidate ExplicitlyDisabled and ExplicitlyEnabledThenDisabled tests
  into a single [Theory] with [InlineData(false/true)]
- Remove redundant [SkipOnPlatform(TestPlatforms.Wasi)] attributes since
  IsThreadingSupported already returns false on WASI

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@matantsach matantsach force-pushed the fix/118055-udpclient-enable-broadcast branch from e66e7fa to 988626d Compare March 5, 2026 14:04
@matantsach
Copy link
Contributor Author

Addressed the feedback — consolidated the two "explicitly disabled" tests into a [ConditionalTheory] with [InlineData(false/true)] and removed the redundant [SkipOnPlatform(TestPlatforms.Wasi)] attributes, since IsThreadingSupported already returns false on WASI.

One note: PlatformDetection.IsThreadingSupported does exist (PlatformDetection.cs, line 142) and is what every other test in UdpClientTest.cs uses. IsMultithreadingSupported doesn't exist in the codebase. I believe the Copilot review hallucinated that property name.

Also rebased on latest main.

@matantsach
Copy link
Contributor Author

Correction on my previous comment: the Copilot review was right — the property is IsMultithreadingSupported, not IsThreadingSupported. I was mistaken. Fixed in the latest push.

@matantsach
Copy link
Contributor Author

@dotnet-policy-service agree

@matantsach
Copy link
Contributor Author

Hi — just checking in. I addressed all the review feedback on March 5 (consolidated tests into a [ConditionalTheory], removed redundant [SkipOnPlatform], and corrected the PlatformDetection property). Is there anything else needed from my side?

@liveans
Copy link
Member

liveans commented Mar 13, 2026

Hi — just checking in. I addressed all the review feedback on March 5 (consolidated tests into a [ConditionalTheory], removed redundant [SkipOnPlatform], and corrected the PlatformDetection property). Is there anything else needed from my side?

Hello, thanks for checking in, no action is needed from your side for now. I'll review this PR today.

@liveans
Copy link
Member

liveans commented Mar 15, 2026

/azp run runtime-libraries-coreclr outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@liveans liveans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@liveans
Copy link
Member

liveans commented Mar 16, 2026

/ba-g failures unrelated

@liveans liveans merged commit e2322af into dotnet:main Mar 16, 2026
86 of 98 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Net.Sockets community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regarding the issue of the UdpClient.EnableBroadcast property

3 participants