Description:
The problem is that we don't check packet length of COM_EXECUTE packet.
Add +4 (zero) bytes to COM_EXECUTE packet right after statement id and the server will SIGSEGV
with the following diagnostics:
==20326== Use of uninitialised value of size 4
==20326== at 0x81B3FE6: insert_params(Prepared_statement*, unsigned char*, unsigned char*) (sql_prepare.cc:473)
==20326== by 0x81B411C: setup_params_data(Prepared_statement*) (sql_prepare.cc:506)
==20326== by 0x81B50BA: mysql_stmt_execute(THD*, char*) (sql_prepare.cc:1022)
==20326== by 0x816CE3B: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1364)
==20326== by 0x816C8C0: do_command(THD*) (sql_parse.cc:1223)
==20326== by 0x816BD95: handle_one_connection (sql_parse.cc:989)
==20326== by 0x4037A53E: thread_wrapper (vg_libpthread.c:667)
==20326== by 0x40177104: do__quit (vg_scheduler.c:2146)
==20326==
==20326== Thread 3:
==20326== Jump to the invalid address stated on the next line
==20326== at 0x0: ???
==20326== by 0x81B411C: setup_params_data(Prepared_statement*) (sql_prepare.cc:506)
==20326== by 0x81B50BA: mysql_stmt_execute(THD*, char*) (sql_prepare.cc:1022)
==20326== by 0x816CE3B: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1364)
==20326== by 0x816C8C0: do_command(THD*) (sql_parse.cc:1223)
==20326== by 0x816BD95: handle_one_connection (sql_parse.cc:989)
==20326== by 0x4037A53E: thread_wrapper (vg_libpthread.c:667)
The bug is not something rare: it will be easy the case when new (5.0 + cursors) client library will be used against old 4.1.1 and 5.0.0 servers.
How to repeat:
Patch client library with the following patch:
===== libmysql.c 1.203 vs edited =====
--- 1.203/libmysql/libmysql.c Tue Dec 23 18:46:55 2003
+++ edited/libmysql.c Sun Jan 4 15:05:53 2004
@@ -2004,14 +2004,15 @@
{
MYSQL *mysql= stmt->mysql;
NET *net= &mysql->net;
- char buff[MYSQL_STMT_HEADER];
+ char buff[8];
DBUG_ENTER("execute");
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
mysql->last_used_con= mysql;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
+ int4store(buff+4, 0);
if (cli_advanced_command(mysql, COM_EXECUTE, buff,
- MYSQL_STMT_HEADER, packet,
+ sizeof(buff), packet,
length, 1) ||
(*mysql->methods->read_query_result)(mysql))
{
And run client_test linked with patched libmysql against the server.
Suggested fix:
We need to overhaul COM_EXECUTE command processing from security standpoint.