Bug #32684 ODBC driver crashes in SQLGetData with SQL_C_WCHAR
Submitted: 23 Nov 2007 21:52 Modified: 14 Feb 2008 17:33
Reporter: John Water
Status: Closed
Category:Connector/ODBC Severity:S2 (Serious)
Version:5.1 OS:Microsoft Windows (XP)
Assigned to: Bugs System Target Version:
Tags: wchar, SQLGetData, ODBC driver
Triage: D2 (Serious)

[23 Nov 2007 21: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 1:46] 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 2:08] 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
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
90123456789012345678901234567890123456789012345678
901234567890123456789012345678
SQLGetData: ret = 0, len = 1921, chunk = 2, buff =
90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
89012345678901234567890123456789012345678901234567
890123456789
no more data: chunks = 3
fetch completed!

C:\mysql-5.1.22-rc-win32>
[26 Nov 2007 2: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 16: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 21:15] Jess Balint
fix + test

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

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

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

[4 Feb 2008 20:05] Lawrin Novitsky
patch approved
[4 Feb 2008 20:43] Jess Balint
This patch has been committed as rev1015 and will be included in the 5.1.2 release.
[14 Feb 2008 17: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.