From be68b1b7d49c86034baa0a60d5fcbb3a9afc1fc0 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 11 Feb 2020 11:41:54 -0800 Subject: [PATCH 1/3] Fixing AccessViolationException on x86 architecture Fixes: #981 --- .../System.Data.OleDb/src/DbBindings.cs | 79 +++++++++++++++---- .../System.Data.OleDb/src/OleDbCommand.cs | 36 ++++++++- .../System.Data.OleDb/src/OleDbStruct.cs | 30 ++++++- .../src/UnsafeNativeMethods.cs | 2 +- 4 files changed, 126 insertions(+), 21 deletions(-) diff --git a/src/libraries/System.Data.OleDb/src/DbBindings.cs b/src/libraries/System.Data.OleDb/src/DbBindings.cs index 46c824d02f2e6d..65139fd434d61a 100644 --- a/src/libraries/System.Data.OleDb/src/DbBindings.cs +++ b/src/libraries/System.Data.OleDb/src/DbBindings.cs @@ -4,13 +4,16 @@ using System.Data.Common; using System.Diagnostics; +using System.Runtime.InteropServices; using System.Text; namespace System.Data.OleDb { internal sealed class Bindings { + private static readonly bool s_runningOnX86 = Marshal.SizeOf() == 4; private readonly tagDBPARAMBINDINFO[] _bindInfo; + private readonly tagDBPARAMBINDINFO_x86[] _bindInfo_x86; private readonly tagDBBINDING[] _dbbindings; private readonly tagDBCOLUMNACCESS[] _dbcolumns; @@ -42,7 +45,10 @@ private Bindings(int count) internal Bindings(OleDbParameter[] parameters, int collectionChangeID) : this(parameters.Length) { - _bindInfo = new tagDBPARAMBINDINFO[parameters.Length]; + if (s_runningOnX86) + _bindInfo_x86 = new tagDBPARAMBINDINFO_x86[parameters.Length]; + else + _bindInfo = new tagDBPARAMBINDINFO[parameters.Length]; _parameters = parameters; _collectionChangeID = collectionChangeID; _ifIRowsetElseIRow = true; @@ -54,6 +60,11 @@ internal Bindings(OleDbDataReader dataReader, bool ifIRowsetElseIRow, int count) _ifIRowsetElseIRow = ifIRowsetElseIRow; } + internal tagDBPARAMBINDINFO_x86[] BindInfo_x86 + { + get { return _bindInfo_x86; } + } + internal tagDBPARAMBINDINFO[] BindInfo { get { return _bindInfo; } @@ -100,40 +111,60 @@ internal bool ForceRebind // tagDBPARAMBINDINFO member access internal IntPtr DataSourceType { - //get { return _bindInfo[_index].pwszDataSourceType; } set { - _bindInfo[_index].pwszDataSourceType = value; + if (s_runningOnX86) + _bindInfo_x86[_index].pwszDataSourceType = value; + else + _bindInfo[_index].pwszDataSourceType = value; } } internal IntPtr Name { - //get { return _bindInfo[_index].pwszName; } set { - _bindInfo[_index].pwszName = value; + if (s_runningOnX86) + _bindInfo_x86[_index].pwszName = value; + else + _bindInfo[_index].pwszName = value; } } internal IntPtr ParamSize { get { - if (null != _bindInfo) + if (s_runningOnX86) + { + if (null != _bindInfo_x86) + { + return _bindInfo_x86[_index].ulParamSize; + } + return IntPtr.Zero; + } + else { - return _bindInfo[_index].ulParamSize; + if (null != _bindInfo) + { + return _bindInfo[_index].ulParamSize; + } + return IntPtr.Zero; } - return IntPtr.Zero; } set { - _bindInfo[_index].ulParamSize = value; + if (s_runningOnX86) + _bindInfo_x86[_index].ulParamSize = value; + else + _bindInfo[_index].ulParamSize = value; } } internal int Flags { - //get { return _bindInfo[_index].dwFlag; } set { + if (s_runningOnX86) + _bindInfo_x86[_index].dwFlags = value; + else _bindInfo[_index].dwFlags = value; } } @@ -223,9 +254,19 @@ internal byte Precision #endif set { - if (null != _bindInfo) + if (s_runningOnX86) { - _bindInfo[_index].bPrecision = value; + if (null != _bindInfo_x86) + { + _bindInfo_x86[_index].bPrecision = value; + } + } + else + { + if (null != _bindInfo) + { + _bindInfo[_index].bPrecision = value; + } } _dbbindings[_index].bPrecision = value; _dbcolumns[_index].bPrecision = value; @@ -238,9 +279,19 @@ internal byte Scale #endif set { - if (null != _bindInfo) + if (s_runningOnX86) { - _bindInfo[_index].bScale = value; + if (null != _bindInfo_x86) + { + _bindInfo_x86[_index].bScale = value; + } + } + else + { + if (null != _bindInfo) + { + _bindInfo[_index].bScale = value; + } } _dbbindings[_index].bScale = value; _dbcolumns[_index].bScale = value; diff --git a/src/libraries/System.Data.OleDb/src/OleDbCommand.cs b/src/libraries/System.Data.OleDb/src/OleDbCommand.cs index 0f8581f708e582..e0f3d2163c0d9a 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbCommand.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbCommand.cs @@ -400,7 +400,14 @@ private void CreateAccessor() bindings.AllocateForAccessor(null, 0, 0); - ApplyParameterBindings(commandWithParameters, bindings.BindInfo); + if (bindings.BindInfo_x86 != null) + { + ApplyParameterBindings(commandWithParameters, bindings.BindInfo_x86); + } + else + { + ApplyParameterBindings(commandWithParameters, bindings.BindInfo); + } UnsafeNativeMethods.IAccessor iaccessor = IAccessor(); OleDbHResult hr = bindings.CreateAccessor(iaccessor, ODB.DBACCESSOR_PARAMETERDATA); @@ -411,14 +418,37 @@ private void CreateAccessor() _dbBindings = bindings; } - private void ApplyParameterBindings(UnsafeNativeMethods.ICommandWithParameters commandWithParameters, tagDBPARAMBINDINFO[] bindInfo) + private unsafe void ApplyParameterBindings(UnsafeNativeMethods.ICommandWithParameters commandWithParameters, tagDBPARAMBINDINFO[] bindInfo) { IntPtr[] ordinals = new IntPtr[bindInfo.Length]; for (int i = 0; i < ordinals.Length; ++i) { ordinals[i] = (IntPtr)(i + 1); } - OleDbHResult hr = commandWithParameters.SetParameterInfo((IntPtr)bindInfo.Length, ordinals, bindInfo); + OleDbHResult hr; + fixed (tagDBPARAMBINDINFO* p = &bindInfo[0]) + { + hr = commandWithParameters.SetParameterInfo((IntPtr)bindInfo.Length, ordinals, (IntPtr)p); + } + + if (hr < 0) + { + ProcessResults(hr); + } + } + + private unsafe void ApplyParameterBindings(UnsafeNativeMethods.ICommandWithParameters commandWithParameters, tagDBPARAMBINDINFO_x86[] bindInfo_x86) + { + IntPtr[] ordinals = new IntPtr[bindInfo_x86.Length]; + for (int i = 0; i < ordinals.Length; ++i) + { + ordinals[i] = (IntPtr)(i + 1); + } + OleDbHResult hr; + fixed (tagDBPARAMBINDINFO_x86* p = &bindInfo_x86[0]) + { + hr = commandWithParameters.SetParameterInfo((IntPtr)bindInfo_x86.Length, ordinals, (IntPtr)p); + } if (hr < 0) { diff --git a/src/libraries/System.Data.OleDb/src/OleDbStruct.cs b/src/libraries/System.Data.OleDb/src/OleDbStruct.cs index 1254602394db7a..1b3b1d5d55c6c5 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbStruct.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbStruct.cs @@ -33,11 +33,35 @@ typedef struct tagDBPARAMBINDINFO { } #endif -#if (WIN32 && !ARCH_arm) [StructLayoutAttribute(LayoutKind.Sequential, Pack = 2)] -#else - [StructLayout(LayoutKind.Sequential, Pack = 8)] + internal struct tagDBPARAMBINDINFO_x86 + { + internal IntPtr pwszDataSourceType; + internal IntPtr pwszName; + internal IntPtr ulParamSize; + internal int dwFlags; + internal byte bPrecision; + internal byte bScale; + +#if DEBUG + public override string ToString() + { + StringBuilder builder = new StringBuilder(); + builder.Append("tagDBPARAMBINDINFO_x86").Append(Environment.NewLine); + if (IntPtr.Zero != pwszDataSourceType) + { + builder.Append("pwszDataSourceType =").Append(Marshal.PtrToStringUni(pwszDataSourceType)).Append(Environment.NewLine); + } + builder.Append("\tulParamSize =" + ulParamSize.ToInt64().ToString(CultureInfo.InvariantCulture)).Append(Environment.NewLine); + builder.Append("\tdwFlags =0x" + dwFlags.ToString("X4", CultureInfo.InvariantCulture)).Append(Environment.NewLine); + builder.Append("\tPrecision =" + bPrecision.ToString(CultureInfo.InvariantCulture)).Append(Environment.NewLine); + builder.Append("\tScale =" + bScale.ToString(CultureInfo.InvariantCulture)).Append(Environment.NewLine); + return builder.ToString(); + } #endif + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct tagDBPARAMBINDINFO { internal IntPtr pwszDataSourceType; diff --git a/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs b/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs index d18c574731bcff..07df57c6c14831 100644 --- a/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs +++ b/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs @@ -409,7 +409,7 @@ HRESULT SetParameterInfo( System.Data.OleDb.OleDbHResult SetParameterInfo( [In] IntPtr cParams, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] rgParamOrdinals, - [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct)] System.Data.OleDb.tagDBPARAMBINDINFO[] rgParamBindInfo); + [In] IntPtr rgParamBindInfo); } [Guid("2206CCB1-19C1-11D1-89E0-00C04FD7A829"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComImport, SuppressUnmanagedCodeSecurity] From e3886b69fb979e636954f60f504979a048c06104 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 11 Feb 2020 16:56:04 -0800 Subject: [PATCH 2/3] Update src/libraries/System.Data.OleDb/src/DbBindings.cs Co-Authored-By: Jan Kotas --- src/libraries/System.Data.OleDb/src/DbBindings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Data.OleDb/src/DbBindings.cs b/src/libraries/System.Data.OleDb/src/DbBindings.cs index 65139fd434d61a..526af1b4a7d479 100644 --- a/src/libraries/System.Data.OleDb/src/DbBindings.cs +++ b/src/libraries/System.Data.OleDb/src/DbBindings.cs @@ -165,7 +165,7 @@ internal int Flags if (s_runningOnX86) _bindInfo_x86[_index].dwFlags = value; else - _bindInfo[_index].dwFlags = value; + _bindInfo[_index].dwFlags = value; } } From 8dcf98f626dcbc21af443e02fde67739bb6f9069 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 11 Feb 2020 17:01:39 -0800 Subject: [PATCH 3/3] implicit check for x86 --- src/libraries/System.Data.OleDb/src/DbBindings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Data.OleDb/src/DbBindings.cs b/src/libraries/System.Data.OleDb/src/DbBindings.cs index 526af1b4a7d479..8044952a1c589e 100644 --- a/src/libraries/System.Data.OleDb/src/DbBindings.cs +++ b/src/libraries/System.Data.OleDb/src/DbBindings.cs @@ -11,7 +11,7 @@ namespace System.Data.OleDb { internal sealed class Bindings { - private static readonly bool s_runningOnX86 = Marshal.SizeOf() == 4; + private static readonly bool s_runningOnX86 = RuntimeInformation.ProcessArchitecture == Architecture.X86; private readonly tagDBPARAMBINDINFO[] _bindInfo; private readonly tagDBPARAMBINDINFO_x86[] _bindInfo_x86; private readonly tagDBBINDING[] _dbbindings;