[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