diff options
author | Neale Ferguson <neale@sinenomine.net> | 2014-09-12 19:19:05 +0400 |
---|---|---|
committer | Neale Ferguson <neale@sinenomine.net> | 2014-09-12 19:25:57 +0400 |
commit | 3f740f3d94c00f0edd4f0bb317bd3133ac279da0 (patch) | |
tree | c541ee5b396f68426ab2169156348b5128d83c43 /mcs/class/System.Data.OracleClient | |
parent | 300876b229fb73f6b6e13bda3081318b43c72971 (diff) |
Fixes 19752 -
Users have been complaining about strange errors arising when using the OracleClient classes.
I have tracked it down to the OciDefineHandle and OciDefineByPos calls, and OracleParameter
handling of amanged objects by unmanaged code. Currently two of the parameters passed to the
above OCI call are short variables. They are passed as "ref" fields as Oracle uses their
address to put size and indicator data once the data is fetched. However, being defined as
short means that they are eligible for being moved during garbage collection. Thus if that
field is moved between the OciDefineByPos call and the fetch of the data then what Oracle is
pointing to may no longer be variable. I'm thinking it may be better to define these fields as
IntPtr and allocate them and retrieve their values via Marshal.ReadInt16. As for OracleParameter,
it uses a managed object "indicator" that is also used in a similar way. This reference is replaced
by a IntPtr and a get/set method to access the contents.
Diffstat (limited to 'mcs/class/System.Data.OracleClient')
3 files changed, 111 insertions, 71 deletions
diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs index 3e1ce930785..e6125bf5c91 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciCalls.cs @@ -95,7 +95,7 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -111,7 +111,7 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -127,7 +127,7 @@ namespace System.Data.OracleClient.Oci byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -142,7 +142,7 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -157,7 +157,7 @@ namespace System.Data.OracleClient.Oci byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -172,7 +172,7 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -193,8 +193,8 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U4)] OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode); @@ -206,8 +206,8 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U4)] OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode); @@ -547,7 +547,7 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -558,7 +558,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByName (stmtp, out bindpp, errhp, placeholder, placeh_len, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByNameRef (IntPtr stmtp, @@ -569,7 +569,7 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -580,7 +580,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByNameRef (stmtp, out bindpp, errhp, placeholder, placeh_len, ref valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByNameBytes (IntPtr stmtp, @@ -591,7 +591,7 @@ namespace System.Data.OracleClient.Oci byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -602,7 +602,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByName", "OCI"); #endif return OciNativeCalls.OCIBindByNameBytes (stmtp, out bindpp, errhp, placeholder, placeh_len, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPos (IntPtr stmtp, @@ -612,7 +612,7 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -623,7 +623,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPos (stmtp, out bindpp, errhp, position, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPosRef (IntPtr stmtp, @@ -633,7 +633,7 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -644,7 +644,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPosRef (stmtp, out bindpp, errhp, position, ref valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } internal static int OCIBindByPosBytes (IntPtr stmtp, @@ -654,7 +654,7 @@ namespace System.Data.OracleClient.Oci byte[] valuep, int value_sz, [MarshalAs (UnmanagedType.U2)] OciDataType dty, - ref short indp, + IntPtr indp, IntPtr alenp, IntPtr rcodep, uint maxarr_len, @@ -665,7 +665,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIBindByPos", "OCI"); #endif return OciNativeCalls.OCIBindByPosBytes (stmtp, out bindpp, errhp, position, valuep, - value_sz, dty, ref indp, alenp, rcodep, maxarr_len, curelp, mode); + value_sz, dty, indp, alenp, rcodep, maxarr_len, curelp, mode); } [DllImport ("oci")] @@ -723,8 +723,8 @@ namespace System.Data.OracleClient.Oci IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode) { @@ -732,7 +732,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIDefineByPos", "OCI"); #endif return OciNativeCalls.OCIDefineByPos (stmtp, out defnpp, errhp, position, valuep, - value_sz, dty, ref indp, ref rlenp, rcodep, mode); + value_sz, dty, indp, rlenp, rcodep, mode); } internal static int OCIDefineByPosPtr (IntPtr stmtp, @@ -742,8 +742,8 @@ namespace System.Data.OracleClient.Oci ref IntPtr valuep, int value_sz, OciDataType dty, - ref short indp, - ref short rlenp, + IntPtr indp, + IntPtr rlenp, IntPtr rcodep, uint mode) { @@ -751,7 +751,7 @@ namespace System.Data.OracleClient.Oci Trace.WriteLineIf(traceOci, "OCIDefineByPosPtr", "OCI"); #endif return OciNativeCalls.OCIDefineByPosPtr (stmtp, out defnpp, errhp, position, ref valuep, - value_sz, dty, ref indp, ref rlenp, rcodep, mode); + value_sz, dty, indp, rlenp, rcodep, mode); } internal static int OCIDescriptorFree (IntPtr hndlp, diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs index baf90c1865f..9f46f98509b 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci/OciDefineHandle.cs @@ -32,16 +32,16 @@ namespace System.Data.OracleClient.Oci //IntPtr handle; IntPtr value; - short indicator; + IntPtr indicator; //OracleType type; OciDataType ociType; OciDataType definedType; int definedSize; - short rlenp = 0; + IntPtr rlenp; //short precision; short scale; Type fieldType; - //string name; + string name; // Oracle defines the LONG VARCHAR and LONG VARRAW to have a size of 2 to the 31 power - 5 // see DefineLongVarChar and DefineLongVarRaw @@ -70,11 +70,13 @@ namespace System.Data.OracleClient.Oci { OciParameterDescriptor parameter = ((OciStatementHandle) Parent).GetParameter (position); - //name = parameter.GetName (); + name = parameter.GetName (); definedType = parameter.GetDataType (); definedSize = parameter.GetDataSize (); //precision = parameter.GetPrecision (); scale = parameter.GetScale (); + rlenp = OciCalls.AllocateClear (sizeof(short)); + indicator = OciCalls.AllocateClear (sizeof(short)); Define (position, connection); @@ -103,7 +105,7 @@ namespace System.Data.OracleClient.Oci } internal bool IsNull { - get { return (indicator == -1); } + get { return (Indicator == -1); } } internal short Scale { @@ -111,7 +113,13 @@ namespace System.Data.OracleClient.Oci } internal short Size { - get { return rlenp; } + get { return(Marshal.ReadInt16(rlenp)); } + set { Marshal.WriteInt16(rlenp, value); } + } + + internal short Indicator { + get { return(Marshal.ReadInt16(indicator)); } + set { Marshal.WriteInt16(indicator, value); } } internal IntPtr Value { @@ -192,8 +200,8 @@ namespace System.Data.OracleClient.Oci ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -222,8 +230,8 @@ namespace System.Data.OracleClient.Oci value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -261,11 +269,11 @@ namespace System.Data.OracleClient.Oci value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); - rlenp = (short) definedSize; + Size = (short) definedSize; if (status != 0) { OciErrorInfo info = ErrorHandle.HandleError (); @@ -291,8 +299,8 @@ namespace System.Data.OracleClient.Oci value, maxByteCount, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); OciErrorHandle.ThrowExceptionIfError (ErrorHandle, status); @@ -312,10 +320,10 @@ namespace System.Data.OracleClient.Oci ErrorHandle, position + 1, value, - definedSize * 2, + definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -357,8 +365,8 @@ namespace System.Data.OracleClient.Oci ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -386,8 +394,8 @@ namespace System.Data.OracleClient.Oci value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); if (status != 0) { @@ -415,8 +423,8 @@ namespace System.Data.OracleClient.Oci value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); if (status != 0) { @@ -459,8 +467,8 @@ namespace System.Data.OracleClient.Oci ref value, definedSize, ociType, - ref indicator, - ref rlenp, + indicator, + rlenp, IntPtr.Zero, 0); @@ -487,6 +495,8 @@ namespace System.Data.OracleClient.Oci } disposed = true; } finally { + Marshal.FreeHGlobal (indicator); + Marshal.FreeHGlobal (rlenp); base.Dispose (disposing); value = IntPtr.Zero; } diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs index 6f11d970f0d..ef5eb270207 100644 --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleParameter.cs @@ -37,12 +37,13 @@ using System.Text; namespace System.Data.OracleClient { [TypeConverter (typeof(OracleParameter.OracleParameterConverter))] - public sealed class OracleParameter : + public sealed class OracleParameter : #if NET_2_0 - DbParameter, IDbDataParameter, ICloneable + DbParameter, IDbDataParameter, ICloneable, #else - MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable + MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable, #endif + IDisposable { #region Fields @@ -66,6 +67,7 @@ namespace System.Data.OracleClient object value = DBNull.Value; OciLobLocator lobLocator; // only if Blob or Clob IntPtr bindOutValue = IntPtr.Zero; + IntPtr indicator = IntPtr.Zero; OciDateTimeDescriptor dateTimeDesc; IntPtr cursor = IntPtr.Zero; @@ -77,7 +79,6 @@ namespace System.Data.OracleClient bool useRef; OciDataType bindType; - short indicator; int bindSize; bool sizeManuallySet; @@ -104,6 +105,7 @@ namespace System.Data.OracleClient this.value = value.value; this.lobLocator = value.lobLocator; this.oracleTypeSet = value.oracleTypeSet; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } public OracleParameter () @@ -119,6 +121,7 @@ namespace System.Data.OracleClient this.srcVersion = DataRowVersion.Current; this.value = null; this.oracleTypeSet = false; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } public OracleParameter (string name, object value) @@ -129,6 +132,7 @@ namespace System.Data.OracleClient srcColumn = string.Empty; SourceVersion = DataRowVersion.Current; InferOracleType (value); + this.indicator = OciCalls.AllocateClear (sizeof(short)); #if NET_2_0 // Find the OciType before inferring for the size if (value != null && value != DBNull.Value) { @@ -173,6 +177,7 @@ namespace System.Data.OracleClient OracleType = oracleType; SourceColumn = sourceColumn; SourceVersion = sourceVersion; + this.indicator = OciCalls.AllocateClear (sizeof(short)); } #endif @@ -199,6 +204,12 @@ namespace System.Data.OracleClient OracleType = oracleType; SourceColumn = srcColumn; SourceVersion = srcVersion; + this.indicator = OciCalls.AllocateClear (sizeof(short)); + } + + ~OracleParameter () + { + Dispose(false); } #endregion // Constructors @@ -210,6 +221,11 @@ namespace System.Data.OracleClient set { container = value; } } + internal short Indicator { + get { return (Marshal.ReadInt16(indicator)); } + set { Marshal.WriteInt16(indicator, value); } + } + #if !NET_2_0 [Browsable (false)] [RefreshProperties (RefreshProperties.All)] @@ -453,7 +469,6 @@ namespace System.Data.OracleClient } if (isnull == true && direction == ParameterDirection.Input) { - indicator = 0; bindType = OciDataType.VarChar2; bindSize = 0; } else { @@ -465,7 +480,6 @@ namespace System.Data.OracleClient case OciDataType.CharZ: case OciDataType.OciString: bindType = OciDataType.String; - indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -558,7 +572,7 @@ namespace System.Data.OracleClient dt = DateTime.MinValue; sDate = ""; if (isnull) - indicator = -1; + Indicator = -1; else if (v is String) { sDate = (string) v; dt = DateTime.Parse (sDate); @@ -594,7 +608,7 @@ namespace System.Data.OracleClient case OciDataType.Float: case OciDataType.Number: bindType = OciDataType.String; - indicator = 0; + Indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -638,7 +652,7 @@ namespace System.Data.OracleClient bindSize = Size + 5; // 4 bytes prepended for length, bytes, 1 byte NUL character - indicator = 0; + Indicator = 0; svalue = "\0"; // convert value from managed type to type to marshal if (direction == ParameterDirection.Input || @@ -758,7 +772,7 @@ namespace System.Data.OracleClient case OciDataType.VarRaw: bindType = OciDataType.VarRaw; bindSize = Size + 2; // include 2 bytes prepended to hold the length - indicator = 0; + Indicator = 0; bytes = new byte [bindSize]; if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) { @@ -784,7 +798,7 @@ namespace System.Data.OracleClient case OciDataType.LongVarRaw: bindType = OciDataType.LongVarRaw; bindSize = Size + 4; // include 4 bytes prepended to hold the length - indicator = 0; + Indicator = 0; bytes = new byte [bindSize]; if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) { @@ -854,7 +868,7 @@ namespace System.Data.OracleClient ref bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -870,7 +884,7 @@ namespace System.Data.OracleClient ref bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -887,7 +901,7 @@ namespace System.Data.OracleClient ref cursor, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -903,7 +917,7 @@ namespace System.Data.OracleClient bytes, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -919,7 +933,7 @@ namespace System.Data.OracleClient bindValue, bindSize, bindType, - ref indicator, + indicator, IntPtr.Zero, IntPtr.Zero, 0, @@ -1251,7 +1265,7 @@ namespace System.Data.OracleClient // used to update the parameter value // for Output, the output of InputOutput, and Return parameters value = DBNull.Value; - if (indicator == -1) + if (Indicator == -1) return; int rsize = 0; @@ -1453,6 +1467,22 @@ namespace System.Data.OracleClient return buffer; } + public void Dispose () + { + Dispose (true); + } + + void Dispose (bool disposing) + { + if (disposing) { + GC.SuppressFinalize(this); + } + if (indicator != IntPtr.Zero) { + Marshal.FreeHGlobal (indicator); + indicator = IntPtr.Zero; + } + } + #endregion // Methods internal sealed class OracleParameterConverter : ExpandableObjectConverter |