diff --git a/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs b/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs index dd418d32f94406..92fed514916fa7 100644 --- a/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs +++ b/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices; + namespace System; /// Provides downlevel polyfills for static methods on . @@ -23,5 +25,16 @@ public static ulong DoubleToUInt64Bits(double value) return *(ulong*)&value; } } + + // ---- ReadOnlySpan read overloads (host-endian, semantics match BCL net5+) ---- + + public static short ToInt16(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static ushort ToUInt16(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static int ToInt32(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static uint ToUInt32(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static long ToInt64(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static ulong ToUInt64(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static float ToSingle(ReadOnlySpan value) => MemoryMarshal.Read(value); + public static double ToDouble(ReadOnlySpan value) => MemoryMarshal.Read(value); } } diff --git a/src/libraries/Common/src/Polyfills/HashCodePolyfills.cs b/src/libraries/Common/src/Polyfills/HashCodePolyfills.cs index 7b2bc309c24bfd..95aa9ad2ce5ea4 100644 --- a/src/libraries/Common/src/Polyfills/HashCodePolyfills.cs +++ b/src/libraries/Common/src/Polyfills/HashCodePolyfills.cs @@ -12,7 +12,7 @@ public static void AddBytes(this ref HashCode hashCode, ReadOnlySpan value { while (value.Length >= sizeof(int)) { - hashCode.Add(MemoryMarshal.Read(value)); + hashCode.Add(BitConverter.ToInt32(value)); value = value.Slice(sizeof(int)); } diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index 0aa1b22d5f316d..5da1144cd2e94a 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -1087,8 +1087,8 @@ public unsafe string[] GetValueNames() case Interop.Advapi32.RegistryValues.REG_QWORD: return dataLength switch { - 4 => MemoryMarshal.Read(span), - 8 => MemoryMarshal.Read(span), + 4 => BitConverter.ToInt32(span), + 8 => BitConverter.ToInt64(span), _ => span.Slice(0, dataLength).ToArray(), // This shouldn't happen, but the previous implementation included it defensively. }; diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 1a6cc53679e5f8..cf181a3cf2e763 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -137,6 +137,10 @@ System.Diagnostics.PerformanceCounter Link="Common\DisableRuntimeMarshalling.cs" /> + + + + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs index a9f4d8121f5033..34f317c812be5f 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs @@ -1713,11 +1713,11 @@ private long ReadValue(ReadOnlySpan data) { if (_size == 4) { - return (long)MemoryMarshal.Read(data.Slice(_offset)); + return (long)BitConverter.ToUInt32(data.Slice(_offset)); } else if (_size == 8) { - return MemoryMarshal.Read(data.Slice(_offset)); + return BitConverter.ToInt64(data.Slice(_offset)); } return -1; diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs index 7c2bb7b35764b3..87fbf233f882c6 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs @@ -761,9 +761,9 @@ private static ValueId GetValueId(string counterName) private static long ReadCounterValue(int counterType, ReadOnlySpan data) { if ((counterType & PerfCounterOptions.NtPerfCounterSizeLarge) != 0) - return MemoryMarshal.Read(data); + return BitConverter.ToInt64(data); else - return MemoryMarshal.Read(data); + return BitConverter.ToInt32(data); } private enum ValueId diff --git a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj index 04dfc7a44cf491..1c9501fdfd0c17 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -51,6 +51,7 @@ System.Formats.Cbor.CborWriter + diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs index adb2eb362c0308..d62cd99e4cdbcb 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs @@ -91,71 +91,27 @@ public static string BuildStringFromIndefiniteLengthTextString(int lengt [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort ReadHalfBigEndian(ReadOnlySpan source) - { - ushort value = BitConverter.IsLittleEndian ? - BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source)) : - MemoryMarshal.Read(source); - - return value; - } + => BinaryPrimitives.ReadUInt16BigEndian(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteHalfBigEndian(Span destination, ushort value) - { - if (BitConverter.IsLittleEndian) - { - ushort tmp = BinaryPrimitives.ReverseEndianness(value); - MemoryMarshal.Write(destination, ref tmp); - } - else - { - MemoryMarshal.Write(destination, ref value); - } - } + => BinaryPrimitives.WriteUInt16BigEndian(destination, value); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ReadSingleBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - Int32BitsToSingle(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } + => Int32BitsToSingle(BinaryPrimitives.ReadInt32BigEndian(source)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteSingleBigEndian(Span destination, float value) - { - if (BitConverter.IsLittleEndian) - { - int tmp = BinaryPrimitives.ReverseEndianness(SingleToInt32Bits(value)); - MemoryMarshal.Write(destination, ref tmp); - } - else - { - MemoryMarshal.Write(destination, ref value); - } - } + => BinaryPrimitives.WriteInt32BigEndian(destination, SingleToInt32Bits(value)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double ReadDoubleBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } + => BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64BigEndian(source)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteDoubleBigEndian(Span destination, double value) - { - if (BitConverter.IsLittleEndian) - { - long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - MemoryMarshal.Write(destination, ref tmp); - } - else - { - MemoryMarshal.Write(destination, ref value); - } - } + => BinaryPrimitives.WriteInt64BigEndian(destination, BitConverter.DoubleToInt64Bits(value)); internal static uint SingleToUInt32Bits(float value) => (uint)SingleToInt32Bits(value); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs b/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs index b53353cdf18edc..e093852350f318 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs @@ -183,7 +183,7 @@ public IPAddress(ReadOnlySpan address) { if (address.Length == IPAddressParserStatics.IPv4AddressBytes) { - PrivateAddress = MemoryMarshal.Read(address); + PrivateAddress = BitConverter.ToUInt32(address); } else if (address.Length == IPAddressParserStatics.IPv6AddressBytes) { @@ -721,10 +721,10 @@ public override int GetHashCode() { ReadOnlySpan numbers = MemoryMarshal.AsBytes(_numbers).Slice(0, 16); _hashCode = HashCode.Combine( - MemoryMarshal.Read(numbers), - MemoryMarshal.Read(numbers.Slice(4)), - MemoryMarshal.Read(numbers.Slice(8)), - MemoryMarshal.Read(numbers.Slice(12)), + BitConverter.ToUInt32(numbers), + BitConverter.ToUInt32(numbers.Slice(4)), + BitConverter.ToUInt32(numbers.Slice(8)), + BitConverter.ToUInt32(numbers.Slice(12)), _addressOrScopeId); } else diff --git a/src/libraries/System.Private.CoreLib/src/Internal/Win32/RegistryKey.cs b/src/libraries/System.Private.CoreLib/src/Internal/Win32/RegistryKey.cs index fd590c9e2ba7f1..a0557322279ecb 100644 --- a/src/libraries/System.Private.CoreLib/src/Internal/Win32/RegistryKey.cs +++ b/src/libraries/System.Private.CoreLib/src/Internal/Win32/RegistryKey.cs @@ -287,8 +287,8 @@ public string[] GetValueNames() case Interop.Advapi32.RegistryValues.REG_QWORD: return dataLength switch { - 4 => MemoryMarshal.Read(span), - 8 => MemoryMarshal.Read(span), + 4 => BitConverter.ToInt32(span), + 8 => BitConverter.ToInt64(span), _ => span.Slice(0, dataLength).ToArray(), // This shouldn't happen, but the previous implementation included it defensively. }; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs index 661910025d8b1b..9def1dadecacfa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipePayloadDecoder.cs @@ -55,12 +55,12 @@ internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, R } else if (parameterType == typeof(byte) || enumType == typeof(byte)) { - decodedFields[i] = MemoryMarshal.Read(payload); + decodedFields[i] = payload[0]; payload = payload.Slice(sizeof(byte)); } else if (parameterType == typeof(sbyte) || enumType == typeof(sbyte)) { - decodedFields[i] = MemoryMarshal.Read(payload); + decodedFields[i] = (sbyte)payload[0]; payload = payload.Slice(sizeof(sbyte)); } else if (parameterType == typeof(short) || enumType == typeof(short)) diff --git a/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj b/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj index b2b23ba884f621..b9951dd48a67b5 100644 --- a/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj +++ b/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj @@ -57,6 +57,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs index a7127751bc5c11..109c39635f6c28 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs @@ -385,7 +385,7 @@ public static CspParameters GetProvParameters(this SafeProvOrNCryptKeyHandle han throw new CryptographicException(); } - int provType = MemoryMarshal.Read(stackSpan.Slice(0, size)); + int provType = BitConverter.ToInt32(stackSpan.Slice(0, size)); size = stackSpan.Length; if (!Interop.Advapi32.CryptGetProvParam(handle, CryptProvParam.PP_KEYSET_TYPE, stackSpan, ref size)) @@ -399,7 +399,7 @@ public static CspParameters GetProvParameters(this SafeProvOrNCryptKeyHandle han throw new CryptographicException(); } - int keysetType = MemoryMarshal.Read(stackSpan.Slice(0, size)); + int keysetType = BitConverter.ToInt32(stackSpan.Slice(0, size)); // Only CRYPT_MACHINE_KEYSET is described as coming back, but be defensive. CspProviderFlags provFlags = diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index 19cc655555f692..a6d789e4ff0fc3 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -712,6 +712,10 @@ System.Security.Cryptography.Pkcs.EnvelopedCms + + + + diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs index 1e69749ed681eb..d112569f31b54a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCrlCache.cs @@ -387,7 +387,7 @@ private static string GetCrlFileName(SafeX509Handle cert, string crlUrl) throw new CryptographicException(); } - uint urlHash = MemoryMarshal.Read(hash); + uint urlHash = BitConverter.ToUInt32(hash); // OpenSSL's hashed filename algorithm is the 8-character hex version of the 32-bit value // of X509_issuer_name_hash (or X509_subject_name_hash, depending on the context). diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 687d263b4a3197..2f1a903683e201 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -369,6 +369,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/PropertyRef.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/PropertyRef.cs index aabcfdd2ee5f9f..1888c84cd3b218 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/PropertyRef.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/PropertyRef.cs @@ -58,13 +58,13 @@ public static ulong GetKey(ReadOnlySpan name) { 0 => 0, 1 => name[0], - 2 => MemoryMarshal.Read(name), - 3 => MemoryMarshal.Read(name) | ((ulong)name[2] << 16), - 4 => MemoryMarshal.Read(name), - 5 => MemoryMarshal.Read(name) | ((ulong)name[4] << 32), - 6 => MemoryMarshal.Read(name) | ((ulong)MemoryMarshal.Read(name.Slice(4, 2)) << 32), - 7 => MemoryMarshal.Read(name) | ((ulong)MemoryMarshal.Read(name.Slice(4, 2)) << 32) | ((ulong)name[6] << 48), - _ => MemoryMarshal.Read(name) & 0x00ffffffffffffffUL + 2 => BitConverter.ToUInt16(name), + 3 => BitConverter.ToUInt16(name) | ((ulong)name[2] << 16), + 4 => BitConverter.ToUInt32(name), + 5 => BitConverter.ToUInt32(name) | ((ulong)name[4] << 32), + 6 => BitConverter.ToUInt32(name) | ((ulong)BitConverter.ToUInt16(name.Slice(4, 2)) << 32), + 7 => BitConverter.ToUInt32(name) | ((ulong)BitConverter.ToUInt16(name.Slice(4, 2)) << 32) | ((ulong)name[6] << 48), + _ => BitConverter.ToUInt64(name) & 0x00ffffffffffffffUL }; #if DEBUG // Verify key contains the embedded bytes as expected.