Bug #32684 ODBC driver crashes in SQLGetData with SQL_C_WCHAR
Submitted: 23 Nov 2007 20:52 Modified: 14 Feb 2008 16:33
Reporter: John Water Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / ODBC Severity:S2 (Serious)
Version:5.1 OS:Microsoft Windows (XP)
Assigned to: Jess Balint
Tags: ODBC driver, SQLGetData, wchar
Triage: D2 (Serious)

[23 Nov 2007 20:52] John Water
Description:
The MyODBC driver 5.01.00.00 crashes in SQLGetData when fetching a text blob with length >= 5120 from the MySQL server 5.1.22 database, if the target type is SQL_C_WCHAR.

How to repeat:
The executable, source code, ODBC tracing file will be attached.  To reproduce this problem,
1) unzip the zip file;
2) command window, issue
odbcbug "dsn=your_dsn;uid=your_uid;pwd=your_pwd"
then you'll see the driver will crash.

Here is the main function of the source code of the repro:

void ShowBug( p_odbc_conn conn )
/******************************/
{
    SQLHSTMT	stmt;
    RETCODE	ret;

    char *	drop_table	= "drop table test";
    char *	create_table	= "create table test (pk int primary key, c1 mediumtext)";
    char *	insert_stmt	= "insert into test values( 1, '0123456789' )";
    char *	update_stmt	= "update test set c1 = concat( c1, c1 ) where pk = 1";
    char *	select_table	= "select pk, c1 from test";

    SQLINTEGER	pk;
    SQLINTEGER	pk_ind;
    wchar_t	buff[3200];
    char	tmp[3200];
    SQLLEN	len;
    int		rows	= 1;
    int		chunks	= 1;

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

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

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

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

    for( int i = 0; i < 9; i++ ) {
	ret = SQLExecDirect( stmt, (SQLCHAR *) update_stmt, 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 *)select_table, SQL_NTS  );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLExecute( stmt );
    _c( conn->info->env, conn->dbc, stmt );

    ret = SQLBindCol( stmt, 1, SQL_C_SLONG, &pk, sizeof( pk ), &pk_ind );
    _c( conn->info->env, conn->dbc, stmt );

    while( TRUE ) {
	ret = SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 );
	if( ret == SQL_NO_DATA ) {
	    printf( "fetch completed!\n" );
	    break;
	}
	printf( "SQLFetch: ret = %d: row = %d, pk = %d, ind = %d\n", ret, rows, pk, pk_ind );
	_c( conn->info->env, conn->dbc, stmt );
    
	while( TRUE ) {
	    ret = SQLGetData( stmt, 2, SQL_C_WCHAR, buff,
				    sizeof( buff ), &len );
	    if( ret != SQL_SUCCESS &&
		ret != SQL_SUCCESS_WITH_INFO &&
		ret != SQL_NO_DATA ) {
		printf( "break out\n" );
		break;
	    } else {
		if( ret == SQL_NO_DATA || len == 0 ) {
		    printf( "no more data: chunks = %ld\n", chunks );
		    break;
		} else if( len == SQL_NULL_DATA ) {
		    printf( "null data\n" );
		    break;
		} else {
		    ShrinkStr( buff, tmp );
		    printf( "SQLGetData: ret = %d, len = %d, chunk = %d, buff = %s\n",
			    ret, len / sizeof( wchar_t ), chunks, tmp );
		    if( len == SQL_NO_TOTAL ) {
		    } else {
		    }
		}
	    }
	    chunks++;
	}
	rows++;
    }

    ret = SQLFreeHandle( SQL_HANDLE_STMT, stmt );

done:
    return;
}
[24 Nov 2007 0:46] Godofredo Miguel Solorzano
Thank you for the bug report and test case. Could you please test with
Connector/ODBC 5.1 version, I wasn't able to get the crash, below the
output I got:

C:\mysql-5.1.22-rc-win32>bin\mysql -uroot test
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.22-rc-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> grant all on *.* to "miguel"@"localhost" identified by "miguel";
Query OK, 0 rows affected (0.05 sec)

mysql> exit
Bye

C:\mysql-5.1.22-rc-win32>c:\temp\odbcbug "dsn=mydsn;uid=miguel;pwd=miguel"
SQLFetch: ret = 0: row = 1, pk = 1, ind = 4

C:\mysql-5.1.22-rc-win32>

Thanks in advance.
[24 Nov 2007 1:08] Godofredo Miguel Solorzano
Ok..now I tested against the driver 3.51 and I got the correct result, so I
didn't see a crash. Below the output of 3.51 driver:

C:\mysql-5.1.22-rc-win32>c:\temp\odbcbug "dsn=mydsn2;uid=miguel;pwd=miguel"
SQLFetch: ret = 0: row = 1, pk = 1, ind = 4
SQLGetData: ret = 1, len = 5120, chunk = 1, buff = 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
901234567890123456789012345678
SQLGetData: ret = 0, len = 1921, chunk = 2, buff = 90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
890123456789
no more data: chunks = 3
fetch completed!

C:\mysql-5.1.22-rc-win32>
[26 Nov 2007 1:00] John Water
Thank you taking a look at this crash.

When you run the repro, you have see the following two lines only:

>C:\mysql-5.1.22-rc-win32>c:\temp\odbcbug "dsn=mydsn;uid=miguel;pwd=miguel"
>SQLFetch: ret = 0: row = 1, pk = 1, ind = 4

because the repro crashed!  If you run the repro with odbc tracing, the tacing file shows
             ENTER SQLGetData
but there is no
             EXIT SQLGetData
There is no problem in the MyODBC 3.51.21.  If you run the repro with 3.51.21, it will show you the data in the column c1 ad you have seen it.

Thanks again!
[17 Dec 2007 15:39] John Water
I have seen the 5.01 beta, but it did not fix this problem.  I believe no one can use this driver if their applications use BLOBs.
Some one please give me an update?
Thanks.
[4 Jan 2008 20:15] Jess Balint
fix + test

Attachment: bug32684.diff (application/octet-stream, text), 2.52 KiB.

[8 Jan 2008 22:49] Jess Balint
updated patch, fix 4-byte SQLWCHAR (iodbc)

Attachment: bug32684.diff (application/octet-stream, text), 2.49 KiB.

[4 Feb 2008 19:05] Lawrenty Novitsky
patch approved
[4 Feb 2008 19:43] Jess Balint
This patch has been committed as rev1015 and will be included in the 5.1.2 release.
[14 Feb 2008 16:33] MC Brown
A note has been added to the 5.1.2 changelog: 

Retrieving data from a BLOG column would fail within SQLGetDatawhen the target data type was SQL_C_WCHAR due to incorrect handling of the character buffer.