Hmm, I got confused in the last email and was looking at the other functions 
that use the indicator params before the previous patch was applied.  So of 
course they all looked broken.

While testing the patch you supplied, I found that it made no difference and 
looked deeper to see where the types were being confused.  

As it turns out, the most recent patch for this bug you sent will have no 
effect on the crash since the previous patch had changed some of the types 
from SQLINTEGER* to SQLLEN* in the results.c file as well as the odbcapi.c 
file.  As such, passing a SQLINTEGER* when the function will be expecting a 
SQLLEN* is just as wrong.

Then in order to figure out why the driver was corrupting memory, I discovered 
that even though the previous patch changed the copy_and_convert_field 
function to take an SQLLEN* as the parameter, it didn't modify the 
implementation of the function to get use the new type.

Attached is a patch that corrects the copy_and_convert_field function to use 
different casts as needed, and change the cbValueMax type to SQLLEN.

This patch works for me and was based on a side-by-side comparison with the 
8.02.200 version of the function which already implemented the proper 
handling.

There are a few little parts that didn't match up directly between the 2 
versions of the function, so getting someone else to sanity check it would be 
good.

In the process I also discovered another bug in our code that was causing 
similar problems.  Using either the included psqlodbc patch or fixing our 
calling code seems to avoid the specific crash I was seeing on 64 bit 
platforms.

As such, we are fixing our code internally, but the psqldriver is also buggy I 
believe.


-- 
Stephen Depooter
<[EMAIL PROTECTED]>
diff -ur psqlodbc-08.01.0200.orig/convert.c psqlodbc-08.01.0200/convert.c
--- psqlodbc-08.01.0200.orig/convert.c	2007-03-07 12:10:01.000000000 -0500
+++ psqlodbc-08.01.0200/convert.c	2007-03-07 12:10:17.000000000 -0500
@@ -379,14 +379,14 @@
 
 	SC_set_current_col(stmt, -1);
 	return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) (bic->buffer + offset),
-							 (SDWORD) bic->buflen, (bic->used + (offset >> 2)));
+							 bic->buflen, (bic->used + (offset >> 2)));
 }
 
 
 /*	This is called by SQLGetData() */
 int
 copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
-					   PTR rgbValue, SDWORD cbValueMax, SQLLEN *pcbValue)
+					   PTR rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue)
 {
 	CSTR func = "copy_and_convert_field";
 	ARDFields	*opts = SC_get_ARDF(stmt);
@@ -454,7 +454,7 @@
 		pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
 	else
 	{
-		pcbValueOffset = bind_row * sizeof(SDWORD);
+		pcbValueOffset = bind_row * sizeof(SQLLEN);
 		rgbValueOffset = bind_row * cbValueMax;
 	}
 	/*
@@ -486,7 +486,7 @@
 		 */
 		if (pcbValue)
 		{
-			*((SDWORD *) pcbValueBindRow) = SQL_NULL_DATA;
+			*((SQLLEN *) pcbValueBindRow) = SQL_NULL_DATA;
 			return COPY_OK;
 		}
 		else
@@ -663,7 +663,7 @@
 
 				/* There is no corresponding fCType for this. */
 				if (pcbValue)
-					*((SDWORD *) pcbValueBindRow) = len;
+					*((SQLLEN *) pcbValueBindRow) = len;
 
 				return COPY_OK; /* dont go any further or the data will be
 								 * trashed */
@@ -675,13 +675,13 @@
 			 */
 		case PG_TYPE_LO_UNDEFINED:
 
-			return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);
+			return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SQLLEN *) pcbValueBindRow);
 
 		default:
 
 			if (field_type == stmt->hdbc->lobj_type)	/* hack until permanent
 														 * type available */
-				return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);
+				return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SQLLEN *) pcbValueBindRow);
 	}
 
 	/* Change default into something useable */
@@ -956,13 +956,13 @@
 			{
 				char *str = strdup(rgbValueBindRow);
 				UInt4	ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / WCLEN);
-				if (cbValueMax < (SDWORD) (WCLEN * ucount))
+				if (cbValueMax < WCLEN * ucount)
 					result = COPY_RESULT_TRUNCATED;
 				free(str); 
 			}
 			else
 			{
-                if ((SDWORD) (len + WCLEN) <= cbValueMax)
+                if (len + WCLEN <= cbValueMax)
                 {
                     result = COPY_OK;
                 }
@@ -1263,7 +1263,7 @@
 					if (neut_str)
 						len = strlen(neut_str);
 					if (pcbValue)
-						*((SDWORD *) pcbValueBindRow) = len;
+						*((SQLLEN *) pcbValueBindRow) = len;
 					if (len > 0 && cbValueMax > 0)
 					{
 						memcpy(rgbValueBindRow, neut_str, len < cbValueMax ? len : cbValueMax);
@@ -1282,7 +1282,7 @@
 
 inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
 					if (pcbValue)
-						*((SDWORD *) pcbValueBindRow) = sizeof(ival);
+						*((SQLLEN *) pcbValueBindRow) = sizeof(ival);
 					if (cbValueMax >= sizeof(ival))
 					{
 						memcpy(rgbValueBindRow, &ival, sizeof(ival));
@@ -1381,7 +1381,7 @@
 
 	/* store the length of what was copied, if there's a place for it */
 	if (pcbValue)
-		*((SDWORD *) pcbValueBindRow) = len;
+		*((SQLLEN *) pcbValueBindRow) = len;
 
 	if (result == COPY_OK && stmt->current_col >= 0)
 		gdata->gdata[stmt->current_col].data_left = 0;
@@ -3873,7 +3873,7 @@
  */
 int
 convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
-		   SDWORD cbValueMax, SDWORD *pcbValue)
+		   SQLLEN cbValueMax, SQLLEN *pcbValue)
 {
 	Oid			oid;
 	int			retval,
diff -ur psqlodbc-08.01.0200.orig/convert.h psqlodbc-08.01.0200/convert.h
--- psqlodbc-08.01.0200.orig/convert.h	2007-03-07 12:10:01.000000000 -0500
+++ psqlodbc-08.01.0200/convert.h	2007-03-07 12:10:17.000000000 -0500
@@ -37,7 +37,7 @@
 
 int			copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col);
 int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
-					   PTR rgbValue, SDWORD cbValueMax, SQLLEN *pcbValue);
+					   PTR rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue);
 
 int		copy_statement_with_parameters(StatementClass *stmt, BOOL);
 BOOL		convert_money(const char *s, char *sout, size_t soutmax);
@@ -52,6 +52,6 @@
 void		encode(const char *in, char *out);
 void		decode(const char *in, char *out);
 int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
-		   SDWORD cbValueMax, SDWORD *pcbValue);
+		   SQLLEN cbValueMax, SQLLEN *pcbValue);
 
 #endif

Reply via email to