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 [EMAIL PROTECTED] 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: [EMAIL PROTECTED] +ReportedBy: [EMAIL PROTECTED] +QAContact: [EMAIL PROTECTED] +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 ([EMAIL PROTECTED]) +--- +> // Brian Ritchie ([EMAIL PROTECTED]) +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: _______________________________________________ mono-bugs maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-bugs
