From: Date: August 23 2007 8:38pm Subject: bk commit into 5.1 tree (gshchepa:1.2571) BUG#29948 List-Archive: http://lists.mysql.com/commits/32987 X-Bug: 29948 Message-Id: <20070823183851.4BD913D46B8@localhost.localdomain> Below is the list of changes that have just been committed into a local 5.1 repository of uchum. When uchum does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-08-23 23:38:43+05:00, gshchepa@stripped +2 -0 Bug#29948: Unchecked NULL pointer caused server crash. Recommit to 5.1.22. The cli_read_binary_rows function is used to fetch data from the server after a prepared statement execution. It accepts a statement handler and gets the connection handler from it. But when the auto-reconnect option is set the connection handler is reset to NULL after reconnection because the prepared statement is lost and the handler became useless. This case wasn't checked in the cli_read_binary_rows function and caused server crash. Now the cli_read_binary_rows function checks the connection handler to be not NULL and returns an error if it is. libmysql/libmysql.c@stripped, 2007-08-23 23:38:36+05:00, gshchepa@stripped +9 -1 Bug#29948: Unchecked NULL pointer caused server crash. Recommit to 5.1.22. Now the cli_read_binary_rows function checks the connection handler to be not NULL and returns an error if it is. tests/mysql_client_test.c@stripped, 2007-08-23 23:38:39+05:00, gshchepa@stripped +74 -73 Added a test case for the bug#29948: Unchecked NULL pointer caused server crash. Recommit to 5.1.22. diff -Nrup a/libmysql/libmysql.c b/libmysql/libmysql.c --- a/libmysql/libmysql.c 2007-08-13 18:11:09 +05:00 +++ b/libmysql/libmysql.c 2007-08-23 23:38:36 +05:00 @@ -4676,9 +4676,17 @@ int cli_read_binary_rows(MYSQL_STMT *stm MYSQL *mysql= stmt->mysql; MYSQL_DATA *result= &stmt->result; MYSQL_ROWS *cur, **prev_ptr= &result->data; - NET *net = &mysql->net; + NET *net; + + if (!mysql) + { + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + return 1; + } + DBUG_ENTER("cli_read_binary_rows"); + net = &mysql->net; mysql= mysql->last_used_con; while ((pkt_len= cli_safe_read(mysql)) != packet_error) diff -Nrup a/tests/mysql_client_test.c b/tests/mysql_client_test.c --- a/tests/mysql_client_test.c 2007-08-23 22:30:01 +05:00 +++ b/tests/mysql_client_test.c 2007-08-23 23:38:39 +05:00 @@ -15690,6 +15690,80 @@ static void test_mysql_insert_id() myquery(rc); } +static void test_bug29948() +{ + MYSQL *dbc=NULL; + MYSQL_STMT *stmt=NULL; + MYSQL_BIND bind; + + int res=0; + my_bool auto_reconnect=1, error=0, is_null=0; + char kill_buf[20]; + const char *query; + int buf; + unsigned long length, cursor_type; + + dbc = mysql_init(NULL); + DIE_UNLESS(dbc); + + mysql_options(dbc, MYSQL_OPT_RECONNECT, (char*)&auto_reconnect); + if (!mysql_real_connect(dbc, opt_host, opt_user, + opt_password, current_db, opt_port, + opt_unix_socket, + (CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS | + CLIENT_MULTI_RESULTS))) + { + printf("connection failed: %s (%d)", mysql_error(dbc), + mysql_errno(dbc)); + exit(1); + } + + bind.buffer_type= MYSQL_TYPE_LONG; + bind.buffer= (char *)&buf; + bind.is_null= &is_null; + bind.error= &error; + bind.length= &length; + + res= mysql_query(dbc, "DROP TABLE IF EXISTS t1"); + myquery(res); + res= mysql_query(dbc, "CREATE TABLE t1 (a INT)"); + myquery(res); + res= mysql_query(dbc, "INSERT INTO t1 VALUES(1)"); + myquery(res); + + stmt= mysql_stmt_init(dbc); + check_stmt(stmt); + + cursor_type= CURSOR_TYPE_READ_ONLY; + res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&cursor_type); + myquery(res); + + query= "SELECT * from t1 where a=?"; + res= mysql_stmt_prepare(stmt, query, strlen(query)); + myquery(res); + + res= mysql_stmt_bind_param(stmt, &bind); + myquery(res); + + res= mysql_stmt_execute(stmt); + check_execute(stmt, res); + + res= mysql_stmt_bind_result(stmt,&bind); + check_execute(stmt, res); + + sprintf(kill_buf, "kill %ld", dbc->thread_id); + mysql_query(dbc, kill_buf); + + res= mysql_stmt_store_result(stmt); + DIE_UNLESS(res); + + mysql_stmt_free_result(stmt); + mysql_stmt_close(stmt); + mysql_query(dbc, "DROP TABLE t1"); + mysql_close(dbc); +} + + /* Bug#20152: mysql_stmt_execute() writes to MYSQL_TYPE_DATE buffer */ @@ -16265,79 +16339,6 @@ static void test_bug27592() mysql_stmt_close(stmt); DBUG_VOID_RETURN; -} - -static void test_bug29948() -{ - MYSQL *dbc=NULL; - MYSQL_STMT *stmt=NULL; - MYSQL_BIND bind; - - int res=0; - my_bool auto_reconnect=1, error=0, is_null=0; - char kill_buf[20]; - const char *query; - int buf; - unsigned long length, cursor_type; - - dbc = mysql_init(NULL); - DIE_UNLESS(dbc); - - mysql_options(dbc, MYSQL_OPT_RECONNECT, (char*)&auto_reconnect); - if (!mysql_real_connect(dbc, opt_host, opt_user, - opt_password, current_db, opt_port, - opt_unix_socket, - (CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS | - CLIENT_MULTI_RESULTS))) - { - printf("connection failed: %s (%d)", mysql_error(dbc), - mysql_errno(dbc)); - exit(1); - } - - bind.buffer_type= MYSQL_TYPE_LONG; - bind.buffer= (char *)&buf; - bind.is_null= &is_null; - bind.error= &error; - bind.length= &length; - - res= mysql_query(dbc, "DROP TABLE IF EXISTS t1"); - myquery(res); - res= mysql_query(dbc, "CREATE TABLE t1 (a INT)"); - myquery(res); - res= mysql_query(dbc, "INSERT INTO t1 VALUES(1)"); - myquery(res); - - stmt= mysql_stmt_init(dbc); - check_stmt(stmt); - - cursor_type= CURSOR_TYPE_READ_ONLY; - res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&cursor_type); - myquery(res); - - query= "SELECT * from t1 where a=?"; - res= mysql_stmt_prepare(stmt, query, strlen(query)); - myquery(res); - - res= mysql_stmt_bind_param(stmt, &bind); - myquery(res); - - res= mysql_stmt_execute(stmt); - check_execute(stmt, res); - - res= mysql_stmt_bind_result(stmt,&bind); - check_execute(stmt, res); - - sprintf(kill_buf, "kill %ld", dbc->thread_id); - mysql_query(dbc, kill_buf); - - res= mysql_stmt_store_result(stmt); - DIE_UNLESS(res); - - mysql_stmt_free_result(stmt); - mysql_stmt_close(stmt); - mysql_query(dbc, "DROP TABLE t1"); - mysql_close(dbc); }