From 3bd81c1ea080c7dc966259c6384491cd9a0eff24 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:05:50 +0100 Subject: [PATCH 1/4] Remove `unsafe` modifier from `Memory.Span` --- src/libraries/System.Private.CoreLib/src/System/Memory.cs | 4 ++-- .../System.Private.CoreLib/src/System/ReadOnlyMemory.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index 989cac29c57c1f..16bf85e5d0e514 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -263,7 +263,7 @@ public Memory Slice(int start, int length) /// /// Returns a span from the memory. /// - public unsafe Span Span + public Span Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get @@ -343,7 +343,7 @@ public unsafe Span Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (IntPtr)(void*)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, (nint)desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs index 6b59ac75e57663..ca3a29169e032e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs @@ -192,7 +192,7 @@ public ReadOnlyMemory Slice(int start, int length) /// /// Returns a span from the memory. /// - public unsafe ReadOnlySpan Span + public ReadOnlySpan Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get @@ -265,7 +265,7 @@ public unsafe ReadOnlySpan Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (IntPtr)(void*)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, (nint)desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } From e68e7d9eba7a7bb15fe33329e1cf7558001553c1 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 22 Oct 2024 02:59:37 +0100 Subject: [PATCH 2/4] Make `desiredStartIndex` an `int` --- src/libraries/System.Private.CoreLib/src/System/Memory.cs | 6 +++--- .../System.Private.CoreLib/src/System/ReadOnlyMemory.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index 16bf85e5d0e514..56e2aa9fc9406f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -327,12 +327,12 @@ public Span Span // least to be in-bounds when compared with the original Memory instance, so using the span won't // AV the process. - nuint desiredStartIndex = (uint)_index & (uint)ReadOnlyMemory.RemoveFlagsBitMask; + int desiredStartIndex = _index & ReadOnlyMemory.RemoveFlagsBitMask; int desiredLength = _length; #if TARGET_64BIT // See comment in Span.Slice for how this works. - if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) + if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) { ThrowHelper.ThrowArgumentOutOfRangeException(); } @@ -343,7 +343,7 @@ public Span Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (nint)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, (uint)desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs index ca3a29169e032e..98591ea6a64d54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs @@ -249,12 +249,12 @@ public ReadOnlySpan Span // least to be in-bounds when compared with the original Memory instance, so using the span won't // AV the process. - nuint desiredStartIndex = (uint)_index & (uint)RemoveFlagsBitMask; + int desiredStartIndex = _index & RemoveFlagsBitMask; int desiredLength = _length; #if TARGET_64BIT // See comment in Span.Slice for how this works. - if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) + if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) { ThrowHelper.ThrowArgumentOutOfRangeException(); } @@ -265,7 +265,7 @@ public ReadOnlySpan Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (nint)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, (uint)desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } From b6b93d972b5b16b345e53c8c07c074cdc85cad9a Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:23:30 +0100 Subject: [PATCH 3/4] Use `nuint` and add comment --- src/libraries/System.Private.CoreLib/src/System/Memory.cs | 6 ++++-- .../System.Private.CoreLib/src/System/ReadOnlyMemory.cs | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index 56e2aa9fc9406f..5bddd512b785b9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -327,7 +327,9 @@ public Span Span // least to be in-bounds when compared with the original Memory instance, so using the span won't // AV the process. - int desiredStartIndex = _index & ReadOnlyMemory.RemoveFlagsBitMask; + // We use 'nuint' because it gives us a free early zero-extension to 64 bits when running on a 64-bit platform. + nuint desiredStartIndex = (uint)_index & (uint)ReadOnlyMemory.RemoveFlagsBitMask; + int desiredLength = _length; #if TARGET_64BIT @@ -343,7 +345,7 @@ public Span Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (uint)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs index 98591ea6a64d54..ee2059ef0170aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs @@ -249,12 +249,14 @@ public ReadOnlySpan Span // least to be in-bounds when compared with the original Memory instance, so using the span won't // AV the process. - int desiredStartIndex = _index & RemoveFlagsBitMask; + // We use 'nuint' because it gives us a free early zero-extension to 64 bits when running on a 64-bit platform. + nuint desiredStartIndex = (uint)_index & (uint)RemoveFlagsBitMask; + int desiredLength = _length; #if TARGET_64BIT // See comment in Span.Slice for how this works. - if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) + if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) { ThrowHelper.ThrowArgumentOutOfRangeException(); } @@ -265,7 +267,7 @@ public ReadOnlySpan Span } #endif - refToReturn = ref Unsafe.Add(ref refToReturn, (uint)desiredStartIndex); + refToReturn = ref Unsafe.Add(ref refToReturn, desiredStartIndex); lengthOfUnderlyingSpan = desiredLength; } From fbe01cd1526bd275836e5d2cf8a4b3080fe7adf8 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:04:33 +0100 Subject: [PATCH 4/4] fixup!b6b93d972b5b16b345e53c8c07c074cdc85cad9a --- src/libraries/System.Private.CoreLib/src/System/Memory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index 5bddd512b785b9..5ec18c4cb842ec 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -334,7 +334,7 @@ public Span Span #if TARGET_64BIT // See comment in Span.Slice for how this works. - if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) + if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan) { ThrowHelper.ThrowArgumentOutOfRangeException(); }