[Mono-bugs] [Bug 75263][Nor] New - OdbcDataReader.cs bug in
GetPrimaryKeys() method
bugzilla-daemon at bugzilla.ximian.com
bugzilla-daemon at bugzilla.ximian.com
Tue Jun 14 12:30:31 EDT 2005
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by ndo at rockwellcollins.com.
http://bugzilla.ximian.com/show_bug.cgi?id=75263
--- shadow/75263 2005-06-14 12:30:31.000000000 -0400
+++ shadow/75263.tmp.4237 2005-06-14 12:30:31.000000000 -0400
@@ -0,0 +1,412 @@
+Bug#: 75263
+Product: Mono: Class Libraries
+Version: 1.0
+OS:
+OS Details: SuSE 9.2
+Status: NEW
+Resolution:
+Severity:
+Priority: Normal
+Component: Sys.Data
+AssignedTo: mono-bugs at ximian.com
+ReportedBy: ndo at rockwellcollins.com
+QAContact: mono-bugs at ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: OdbcDataReader.cs bug in GetPrimaryKeys() method
+
+Please fill in this template when reporting a bug, unless you know what
+you are doing.
+Description of Problem:
+
+The bug in GetPrimaryKeys() for the following scenario:
+
+1) A database table has a compound primary keys (two db columns make a row
+unique).
+2) Exercise Select query where the selected column in the query is not one
+of the primary key combination. There is only one column is selected in
+the query.
+3) The bug in the GetPrimaryKeys() was allocated the returned keys string
+array based on the number of returned columns in the Select statement up
+front. In this scenario, the returned column is one, and the number of
+primary keys in the table is two. The bug is in the while(true) section
+while retrieving the number of primary fields from backend database. On
+the second fetch of the second primary key, the keys[] array string crash
+since it only being allocated one slot at the beginning.
+4) attached is the diff -u of the OdbcDataReader.cs from tarball 1.1.7
+with the latest from svn (retrieved about 11am June 13th 05). The fix was
+not to make an assumption of keys[] string array to be allocated up front
+based on the returned columns of the Select statement. There is a local
+ArrayList object being introduced to dynamic add the primary keys fetched
+from backend database. As the completion of the fetch, then the ArrayList
+will convert and return an array of string. The signature of method
+doesn't change.
+5) here is the diff -u
+5c5
+< // Brian Ritchie (brianlritchie at hotmail.com)
+---
+> // Brian Ritchie (brianlritchie at hotmail.com)
+23c23
+< //
+---
+> //
+26c26
+< //
+---
+> //
+92c92
+< private CommandBehavior CommandBehavior
+---
+> private CommandBehavior CommandBehavior
+107c107
+< protected override bool IsValidRow
+---
+> protected override bool IsValidRow
+225,226c225,226
+< OdbcReturn
+ret=libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal+1),
+< colname_buffer, bufsize, ref
+colname_size, ref dt, ref ColSize,
+---
+> OdbcReturn
+ret=libodbc.SQLDescribeCol(hstmt, Convert.ToUInt16(ordinal+1),
+> colname_buffer, bufsize, ref
+colname_size, ref dt, ref ColSize,
+228c228
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+250c250
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+256,257c256,257
+< ret = libodbc.SQLFreeHandle( (ushort)
+OdbcHandleType.Stmt, hstmt);
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> ret = libodbc.SQLFreeHandle( (ushort)
+OdbcHandleType.Stmt, hstmt);
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+270c270
+< public
+---
+> public
+279c279
+< public
+---
+> public
+288c288
+< public
+---
+> public
+300c300
+< ret=libodbc.SQLGetData (hstmt, (ushort)
+(ordinal+1), SQL_C_TYPE.BINARY, tbuff, length,
+---
+> ret=libodbc.SQLGetData (hstmt, (ushort)
+(ordinal+1), SQL_C_TYPE.BINARY, tbuff, length,
+306c306
+< if ( (ret != OdbcReturn.Success) && (ret !=
+OdbcReturn.SuccessWithInfo))
+---
+> if ( (ret != OdbcReturn.Success) && (ret !=
+OdbcReturn.SuccessWithInfo))
+325c325
+< if (sqlstate !=
+libodbc.SQLSTATE_RIGHT_TRUNC)
+---
+> if (sqlstate !=
+libodbc.SQLSTATE_RIGHT_TRUNC)
+346c346
+< public
+---
+> public
+356c356
+< public
+---
+> public
+367c367
+< public
+---
+> public
+376c376
+< public
+---
+> public
+389c389
+< public
+---
+> public
+399c399
+< public
+---
+> public
+408c408
+< public
+---
+> public
+417c417
+< public
+---
+> public
+426c426
+< public
+---
+> public
+436c436
+< public
+---
+> public
+445c445
+< public
+---
+> public
+454c454
+< public
+---
+> public
+463c463
+< public
+---
+> public
+472c472
+< public
+---
+> public
+481c481
+< public
+---
+> public
+500c500
+< DataTable GetSchemaTable()
+---
+> DataTable GetSchemaTable()
+502c502
+< // FIXME :
+---
+> // FIXME :
+506c506
+< // * Cache this DataTable so that it is not
+contacting
+---
+> // * Cache this DataTable so that it is not
+contacting
+510c510
+< // Only Results from SQL SELECT Queries
+---
+> // Only Results from SQL SELECT Queries
+513c513
+< if(cols.Length > 0)
+---
+> if(cols.Length > 0)
+546c546
+< for (int i = 0; i < cols.Length; i += 1 )
+---
+> for (int i = 0; i < cols.Length; i += 1 )
+599c599
+< // FIXME: according to Brian,
+---
+> // FIXME: according to Brian,
+601c601
+< // however, we need it for Mono
+---
+> // however, we need it for Mono
+611c611
+< public
+---
+> public
+626c626
+< public
+---
+> public
+651a652
+> case OdbcType.Numeric:
+654,655c655
+< buffer=new
+byte[bufsize]; // According to sqlext.h, use SQL_CHAR for decima.
+< // 2005 03 10 : this now
+works with unixodbc with numeric c type.
+---
+> buffer=new
+byte[bufsize]; // According to sqlext.h, use SQL_CHAR for decimal.
+657,661c657,660
+< byte[] temp = new
+byte[outsize];
+< for (int
+i=0;i<outsize;i++)
+<
+temp[i]=buffer[i];
+<
+< if (outsize!=-1)
+---
+> if (outsize!=-1) {
+> byte[] temp = new
+byte[outsize];
+> for (int
+i=0;i<outsize;i++)
+>
+temp[i]=buffer[i];
+662a662
+> }
+716c716
+< if (outsize!=-1) // This
+means SQL_NULL_DATA
+---
+> if (outsize!=-1) // This
+means SQL_NULL_DATA
+739c739
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+742c742
+< if (outsize==-1) // This means
+SQL_NULL_DATA
+---
+> if (outsize==-1) // This means
+SQL_NULL_DATA
+750c750
+< public
+---
+> public
+823c823
+< }
+---
+> }
+854,855c854,855
+< ret = libodbc.SQLColAttribute (hstmt, column,
+fieldId,
+< buffer,
+buffer.Length,
+---
+> ret = libodbc.SQLColAttribute (hstmt, column,
+fieldId,
+> buffer,
+buffer.Length,
+872,873c872,873
+< ret = libodbc.SQLColAttribute (hstmt, column,
+fieldId,
+< buffer,
+buffer.Length,
+---
+> ret = libodbc.SQLColAttribute (hstmt, column,
+fieldId,
+> buffer,
+buffer.Length,
+891,892c891
+< //string [] keys = new string [cols.Length];
+< string [] keys = null;
+---
+> string [] keys = new string [cols.Length];
+894c893
+< OdbcReturn ret = OdbcReturn.Error;
+---
+> OdbcReturn ret = OdbcReturn.Error;
+896c895
+<
+ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
+---
+>
+ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt,
+898c897
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+906,907c905,906
+< ret = libodbc.SQLPrimaryKeys (handle,
+catalogName, -3,
+<
+schemaName, -3,
+---
+> ret = libodbc.SQLPrimaryKeys (handle,
+catalogName, -3,
+>
+schemaName, -3,
+919,922c918,919
+< //int i = 0;
+< ArrayList
+keysList = new ArrayList();
+<
+< while
+(true) {
+---
+> int i = 0;
+> while (true) {
+927,937c924,926
+<
+<
+ //keys
+[i++] = pkey;
+<
+keysList.Add(pkey);
+< }
+<
+<
+if(keysList.Count > 0) {
+<
+keys = new string[keysList.Count];
+<
+keysList.CopyTo(keys);
+< }
+<
+< } catch (OdbcException){
+---
+> keys [i++] = pkey;
+> }
+> } catch (OdbcException){
+940,941d928
+< if(keys ==
+null) keys = new string[0];
+<
+944c931
+< if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+---
+> if ((ret!=OdbcReturn.Success) &&
+(ret!=OdbcReturn.SuccessWithInfo))
+948c935
+< if
+((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
+---
+> if
+((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
+950c937
+< }
+---
+> }
+
+
+
+
+
+Steps to reproduce the problem:
+1. A database table has a compound primary keys (in this case, two
+database columns make a row unique).
+2. Create an OdbcConnection, OdbcCommand and OdbcDataReader using UnixODBC
+and MySQL-ODBC bridge to access MySQL database. Prepare a select statement
+with returned column is not one of the primary key combination. There is
+only column field retrieve in Select statement.
+3. Execute OdbcDataReader().
+
+Actual Results:
+keys[i++]=pkey on the second fetch causes keys[i++] overwrite memory since
+keys[] is only being allocated one at beginning of the method.
+
+Expected Results:
+
+
+How often does this happen?
+
+
+Additional Information:
More information about the mono-bugs
mailing list