summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <evgen@moonbone.local>2007-08-14 17:28:51 +0400
committerunknown <evgen@moonbone.local>2007-08-14 17:28:51 +0400
commite34aa82da9eca8b219a88bc255938f2c7094567a (patch)
tree32bc0d58af9aa51dfc813bc4a8754b5e360483da
parent8277581b8952d0c3cde2069de1afbc8afbb9e3f2 (diff)
downloadmariadb-git-e34aa82da9eca8b219a88bc255938f2c7094567a.tar.gz
Bug#29948: Unchecked NULL pointer caused server crash.
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. tests/mysql_client_test.c: Added a test case for the bug#29948: Unchecked NULL pointer caused server crash. libmysql/libmysql.c: Bug#29948: Unchecked NULL pointer 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.
-rw-r--r--libmysql/libmysql.c10
-rw-r--r--tests/mysql_client_test.c75
2 files changed, 84 insertions, 1 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 1a0aae414ed..85c56a7ea40 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -4679,9 +4679,17 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
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 --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 75c86902972..ca76270d8b8 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -15735,6 +15735,80 @@ static void test_bug27592()
}
+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;
+
+ 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);
+
+ buf= CURSOR_TYPE_READ_ONLY;
+ res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&buf);
+ 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);
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -16019,6 +16093,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug28505", test_bug28505 },
{ "test_bug28934", test_bug28934 },
{ "test_bug27592", test_bug27592 },
+ { "test_bug29948", test_bug29948 },
{ 0, 0 }
};