Bug #32061 The ODBC driver could mess up the client input buffer
Submitted: 2 Nov 2007 20:57 Modified: 29 May 2013 11:58
Reporter: John Water Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / ODBC Severity:S3 (Non-critical)
Version:3.51.21 OS:Windows (Win-XP)
Assigned to: CPU Architecture:Any
Tags: Input buffer, ODBC driver, SQLBindParameter

[2 Nov 2007 20:57] John Water
Description:
The MySQL ODBC driver 3.51.21 could mess up the client input buffer that is used to bind an input parameter.
The repro is trying to insert two rows into the table named test on MySQL.  After it ran, test contains two rows with the following data
mysql> select * from test;
+----+----------------+----------------+----------------+
| pk | c1             | c2             | c3             |
+----+----------------+----------------+----------------+
|  0 | the 2st string | the 2nd string | the 3rd string |
|  1 | ???4???        | ???????        | the 3rd string |
+----+----------------+----------------+----------------+
2 rows in set (0.00 sec)

This bug is not in the 5.01.00.00 ODBC driver.

How to repeat:
Here is the source code and a repro will be attached later in the zip file:

---------------------------------------------------------------------------
void ShowBug( p_odbc_conn conn )
/******************************/
{
    SQLHSTMT	stmt;
    RETCODE	ret;
    char *	drop	= "drop table test";
    char *	create	= "create table test( pk int primary key, c1 varchar(128), c2 varchar(128), c3 varchar(128) )";
    char *	insert	= "insert into test values( ?, ?, ?, ? )";

    SQLINTEGER	pk;
    wchar_t 	c1[500];
    wchar_t 	c2[500];
    wchar_t 	c3[500];
    SQLINTEGER	c1_ind;
    SQLINTEGER	c2_ind;
    SQLINTEGER	c3_ind;
    SQLINTEGER	c3_tmp;
    SQLPOINTER	ptr;

    c1_ind = ExpandStr( "the 2st string", c1 );
    c2_ind = ExpandStr( "the 2nd string", c2 );
    c3_ind = ExpandStr( "the 3rd string", c3 );
    c1[ c1_ind ] = '\0';
    c2[ c2_ind ] = '\0';
    c3[ c3_ind ] = '\0';
    c1_ind *= sizeof( wchar_t );
    c2_ind *= sizeof( wchar_t );
    c3_ind *= sizeof( wchar_t );

    ret = SQLAllocHandle( SQL_HANDLE_STMT, conn->dbc, &stmt );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLExecDirect( stmt, (SQLCHAR *)drop, SQL_NTS );

    ret = SQLExecDirect( stmt, (SQLCHAR *)create, SQL_NTS );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLEndTran( SQL_HANDLE_DBC, conn->dbc, SQL_COMMIT );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLFreeHandle( SQL_HANDLE_STMT, stmt );

    ret = SQLAllocHandle( SQL_HANDLE_STMT, conn->dbc, &stmt );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLPrepare( stmt, (SQLCHAR *)insert, SQL_NTS  );
    _c( conn->info->env, conn->dbc, stmt );
    
    ret = SQLBindParameter( stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
		    SQL_INTEGER, 0, 0, &pk, 0, NULL  );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLBindParameter( stmt, 2, SQL_PARAM_INPUT, SQL_C_WCHAR,
		    SQL_VARCHAR, 128, 0, (SQLWCHAR *)c1, 2, &c1_ind  );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLBindParameter( stmt, 3, SQL_PARAM_INPUT, SQL_C_WCHAR,
		    SQL_VARCHAR, 128, 0, (SQLWCHAR *)c2, 2, &c2_ind  );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLBindParameter( stmt, 4, SQL_PARAM_INPUT, SQL_C_WCHAR,
		    SQL_VARCHAR, 128, 0, (SQLWCHAR *)c3, 2, &c3_tmp  );
    _c( conn->info->env, conn->dbc, stmt );

    for( pk = 0; pk < 2; pk++ ) {
	c3_tmp = SQL_LEN_DATA_AT_EXEC( c3_ind );

	ret = SQLExecute( stmt );
	printf( "SQLExecute returns = %d\n", ret );
	if( ret == SQL_NEED_DATA ) {
	    ret = SQLParamData( stmt, &ptr );
	    printf( "SQLParamData returns = %d\n", ret );

	    ret = SQLPutData( stmt, c3, c3_ind );
	    printf( "SQLPutData returns = %d\n", ret );

	    ret = SQLParamData( stmt, &ptr );
	    printf( "SQLParamData returns = %d\n", ret );
	}
    }
    ret = SQLFreeHandle( SQL_HANDLE_STMT, stmt );

    ret = SQLEndTran( SQL_HANDLE_DBC, conn->dbc, SQL_COMMIT );
    _c( conn->info->env, conn->dbc, stmt );

done:
    return;
}
[7 Nov 2007 15:22] Susanne Ebrecht
Many thanks for writing a bug report.

Please, can you tell us, which character set and collation your tables have.
Also we need the trace file, to verify this.

MyODBC v3.51 doesn't support utf8, MyODBC v5.1 does.

Susanne
[15 Nov 2007 8:51] Tonci Grgin
John, MyODBC 3.51 does not support unicode (W) functions thus does not have proper SQL_C_WCHAR support. You may be able to get something that works out of it, but that will depend very much on the specifics of your platform, your table definitions, and probably some other factors. So please replace SQL_C_WCHAR with SQL_C_CHAR (and do other proper changes) according to http://msdn2.microsoft.com/en-us/library/ms709280.aspx and try again. 

Please inform me of result.
[16 Dec 2007 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[29 May 2013 11:58] Bogdan Degtyariov
I'm closing this bug because I can not continue without feedback from the reporter. If you have new info, please reopen the report.