From a99952d7e73e1028e4c38489fa221e2106fd5ea7 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 9 May 2023 10:25:30 +0100 Subject: [PATCH 1/3] Use `NativeMemory` in `System.Data.Odbc` --- .../System/Data/Common/SafeNativeMethods.cs | 28 ------------------- .../System/Data/ProviderBase/DbBuffer.cs | 24 ++++------------ .../src/System.Data.Odbc.csproj | 1 - 3 files changed, 6 insertions(+), 47 deletions(-) delete mode 100644 src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs deleted file mode 100644 index 713c692ae4a4df..00000000000000 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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.Data -{ - internal static partial class SafeNativeMethods - { - internal static IntPtr LocalAlloc(nint initialSize) - { - var handle = Marshal.AllocHGlobal(initialSize); - ZeroMemory(handle, (int)initialSize); - return handle; - } - - internal static void LocalFree(IntPtr ptr) - { - Marshal.FreeHGlobal(ptr); - } - - internal static void ZeroMemory(IntPtr ptr, int length) - { - var zeroes = new byte[length]; - Marshal.Copy(zeroes, 0, ptr, length); - } - } -} diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs index 9ef1e0f7b90990..8aee8d41f5f28e 100644 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs +++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs @@ -14,21 +14,12 @@ internal abstract class DbBuffer : SafeHandle { private readonly int _bufferLength; - protected DbBuffer(int initialSize) : base(IntPtr.Zero, true) + protected unsafe DbBuffer(int initialSize) : base(IntPtr.Zero, true) { if (0 < initialSize) { _bufferLength = initialSize; - - try { } - finally - { - base.handle = SafeNativeMethods.LocalAlloc((IntPtr)initialSize); - } - if (IntPtr.Zero == base.handle) - { - throw new OutOfMemoryException(); - } + base.handle = (IntPtr)NativeMemory.AllocZeroed((uint)initialSize); } } @@ -368,15 +359,12 @@ internal unsafe float ReadSingle(int offset) return BitConverter.Int32BitsToSingle(value); } - protected override bool ReleaseHandle() + protected override unsafe bool ReleaseHandle() { // NOTE: The SafeHandle class guarantees this will be called exactly once. IntPtr ptr = base.handle; base.handle = IntPtr.Zero; - if (IntPtr.Zero != ptr) - { - SafeNativeMethods.LocalFree(ptr); - } + NativeMemory.Free((void*)ptr); return true; } @@ -639,7 +627,7 @@ internal unsafe void WriteSingle(int offset, float value) WriteInt32(offset, BitConverter.SingleToInt32Bits(value)); } - internal void ZeroMemory() + internal unsafe void ZeroMemory() { bool mustRelease = false; @@ -648,7 +636,7 @@ internal void ZeroMemory() DangerousAddRef(ref mustRelease); IntPtr ptr = DangerousGetHandle(); - SafeNativeMethods.ZeroMemory(ptr, Length); + NativeMemory.Clear((void*)ptr, (uint)Length); } finally { diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 56bcf649fcd4b3..0bcb60c92da190 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -42,7 +42,6 @@ System.Data.Odbc.OdbcTransaction - Date: Tue, 9 May 2023 15:31:49 +0100 Subject: [PATCH 2/3] Workaround lack of `NativeMemory.Clear` on .NET 6 --- .../System/Data/Common/SafeNativeMethods.cs | 21 +++++++++++++++++++ .../System/Data/ProviderBase/DbBuffer.cs | 4 ++-- .../src/System.Data.Odbc.csproj | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs new file mode 100644 index 00000000000000..cf868366882b01 --- /dev/null +++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs @@ -0,0 +1,21 @@ +// 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.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Data +{ + internal static partial class SafeNativeMethods + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe void ZeroMemory(IntPtr ptr, int length) + { +#if !NET7_0_OR_GREATER + new Span((void*)ptr, length).Clear(); +#else + NativeMemory.Clear((void*)ptr, (uint)length); +#endif + } + } +} diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs index 8aee8d41f5f28e..01be49419818a2 100644 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs +++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs @@ -627,7 +627,7 @@ internal unsafe void WriteSingle(int offset, float value) WriteInt32(offset, BitConverter.SingleToInt32Bits(value)); } - internal unsafe void ZeroMemory() + internal void ZeroMemory() { bool mustRelease = false; @@ -636,7 +636,7 @@ internal unsafe void ZeroMemory() DangerousAddRef(ref mustRelease); IntPtr ptr = DangerousGetHandle(); - NativeMemory.Clear((void*)ptr, (uint)Length); + SafeNativeMethods.ZeroMemory(ptr, Length); } finally { diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 0bcb60c92da190..56bcf649fcd4b3 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -42,6 +42,7 @@ System.Data.Odbc.OdbcTransaction + Date: Tue, 9 May 2023 21:23:18 +0100 Subject: [PATCH 3/3] Use `Unsafe.InitBlock` --- .../System/Data/Common/SafeNativeMethods.cs | 21 ------------------- .../System/Data/ProviderBase/DbBuffer.cs | 6 ++++-- .../src/System.Data.Odbc.csproj | 1 - 3 files changed, 4 insertions(+), 24 deletions(-) delete mode 100644 src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs deleted file mode 100644 index cf868366882b01..00000000000000 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/Common/SafeNativeMethods.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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.CompilerServices; -using System.Runtime.InteropServices; - -namespace System.Data -{ - internal static partial class SafeNativeMethods - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe void ZeroMemory(IntPtr ptr, int length) - { -#if !NET7_0_OR_GREATER - new Span((void*)ptr, length).Clear(); -#else - NativeMemory.Clear((void*)ptr, (uint)length); -#endif - } - } -} diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs index 01be49419818a2..541f1516eff598 100644 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs +++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbBuffer.cs @@ -16,6 +16,8 @@ internal abstract class DbBuffer : SafeHandle protected unsafe DbBuffer(int initialSize) : base(IntPtr.Zero, true) { + Debug.Assert(initialSize % IntPtr.Size == 0, $"Expected aligned {nameof(initialSize)}."); + if (0 < initialSize) { _bufferLength = initialSize; @@ -627,7 +629,7 @@ internal unsafe void WriteSingle(int offset, float value) WriteInt32(offset, BitConverter.SingleToInt32Bits(value)); } - internal void ZeroMemory() + internal unsafe void ZeroMemory() { bool mustRelease = false; @@ -636,7 +638,7 @@ internal void ZeroMemory() DangerousAddRef(ref mustRelease); IntPtr ptr = DangerousGetHandle(); - SafeNativeMethods.ZeroMemory(ptr, Length); + Unsafe.InitBlock((void*)ptr, 0, (uint)Length); } finally { diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 56bcf649fcd4b3..0bcb60c92da190 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -42,7 +42,6 @@ System.Data.Odbc.OdbcTransaction -