Bug #4183 mysql_stmt_fetch() fetches numbers in wrong byte order
Submitted: 17 Jun 2004 13:32 Modified: 1 Sep 2004 14:23
Reporter: Anthon Ouwendijk Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S1 (Critical)
Version:4.1.2 OS:HP/UX (HP-UX 11)
Assigned to: Konstantin Osipov CPU Architecture:Any

[17 Jun 2004 13:32] Anthon Ouwendijk
Description:
This happens when the C API for prepared statements is used.
A sample C source has been included.

A query like "SELECT 1"
returns wrong data: 16777216. The byte order is reversed.

"select help_topic_id from mysql.help_topic"
	>> works fine
"select help_topic_id + 0 from mysql.help_topic"
	>> returns data in reversed byte order
"select help_topic_id + 0 from mysql.help_topic order by 1"
	>> returns data in reversed byte order;
	>> the record order is on the original data, so correct.

How to repeat:
#include <stdlib.h>
#include <mysql.h>

typedef enum {
	BUG_UNKNOWN	= -1,	/* Error occurred */
	BUG_SOLVED	= 0,
	BUG_PRESENT	= 1,
} BugStatus;

char * str_bug_stat( BugStatus bugstat )
{
	if ( bugstat == BUG_PRESENT  ) {
		return "Bug still present";
	} else if ( bugstat == BUG_SOLVED ) {
		return "Bug solved";
	}
	return "Status UNKNOWN (or error occurred)";
}

BugStatus do_the_bug_test( MYSQL * mysql, char ** desc )
{
	MYSQL_STMT *	stmt;

	/* Bind data */
	MYSQL_BIND	bind[2];
	unsigned long	length[2];
	my_bool		is_null[2];
	int		int_data[2];

	char		query[64];
	int		rows = 0;

	*desc =
	"MySQL Bug Baan-040615	\"SELECT <expr>\" reverses the byte order\n"
	"			ok:	select col fetches col\n"
	"			err:	select col + 0 fetches reverse( col )\n"
	"			err:	select 0x01020304 fetches the literal 0x04030201\n";

	if ( !(stmt = mysql_stmt_init(mysql) ) ) {
		return BUG_UNKNOWN;
	}
	sprintf( query, "select help_topic_id, help_topic_id + 0 from mysql.help_topic order by 1" );

	if (mysql_stmt_prepare(stmt, query, strlen(query))) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	if (mysql_stmt_execute(stmt)) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	/* Bind the result buffers */

	bind[0].buffer_type= MYSQL_TYPE_LONG;
	bind[0].buffer= (char *)&int_data[0];
	bind[0].is_null= &is_null[0];
	bind[0].length= &length[0];

	bind[1].buffer_type= MYSQL_TYPE_LONG;
	bind[1].buffer= (char *)&int_data[1];
	bind[1].is_null= &is_null[1];
	bind[1].length= &length[1];

	if (mysql_stmt_bind_result(stmt, bind)) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	/* Fetch all rows */
	while (!mysql_stmt_fetch(stmt))
	{
		rows++;

		if (is_null[0] || is_null[1])
			return BUG_UNKNOWN;
			
		printf ( "id = %d, id+0 = %d", int_data[0], int_data[1] );

		if ( int_data[0] != int_data[1] ) {
			int swap_data;
			char * p = (char *) &swap_data;
			char c;

			swap_data = int_data[ 1 ];
			c = p[0]; p[0] = p[3]; p[3] = c;
			c = p[1]; p[1] = p[2]; p[2] = c;
			printf ( ", swapped %d\n", swap_data );

			if ( int_data[0] == swap_data ) {
				/* The data is equal after revering the byte order */
				return BUG_PRESENT;
			} else {
				/* Something unexpected */
				return BUG_UNKNOWN;
			}
		}
		printf( "\n" );
	}

	/* Close the statement */
	mysql_stmt_close(stmt);

	if ( rows ) {
		return BUG_SOLVED;
	} else {
		return BUG_UNKNOWN;
	}
}

main()
{
	MYSQL *		mysql = mysql_init( NULL );
	BugStatus	bugstat;
	char *		desc;

	/* Bind data */

	if ( ! mysql_real_connect( mysql,
					/* host */ NULL,
					/* user */ User,
					/* pwd */ Passwd,
					/* dbase */ Dbase, 

					/* uint port */ 0,
					/* char * socket */ NULL,
					/* client_flag */ 0 ) )
	{
		fprintf(stderr, " mysql_real_connec() failed\n");
		exit(0);
	}

	bugstat = do_the_bug_test( mysql, &desc );
	fprintf(stdout, "%s\n%s\n\n", desc, str_bug_stat( bugstat ) );

	return 0;
}
[23 Jun 2004 14:02] Michael Widenius
It's 95 % likely this problem is already fixed in 4.1.3. We will verify this ASAP and fix it if it isn't.

Regards,
Monty
[20 Jul 2004 5:30] Konstantin Osipov
We were recently fixing a lot of 64-bit related problems in prepared statements, 
and can't repeat this problem on the latest source tree.
Could you please check if the problem is still present, and if yes, reopen this bug?
[1 Sep 2004 14:23] Konstantin Osipov
I wasn't able to verify this bug.
As we were fixing byte ordering problems, and our own tests show that there is no such any more, I'm closing this bug.
Feel free to reopen it if you have additional info.

mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests> make
        cc -DUNDEF_THREADS_HACK -I. -I. -I.. -I../include      -O -DDBUG_OFF -g -z +O0 +DA2.0W +DD64   -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_BROKEN_INLINE -c 4183.c
cc: warning 454: Option O0 overrides previous setting of O2.
cc: warning 483: The DOC (Debug of Optimized Code) option is unavailable with the PA64 compiler; ignored.
        /bin/sh ../libtool --preserve-dup-deps --mode=link cc  -O -DDBUG_OFF -g -z +O0 +DA2.0W +DD64   -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_BROKEN_INLINE    -o 4183  4183.o ../libmysql/libmysqlclient.la  -lnsl -lm  ../zlib/libz.la 
cc -O -DDBUG_OFF -g -z +O0 +DA2.0W +DD64 -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_BROKEN_INLINE -o 4183 4183.o  ../libmysql/.libs/libmysqlclient.a -lpthread -lpthread ../zlib/.libs/libz.a -lpthread -lnsl -lm -lpthread
cc: warning 454: Option O0 overrides previous setting of O2.
mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests> ./4183 
MySQL Bug Baan-040615   "SELECT <expr>" reverses the byte order
                        ok:     select col fetches col
                        err:    select col + 0 fetches reverse( col )
                        err:    select 0x01020304 fetches the literal 0x04030201

Bug solved

mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests>
[1 Sep 2004 15:31] Konstantin Osipov
Update: after fixing some bugs in the test case (stack overflow in sprintf), and filling help table :), I was able to verify that the bug is indeed solved:

mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests> ./4183 
id = 0, id+0 = 0
id = 1, id+0 = 1
id = 2, id+0 = 2
id = 3, id+0 = 3
id = 4, id+0 = 4
id = 5, id+0 = 5
id = 6, id+0 = 6
id = 7, id+0 = 7
id = 8, id+0 = 8
id = 9, id+0 = 9
id = 10, id+0 = 10
id = 11, id+0 = 11
id = 12, id+0 = 12
id = 13, id+0 = 13
id = 14, id+0 = 14
id = 15, id+0 = 15
id = 16, id+0 = 16
id = 17, id+0 = 17
id = 18, id+0 = 18
id = 19, id+0 = 19
id = 20, id+0 = 20
id = 21, id+0 = 21
id = 22, id+0 = 22
id = 23, id+0 = 23
...
id = 384, id+0 = 384
id = 385, id+0 = 385
id = 386, id+0 = 386
id = 387, id+0 = 387
id = 388, id+0 = 388
id = 389, id+0 = 389
390
MySQL Bug Baan-040615   "SELECT <expr>" reverses the byte order
                        ok:     select col fetches col
                        err:    select col + 0 fetches reverse( col )
                        err:    select 0x01020304 fetches the literal 0x04030201

Bug solved