Skip to content

Commit d1ec77f

Browse files
authored
Remove a few unsafe bits in S.P.Uri, S.N.Ping, System.Transactions.Local (#116281)
1 parent 76d7224 commit d1ec77f

File tree

4 files changed

+56
-56
lines changed

4 files changed

+56
-56
lines changed

src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public partial class Ping
2121
private const int IpV6HeaderLengthInBytes = 40;
2222
private static readonly ushort DontFragment = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)0x4000) : (ushort)0x4000;
2323

24-
private static unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, int timeout, PingOptions? options)
24+
private static SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, int timeout, PingOptions? options)
2525
{
2626
// Use a random value as the identifier. This doesn't need to be perfectly random
2727
// or very unpredictable, rather just good enough to avoid unexpected conflicts.
@@ -35,7 +35,10 @@ private static unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buf
3535
if (sendIpHeader)
3636
{
3737
iph.VersionAndLength = 0x45;
38-
totalLength = sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length);
38+
unsafe
39+
{
40+
totalLength = sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length);
41+
}
3942
// On OSX this strangely must be host byte order.
4043
iph.TotalLength = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)totalLength) : (ushort)totalLength;
4144
iph.Protocol = 1; // ICMP
@@ -103,19 +106,16 @@ private static Socket GetRawSocket(SocketConfig socketConfig)
103106
{
104107
// If it is not multicast, use Connect to scope responses only to the target address.
105108
socket.Connect(socketConfig.EndPoint);
106-
unsafe
109+
int opt = 1;
110+
if (ipv4)
107111
{
108-
int opt = 1;
109-
if (ipv4)
110-
{
111-
// setsockopt(fd, IPPROTO_IP, IP_RECVERR, &value, sizeof(int))
112-
socket.SetRawSocketOption(0, 11, new ReadOnlySpan<byte>(&opt, sizeof(int)));
113-
}
114-
else
115-
{
116-
// setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &value, sizeof(int))
117-
socket.SetRawSocketOption(41, 25, new ReadOnlySpan<byte>(&opt, sizeof(int)));
118-
}
112+
// setsockopt(fd, IPPROTO_IP, IP_RECVERR, &value, sizeof(int))
113+
socket.SetRawSocketOption(0, 11, MemoryMarshal.AsBytes(new ReadOnlySpan<int>(in opt)));
114+
}
115+
else
116+
{
117+
// setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &value, sizeof(int))
118+
socket.SetRawSocketOption(41, 25, MemoryMarshal.AsBytes(new ReadOnlySpan<int>(in opt)));
119119
}
120120
}
121121
#pragma warning restore 618
@@ -247,7 +247,7 @@ private static bool TryGetPingReply(
247247
return true;
248248
}
249249

250-
private static unsafe PingReply SendIcmpEchoRequestOverRawSocket(IPAddress address, byte[] buffer, int timeout, PingOptions? options)
250+
private static PingReply SendIcmpEchoRequestOverRawSocket(IPAddress address, byte[] buffer, int timeout, PingOptions? options)
251251
{
252252
SocketConfig socketConfig = GetSocketConfig(address, buffer, timeout, options);
253253
using (Socket socket = GetRawSocket(socketConfig))

src/libraries/System.Private.Uri/src/System/IPv4AddressHelper.cs

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,43 @@ internal static partial class IPv4AddressHelper
1313
// Parse and canonicalize
1414
internal static string ParseCanonicalName(string str, int start, int end, ref bool isLoopback)
1515
{
16+
// end includes ports, so changedEnd may be different from end
17+
int changedEnd = end;
18+
long result;
19+
1620
unsafe
1721
{
18-
byte* numbers = stackalloc byte[NumberOfLabels];
19-
isLoopback = Parse(str, numbers, start, end);
20-
21-
Span<char> stackSpace = stackalloc char[NumberOfLabels * 3 + 3];
22-
int totalChars = 0, charsWritten;
23-
for (int i = 0; i < 3; i++)
22+
fixed (char* ipString = str)
2423
{
25-
numbers[i].TryFormat(stackSpace.Slice(totalChars), out charsWritten);
26-
int periodPos = totalChars + charsWritten;
27-
stackSpace[periodPos] = '.';
28-
totalChars = periodPos + 1;
24+
result = ParseNonCanonical(ipString, start, ref changedEnd, true);
2925
}
30-
numbers[3].TryFormat(stackSpace.Slice(totalChars), out charsWritten);
31-
return new string(stackSpace.Slice(0, totalChars + charsWritten));
3226
}
33-
}
3427

35-
//
36-
// Parse
37-
//
38-
// Convert this IPv4 address into a sequence of 4 8-bit numbers
39-
//
40-
private static unsafe bool Parse(string name, byte* numbers, int start, int end)
41-
{
42-
fixed (char* ipString = name)
43-
{
44-
// end includes ports, so changedEnd may be different from end
45-
int changedEnd = end;
46-
long result = IPv4AddressHelper.ParseNonCanonical(ipString, start, ref changedEnd, true);
28+
Debug.Assert(result != Invalid, $"Failed to parse after already validated: {str}");
4729

48-
Debug.Assert(result != Invalid, $"Failed to parse after already validated: {name}");
30+
Span<byte> numbers =
31+
unchecked(
32+
[
33+
(byte)(result >> 24),
34+
(byte)(result >> 16),
35+
(byte)(result >> 8),
36+
(byte)(result)
37+
]);
4938

50-
unchecked
51-
{
52-
numbers[0] = (byte)(result >> 24);
53-
numbers[1] = (byte)(result >> 16);
54-
numbers[2] = (byte)(result >> 8);
55-
numbers[3] = (byte)(result);
56-
}
39+
isLoopback = numbers[0] == 127;
40+
41+
Span<char> stackSpace = stackalloc char[NumberOfLabels * 3 + 3];
42+
int totalChars = 0, charsWritten;
43+
for (int i = 0; i < NumberOfLabels - 1; i++)
44+
{
45+
numbers[i].TryFormat(stackSpace.Slice(totalChars), out charsWritten);
46+
int periodPos = totalChars + charsWritten;
47+
stackSpace[periodPos] = '.';
48+
totalChars = periodPos + 1;
5749
}
5850

59-
return numbers[0] == 127;
51+
numbers[3].TryFormat(stackSpace.Slice(totalChars), out charsWritten);
52+
return new string(stackSpace.Slice(0, totalChars + charsWritten));
6053
}
6154
}
6255
}

src/libraries/System.Private.Uri/src/System/UriExt.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri)
891891
return null;
892892
}
893893

894-
private unsafe string GetRelativeSerializationString(UriFormat format)
894+
private string GetRelativeSerializationString(UriFormat format)
895895
{
896896
if (format == UriFormat.UriEscaped)
897897
{

src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Xactopt.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Runtime.CompilerServices;
45
using System.Runtime.InteropServices;
56
using System.Runtime.InteropServices.Marshalling;
67
using System.Text;
@@ -24,27 +25,33 @@ internal Xactopt(uint ulTimeout, string szDescription)
2425
[CustomMarshaller(typeof(Xactopt), MarshalMode.UnmanagedToManagedIn, typeof(Marshaller))]
2526
internal static class Marshaller
2627
{
27-
internal unsafe struct XactoptNative
28+
internal struct XactoptNative
2829
{
2930
public uint UlTimeout;
3031

31-
public fixed byte SzDescription[40];
32+
public SzDescription SzDescription;
3233
}
3334

34-
public static unsafe XactoptNative ConvertToUnmanaged(Xactopt managed)
35+
[InlineArray(40)]
36+
internal struct SzDescription
37+
{
38+
private byte _element0;
39+
}
40+
41+
public static XactoptNative ConvertToUnmanaged(Xactopt managed)
3542
{
3643
XactoptNative native = new()
3744
{
3845
UlTimeout = managed.UlTimeout,
3946
};
4047

4148
// Usage of Xactopt never passes non-ASCII chars, so we can ignore them.
42-
Encoding.ASCII.TryGetBytes(managed.SzDescription, new Span<byte>(native.SzDescription, 40), out _);
49+
Encoding.ASCII.TryGetBytes(managed.SzDescription, native.SzDescription, out _);
4350

4451
return native;
4552
}
4653

47-
public static unsafe Xactopt ConvertToManaged(XactoptNative unmanaged)
48-
=> new(unmanaged.UlTimeout, Encoding.ASCII.GetString(unmanaged.SzDescription, 40));
54+
public static Xactopt ConvertToManaged(XactoptNative unmanaged)
55+
=> new(unmanaged.UlTimeout, Encoding.ASCII.GetString(unmanaged.SzDescription));
4956
}
5057
}

0 commit comments

Comments
 (0)