Bug #16300 inserting with bind values makes assumptions about long size
Submitted: 9 Jan 2006 13:12 Modified: 8 Mar 2007 1:31
Reporter: tom hindle Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Connector / ODBC Severity:S2 (Serious)
Version:3.51.12 OS:IBM AIX (aix 5.2 64bit)
Assigned to: CPU Architecture:Any

[9 Jan 2006 13:12] tom hindle
Description:
inserting with bind values makes assumptions about long size

On a 64bit systems the long int type is 8 bytes.

SQLBindParameter has previous been called with a cbValueMax value of 4 and type of SQL_C_SLONG, it corretly stores this value in param

However in driver/execute.c about line 375:
case SQL_C_SLONG
length=int2str(*(long int *)data),buff,-10,0) -buff;

this cbValueMax is ignored, and the assumption made that SQL_C_SLONG is sizeof(long) which happens to work on 32bit systems.

How to repeat:
Here is a trace of what my testcase did. Just do this on a 64 bit system then select the inserted values too see the error.

Application     00000000 EXIT  SQLBindParameter with return code 0 (SQL_SUCCESS)                SQLHSTMT          1100899f0
                SQLSMALLINT       1
                SQLSMALLINT       1 (SQL_PARAM_INPUT)
                SQLSMALLINT       -16 (SQL_C_SLONG)
                SQLSMALLINT       4 (SQL_INTEGER)
                SQLUINTEGER       4
                SQLSMALLINT       0
                SQLPOINTER        ffffffffffffd2c
                SQLINTEGER        4
                SQLPOINTER        110089878

Application     00000000 ENTER SQLBindParameter
                SQLHSTMT          1100899f0
                SQLSMALLINT       2
                SQLSMALLINT       1 (SQL_PARAM_INPUT)
                SQLSMALLINT       -16 (SQL_C_SLONG)
                SQLSMALLINT       4 (SQL_INTEGER)
                SQLUINTEGER       4
                SQLSMALLINT       0
                SQLPOINTER        ffffffffffffd2c
                SQLINTEGER        4
                SQLPOINTER        1100898a0

Application     00000000 EXIT  SQLBindParameter with return code 0 (SQL_SUCCESS)                SQLHSTMT          1100899f0
                SQLSMALLINT       2
                SQLSMALLINT       1 (SQL_PARAM_INPUT)
                SQLSMALLINT       -16 (SQL_C_SLONG)
                SQLSMALLINT       4 (SQL_INTEGER)
                SQLUINTEGER       4
                SQLSMALLINT       0
                SQLPOINTER        ffffffffffffd2c
                SQLINTEGER        4
                SQLPOINTER        1100898a0

Application     00000000 ENTER SQLSetStmtOption
                SQLHSTMT          1100899f0
                SQLUSMALLINT      0 (SQL_QUERY_TIMEOUT)
                SQLUINTEGER       0

Application     00000000 EXIT  SQLSetStmtOption with return code 0 (SQL_SUCCESS)                SQLHSTMT          1100899f0
                SQLUSMALLINT      0 (SQL_QUERY_TIMEOUT)
                SQLUINTEGER       0

Application     00000000 ENTER SQLExecDirect
                SQLHSTMT          1100899f0
                SQLCHAR         * 11008b860
                                  | INSERT  INTO integer1 (a  , b ) VALUES ( |
                                  |   ? ,  ? )                               |
                SQLINTEGER        51

Application     00000000 EXIT  SQLExecDirect with return code 0 (SQL_SUCCESS)
                SQLHSTMT          1100899f0
                SQLCHAR         * 11008b860
                SQLINTEGER        51

Suggested fix:
I changed:
length=int2str(*(long int *)data),buff,-10,0) -buff;
to:
length=int2str(*(int *)data),buff,-10,0) -buff;

which works for me but not the best way to fix this.

really need to check cbValueMax when ever conversions are done between Integer types and strings.
[27 Jul 2006 11:30] tom hindle
Futher to my previous comments:

A better change would be (if you want to be able to deal with 8 bits long's)

length=int2str(getlong(data,cbValueMax),buff,-10,0) - buff;

where getlong defined as:

#define BITS 8
long getlong(void * data,int size) {
 long  val=0;
 unsigned char * cptr=(char *)ptr;
 int i= size>sizeof(long)?sizeof(long):size;

 for (i=size-1;i>=0;i--) {
   val += (cptr[i] << (size-(size-i))*BITS);
 }

 return(val);
}
[28 Aug 2006 20:42] Sveta Smirnova
test case to recreate the error

Attachment: bug16300.c (text/x-csrc), 1.64 KiB.

[28 Aug 2006 20:46] Sveta Smirnova
Thank you for the report.

Verified as described on SuSe Linux using attached test case:

ssmirnova@sles9-ia64:~> ./bug16300
 Connecting to 'myodbc3' with user name 'root'...
bug16300(11692): unaligned access to 0x60000fffffffadec, ip=0x2000000000062bd0
[8 Mar 2007 1:31] Jim Winstead
cbValueMax should be ignored, as you can't specify the size of a SQL_C_LONG (it's always an SQLINTEGER).