Skip to content

Fix SendTo to throw ArgumentException when remoteEP address family mismatches (#47772) - #135587

Open
Sonder-Traveller wants to merge 2 commits into
dotnet:mainfrom
Sonder-Traveller:issue-47772-sendto-addressfamily
Open

Sonder-Traveller wants to merge 2 commits into
dotnet:mainfrom
Sonder-Traveller:issue-47772-sendto-addressfamily

Conversation

@Sonder-Traveller

Copy link
Copy Markdown

Issue

Fixes #47772. When the remoteEP address family does not match the socket's address family, the Receive(Message)From variants throw an ArgumentException, but the SendTo variants let the underlying PAL fail instead, surfacing a SocketError.InvalidArgument (a SocketException), and SendToAsync fails silently asynchronously. This is inconsistent.

Problem

Socket.SendTo(EndPoint) and Socket.SendToAsync(SocketAsyncEventArgs) do not validate the endpoint's address family before calling into the OS PAL, unlike ReceiveFrom/ReceiveMessageFrom which guard via ValidateReceiveFromEndpointAndState.

Solution

Add a symmetric ValidateSendToEndpointAndState guard to the SendTo family that rejects an endPoint whose AddressFamily is incompatible with the socket, throwing the same ArgumentException (SR.net_InvalidEndPointAddressFamily) that the receive variants already throw. The check reuses the existing CanTryAddressFamily logic so it respects dual-mode sockets consistently. DnsEndPoint is also rejected up front, mirroring the receive path.

Behavior change

Socket.SendTo now throws ArgumentException instead of a SocketException/silent async failure when the endpoint's address family mismatches the socket. This aligns SendTo with the already-documented ReceiveFrom behavior.

Tests

Added MismatchedRemoteAddressFamily_Throws_ArgumentException to SendTo.Tests, asserting both the sync byte[]/span overloads and the async path throw ArgumentException. The pre-existing inconsistency was reproduced on a local SDK build before this change (receive → ArgumentException, send → SocketException/InvalidArgument).

@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 11, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@Sonder-Traveller

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@caraioniurie47

Copy link
Copy Markdown
Contributor

This matches the fix proposed in #47772 (comment), which is still waiting for an area owner's decision. It is a breaking change: these calls fail with a SocketException today (e.SocketError for SendToAsync(SocketAsyncEventArgs)), and ArgumentException does not derive from it. CONTRIBUTING.md ("Breaking Changes") asks for such a change to be agreed in an issue first, as docs/project/breaking-change-process.md describes. DualModeSocketTest.Socket_SendToV4IPEndPointToV4Host_Throws asserts today's SocketException for this case and is not changed here.

@Sonder-Traveller

Copy link
Copy Markdown
Author

Thanks for the careful analysis — my change is indeed the same CanTryAddressFamily guard proposed in #47772. I've brought the PR in line with that proposal:

  • The new SendTo test is now AddressFamilyDoesNotMatch_Throws_ArgumentException, mirroring the ReceiveFrom tests.
  • DualModeSocketTest.Socket_SendToV4IPEndPointToV4Host_Throws now expects ArgumentException (matching its ReceiveFrom counterpart), so the change is self-consistent and the existing dual-mode suite stays green.
  • The SocketAddress overloads are left untouched, as you suggested they be out of scope.

Agreed this is a breaking change (ArgumentException does not derive from SocketException), and per the repo's breaking-change process the direction still needs the area owner's sign-off before this can be merged. Happy to adjust the approach if the area owner prefers documenting the current behavior instead of changing it.

This branch has not been deployed

No deployments
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.

SendTo*** and Receive(Message)From*** throw different exceptions when remoteEP AddressFamily does not match

2 participants