From: Dmitry Shulga Date: March 14 2011 3:21pm Subject: bzr commit into mysql-5.5 branch (Dmitry.Shulga:3362) Bug#11764168 List-Archive: http://lists.mysql.com/commits/132920 X-Bug: 11764168 Message-Id: <201103141521.p2EFLJbI015374@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8635223634703594935==" --===============8635223634703594935== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/mysql-5.5/ based on revid:marc.alff@stripped 3362 Dmitry Shulga 2011-03-14 [merge] Manual merge from mysql-5.1 for Bug#11764168 (56976: Severe denial of service in prepared statements). @ sql/sql_prepare.cc At mysql_stmt_get_longdata(): instead of pushing an internal error handler (as done in 5.1-tree) we save, set and restore the statement's diagnostics area and warning info. added: mysql-test/suite/sys_vars/r/max_long_data_size_basic.result mysql-test/suite/sys_vars/t/max_long_data_size_basic.test modified: mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqld--help-win.result mysql-test/r/variables.result mysql-test/t/variables.test sql/item.cc sql/mysqld.cc sql/mysqld.h sql/sql_prepare.cc sql/sys_vars.cc tests/mysql_client_test.c === modified file 'mysql-test/r/mysqld--help-notwin.result' --- a/mysql-test/r/mysqld--help-notwin.result 2011-01-14 13:21:46 +0000 +++ b/mysql-test/r/mysqld--help-notwin.result 2011-03-14 15:19:44 +0000 @@ -309,6 +309,10 @@ The following options may be given as th max_join_size records return an error --max-length-for-sort-data=# Max number of bytes in sorted records + --max-long-data-size=# + The maximum BLOB length to send to server from + mysql_send_long_data API. Deprecated option; use + max_allowed_packet instead. --max-prepared-stmt-count=# Maximum number of prepared statements in the server --max-relay-log-size=# @@ -830,6 +834,7 @@ max-error-count 64 max-heap-table-size 16777216 max-join-size 18446744073709551615 max-length-for-sort-data 1024 +max-long-data-size 1048576 max-prepared-stmt-count 16382 max-relay-log-size 0 max-seeks-for-key 18446744073709551615 === modified file 'mysql-test/r/mysqld--help-win.result' --- a/mysql-test/r/mysqld--help-win.result 2011-01-14 13:21:46 +0000 +++ b/mysql-test/r/mysqld--help-win.result 2011-03-14 15:19:44 +0000 @@ -308,6 +308,10 @@ The following options may be given as th max_join_size records return an error --max-length-for-sort-data=# Max number of bytes in sorted records + --max-long-data-size=# + The maximum BLOB length to send to server from + mysql_send_long_data API. Deprecated option; use + max_allowed_packet instead. --max-prepared-stmt-count=# Maximum number of prepared statements in the server --max-relay-log-size=# @@ -833,6 +837,7 @@ max-error-count 64 max-heap-table-size 16777216 max-join-size 18446744073709551615 max-length-for-sort-data 1024 +max-long-data-size 1048576 max-prepared-stmt-count 16382 max-relay-log-size 0 max-seeks-for-key 18446744073709551615 === modified file 'mysql-test/r/variables.result' --- a/mysql-test/r/variables.result 2011-02-10 07:34:22 +0000 +++ b/mysql-test/r/variables.result 2011-03-14 15:19:44 +0000 @@ -1540,6 +1540,9 @@ ERROR HY000: Cannot drop default keycach SET @@global.key_cache_block_size=0; Warnings: Warning 1292 Truncated incorrect key_cache_block_size value: '0' +select @@max_long_data_size; +@@max_long_data_size +1048576 SET @@global.max_binlog_cache_size=DEFAULT; SET @@global.max_join_size=DEFAULT; SET @@global.key_buffer_size=@kbs; === added file 'mysql-test/suite/sys_vars/r/max_long_data_size_basic.result' --- a/mysql-test/suite/sys_vars/r/max_long_data_size_basic.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/sys_vars/r/max_long_data_size_basic.result 2011-03-14 15:19:44 +0000 @@ -0,0 +1,14 @@ +select @@global.max_long_data_size=20; +@@global.max_long_data_size=20 +0 +select @@session.max_long_data_size; +ERROR HY000: Variable 'max_long_data_size' is a GLOBAL variable +SELECT @@global.max_long_data_size = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='max_long_data_size'; +@@global.max_long_data_size = VARIABLE_VALUE +1 +set global max_long_data_size=1; +ERROR HY000: Variable 'max_long_data_size' is a read only variable +set session max_long_data_size=1; +ERROR HY000: Variable 'max_long_data_size' is a read only variable === added file 'mysql-test/suite/sys_vars/t/max_long_data_size_basic.test' --- a/mysql-test/suite/sys_vars/t/max_long_data_size_basic.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/sys_vars/t/max_long_data_size_basic.test 2011-03-14 15:19:44 +0000 @@ -0,0 +1,17 @@ +select @@global.max_long_data_size=20; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.max_long_data_size; + +# Show that value of the variable matches the value in the GLOBAL I_S table +SELECT @@global.max_long_data_size = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='max_long_data_size'; + +# +# show that it's read-only +# +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +set global max_long_data_size=1; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +set session max_long_data_size=1; + === modified file 'mysql-test/t/variables.test' --- a/mysql-test/t/variables.test 2011-02-10 07:34:22 +0000 +++ b/mysql-test/t/variables.test 2011-03-14 15:19:44 +0000 @@ -1281,6 +1281,11 @@ SET @@global.max_join_size=0; SET @@global.key_buffer_size=0; SET @@global.key_cache_block_size=0; +# +# Bug#56976: added new start-up parameter +# +select @@max_long_data_size; + # cleanup SET @@global.max_binlog_cache_size=DEFAULT; SET @@global.max_join_size=DEFAULT; === modified file 'sql/item.cc' --- a/sql/item.cc 2011-03-04 15:43:28 +0000 +++ b/sql/item.cc 2011-03-14 15:19:44 +0000 @@ -2885,6 +2885,17 @@ bool Item_param::set_longdata(const char (here), and first have to concatenate all pieces together, write query to the binary log and only then perform conversion. */ + + if (str_value.length() + length > max_long_data_size) + { + my_message(ER_UNKNOWN_ERROR, + "Parameter of prepared statement which is set through " + "mysql_send_long_data() is longer than " + "'max_long_data_size' bytes", + MYF(0)); + DBUG_RETURN(true); + } + if (str_value.append(str, length, &my_charset_bin)) DBUG_RETURN(TRUE); state= LONG_DATA_VALUE; === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2011-03-10 08:43:55 +0000 +++ b/sql/mysqld.cc 2011-03-14 15:19:44 +0000 @@ -324,6 +324,7 @@ static PSI_rwlock_key key_rwlock_openssl /* the default log output is log tables */ static bool lower_case_table_names_used= 0; +static bool max_long_data_size_used= false; static bool volatile select_thread_in_use, signal_thread_in_use; /* See Bug#56666 and Bug#56760 */; volatile bool ready_to_exit; @@ -478,6 +479,11 @@ ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong max_connections, max_connect_errors; +/* + Maximum length of parameter value which can be set through + mysql_send_long_data() call. +*/ +ulong max_long_data_size; /** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. @@ -7155,6 +7161,10 @@ mysqld_get_one_option(int optid, if (argument == NULL) /* no argument */ log_error_file_ptr= const_cast(""); break; + case OPT_MAX_LONG_DATA_SIZE: + max_long_data_size_used= true; + WARN_DEPRECATED(NULL, 5, 6, "--max_long_data_size", "'--max_allowed_packet'"); + break; } return 0; } @@ -7381,6 +7391,13 @@ static int get_options(int *argc_ptr, ch opt_readonly= read_only; + /* + If max_long_data_size is not specified explicitly use + value of max_allowed_packet. + */ + if (!max_long_data_size_used) + max_long_data_size= global_system_variables.max_allowed_packet; + return 0; } === modified file 'sql/mysqld.h' --- a/sql/mysqld.h 2011-03-10 08:43:55 +0000 +++ b/sql/mysqld.h 2011-03-14 15:19:44 +0000 @@ -126,6 +126,7 @@ extern char *default_storage_engine; extern bool opt_endinfo, using_udf_functions; extern my_bool locked_in_memory; extern bool opt_using_transactions; +extern ulong max_long_data_size; extern ulong current_pid; extern ulong expire_logs_days; extern my_bool relay_log_recovery; @@ -397,7 +398,8 @@ enum options_mysqld OPT_UPDATE_LOG, OPT_WANT_CORE, OPT_ENGINE_CONDITION_PUSHDOWN, - OPT_LOG_ERROR + OPT_LOG_ERROR, + OPT_MAX_LONG_DATA_SIZE }; === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2011-03-01 14:42:37 +0000 +++ b/sql/sql_prepare.cc 2011-03-14 15:19:44 +0000 @@ -2784,6 +2784,7 @@ void mysql_sql_stmt_close(THD *thd) } } + /** Handle long data in pieces from client. @@ -2840,17 +2841,25 @@ void mysql_stmt_get_longdata(THD *thd, c param= stmt->param_array[param_number]; + Diagnostics_area new_stmt_da, *save_stmt_da= thd->stmt_da; + Warning_info new_warnning_info(thd->query_id), *save_warinig_info= thd->warning_info; + + thd->stmt_da= &new_stmt_da; + thd->warning_info= &new_warnning_info; + #ifndef EMBEDDED_LIBRARY - if (param->set_longdata(packet, (ulong) (packet_end - packet))) + param->set_longdata(packet, (ulong) (packet_end - packet)); #else - if (param->set_longdata(thd->extra_data, thd->extra_length)) + param->set_longdata(thd->extra_data, thd->extra_length); #endif + if (thd->stmt_da->is_error()) { stmt->state= Query_arena::ERROR; - stmt->last_errno= ER_OUTOFMEMORY; - sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); + stmt->last_errno= thd->stmt_da->sql_errno(); + strncpy(stmt->last_error, thd->stmt_da->message(), MYSQL_ERRMSG_SIZE); } - + thd->stmt_da= save_stmt_da; + thd->warning_info= save_warinig_info; general_log_print(thd, thd->command, NullS); DBUG_VOID_RETURN; @@ -3389,6 +3398,13 @@ Prepared_statement::execute_loop(String bool error; int reprepare_attempt= 0; + /* Check if we got an error when sending long data */ + if (state == Query_arena::ERROR) + { + my_message(last_errno, last_error, MYF(0)); + return TRUE; + } + if (set_parameters(expanded_query, packet, packet_end)) return TRUE; @@ -3656,12 +3672,6 @@ bool Prepared_statement::execute(String status_var_increment(thd->status_var.com_stmt_execute); - /* Check if we got an error when sending long data */ - if (state == Query_arena::ERROR) - { - my_message(last_errno, last_error, MYF(0)); - return TRUE; - } if (flags & (uint) IS_IN_USE) { my_error(ER_PS_NO_RECURSION, MYF(0)); === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2011-02-17 11:53:09 +0000 +++ b/sql/sys_vars.cc 2011-03-14 15:19:44 +0000 @@ -1182,6 +1182,16 @@ static Sys_var_harows Sys_sql_max_join_s NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_max_join_size), DEPRECATED(70000, 0)); +static Sys_var_ulong Sys_max_long_data_size( + "max_long_data_size", + "The maximum BLOB length to send to server from " + "mysql_send_long_data API. Deprecated option; " + "use max_allowed_packet instead.", + READ_ONLY GLOBAL_VAR(max_long_data_size), + CMD_LINE(REQUIRED_ARG, OPT_MAX_LONG_DATA_SIZE), + VALID_RANGE(1024, UINT_MAX32), DEFAULT(1024*1024), + BLOCK_SIZE(1)); + static PolyLock_mutex PLock_prepared_stmt_count(&LOCK_prepared_stmt_count); static Sys_var_ulong Sys_max_prepared_stmt_count( "max_prepared_stmt_count", === modified file 'tests/mysql_client_test.c' --- a/tests/mysql_client_test.c 2011-02-18 14:19:55 +0000 +++ b/tests/mysql_client_test.c 2011-03-14 15:19:44 +0000 @@ -19503,6 +19503,56 @@ static void test_bug57058() /* + Bug #56976: Severe Denial Of Service in prepared statements +*/ +static void test_bug56976() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + int rc; + const char* query = "SELECT LENGTH(?)"; + char *long_buffer; + unsigned long i, packet_len = 256 * 1024L; + unsigned long dos_len = 2 * 1024 * 1024L; + + DBUG_ENTER("test_bug56976"); + myheader("test_bug56976"); + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type = MYSQL_TYPE_TINY_BLOB; + + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + + long_buffer= (char*) my_malloc(packet_len, MYF(0)); + DIE_UNLESS(long_buffer); + + memset(long_buffer, 'a', packet_len); + + for (i= 0; i < dos_len / packet_len; i++) + { + rc= mysql_stmt_send_long_data(stmt, 0, long_buffer, packet_len); + check_execute(stmt, rc); + } + + my_free(long_buffer); + rc= mysql_stmt_execute(stmt); + + DIE_UNLESS(rc && mysql_stmt_errno(stmt) == ER_UNKNOWN_ERROR); + + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -19838,6 +19888,7 @@ static struct my_tests_st my_tests[]= { { "test_bug47485", test_bug47485 }, { "test_bug58036", test_bug58036 }, { "test_bug57058", test_bug57058 }, + { "test_bug56976", test_bug56976 }, { 0, 0 } }; --===============8635223634703594935== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.shulga@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.shulga@stripped\ # q7rirazlzrnj01l7 # target_branch: file:///Users/shulga/projects/mysql/mysql-5.5/ # testament_sha1: f400fa9f30186598ef3f31108c6ee3d577e3527b # timestamp: 2011-03-14 21:21:12 +0600 # source_branch: file:///Users/shulga/projects/mysql/mysql-5.1-\ # bug58887/ # base_revision_id: marc.alff@stripped\ # tzul0sqjz3cxj3n2 # # Begin bundle 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 tzbmTYG9L0v1JqTiHcRkHjT/4u5IpwoSG/3GBoA= --===============8635223634703594935==--