From 07767edcce4709b42bae5d3d9ca7be9ceacb95da Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 28 Jun 2010 12:21:28 -0300 Subject: [PATCH 1/2] Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run The problem was that a user could supply supply data in chunks via the COM_STMT_SEND_LONG_DATA command to prepared statement parameter other than of type TEXT or BLOB. This posed a problem since other parameter types aren't setup to handle long data, which would lead to a crash when attempting to use the supplied data. Given that long data can be supplied at any stage of a prepared statement, coupled with the fact that the type of a parameter marker might change between consecutive executions, the solution is to validate at execution time each parameter marker for which a data stream was provided. If the parameter type is not TEXT or BLOB (that is, if the type is not able to handle a data stream), a error is returned. --- sql/sql_prepare.cc | 28 +++++++++++++++++++ tests/mysql_client_test.c | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 06f77f9689c..c2fecd63777 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -674,6 +674,18 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, } #ifndef EMBEDDED_LIBRARY + +/** + Check whether this parameter data type is compatible with long data. + Used to detect whether a long data stream has been supplied to a + incompatible data type. +*/ +inline bool is_param_long_data_type(Item_param *param) +{ + return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) && + (param->param_type <= MYSQL_TYPE_STRING)); +} + /* Routines to assign parameters from data supplied by the client. @@ -737,6 +749,14 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (!is_param_long_data_type(param)) + DBUG_RETURN(1); res= param->query_val_str(&str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -775,6 +795,14 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (is_param_long_data_type(param)) + DBUG_RETURN(1); if (param->convert_str_value(stmt->thd)) DBUG_RETURN(1); /* out of memory */ } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index b50c1efe92b..43a418c8300 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16757,6 +16757,63 @@ static void test_bug53907() } +/** + Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run +*/ + +static void test_bug54041() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind; + + DBUG_ENTER("test_bug54041"); + myheader("test_bug54041"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (a) VALUES (?)"); + check_stmt(stmt); + verify_param_count(stmt, 1); + + memset(&bind, 0, sizeof(bind)); + + /* Any type that does not support long data handling. */ + bind.buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_bind_param(stmt, &bind); + check_execute(stmt, rc); + + /* + Trick the client API into sending a long data packet for + the parameter. Long data is only supported for string and + binary types. + */ + stmt->params[0].buffer_type= MYSQL_TYPE_STRING; + + rc= mysql_stmt_send_long_data(stmt, 0, "data", 5); + check_execute(stmt, rc); + + /* Undo API violation. */ + stmt->params[0].buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_execute(stmt); + /* Incorrect arguments. */ + check_execute_r(stmt, rc); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -17062,6 +17119,7 @@ static struct my_tests_st my_tests[]= { { "test_bug45010", test_bug45010 }, { "test_bug53371", test_bug53371 }, { "test_bug53907", test_bug53907 }, + { "test_bug54041", test_bug54041 }, { 0, 0 } }; From 20cc561dfa143c090321b1c656672e5ac5600b5e Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 28 Jun 2010 16:20:28 -0300 Subject: [PATCH 2/2] Bug#54457: Test suite broken for 32-bit build The default value of the myisam_max_extra_sort_file_size could be higher than the maximum accepted value, leading to warnings upon the server start. The solution is to simply set the value to the maximum value in a 32-bit built (2147483647, one less than the current). This should be harmless as the option is currently unused in 5.1. --- include/myisam.h | 2 -- sql/mysqld.cc | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index 5334fd6afc4..e502daa2f17 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -55,8 +55,6 @@ extern "C" { #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ #define MI_NAME_IEXT ".MYI" #define MI_NAME_DEXT ".MYD" -/* Max extra space to use when sorting keys */ -#define MI_MAX_TEMP_LENGTH 2*1024L*1024L*1024L /* Possible values for myisam_block_size (must be power of 2) */ #define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index daa1bbe8ccc..adf9ff19326 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6928,7 +6928,7 @@ thread is in the relay logs.", "It will be removed in MySQL " VER_CELOSIA, &global_system_variables.myisam_max_extra_sort_file_size, &max_system_variables.myisam_max_extra_sort_file_size, - 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, + 0, GET_ULL, REQUIRED_ARG, (ulonglong) INT_MAX32, 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, "Don't use the fast sort index method to created index if the temporary "