Skip to content

Don't allow mutating the ScopeId on static readonly IPAddress fields #115456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ public class IPAddress : ISpanFormattable, ISpanParsable<IPAddress>, IUtf8SpanFo

internal const uint LoopbackMaskHostOrder = 0xFF000000;

public static readonly IPAddress IPv6Any = new IPAddress((ReadOnlySpan<byte>)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0);
public static readonly IPAddress IPv6Loopback = new IPAddress((ReadOnlySpan<byte>)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 0);
public static readonly IPAddress IPv6Any = new ReadOnlyIPAddress([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0);
public static readonly IPAddress IPv6Loopback = new ReadOnlyIPAddress([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 0);
public static readonly IPAddress IPv6None = IPv6Any;

private static readonly IPAddress s_loopbackMappedToIPv6 = new IPAddress((ReadOnlySpan<byte>)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1], 0);
private static readonly IPAddress s_loopbackMappedToIPv6 = new ReadOnlyIPAddress([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1], 0);

/// <summary>
/// For IPv4 addresses, this field stores the Address.
Expand Down Expand Up @@ -438,6 +438,11 @@ public long ScopeId
ThrowSocketOperationNotSupported();
}

if (this is ReadOnlyIPAddress)
{
ThrowSocketOperationNotSupported();
}

// Consider: Since scope is only valid for link-local and site-local
// addresses we could implement some more robust checking here
ArgumentOutOfRangeException.ThrowIfNegative(value);
Expand Down Expand Up @@ -772,6 +777,9 @@ private sealed class ReadOnlyIPAddress : IPAddress
{
public ReadOnlyIPAddress(ReadOnlySpan<byte> newAddress) : base(newAddress)
{ }

public ReadOnlyIPAddress(ReadOnlySpan<byte> address, long scopeid) : base(address, scopeid)
{ }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ public static void Address_ReadOnlyStatics_Set_Failure()
Assert.Throws<SocketException>(() => IPAddress.Broadcast.Address = MaxAddress - 1);
Assert.Throws<SocketException>(() => IPAddress.Loopback.Address = MaxAddress - 1);
Assert.Throws<SocketException>(() => IPAddress.None.Address = MaxAddress - 1);

Assert.Throws<SocketException>(() => IPAddress.IPv6Any.ScopeId = 1);
Assert.Throws<SocketException>(() => IPAddress.IPv6Loopback.ScopeId = 1);
Assert.Throws<SocketException>(() => IPAddress.IPv6None.ScopeId = 1);
}
#pragma warning restore 618
}
Expand Down
Loading