From: Dmitry Shulga Date: March 15 2011 1:04pm Subject: bzr commit into mysql-trunk branch (Dmitry.Shulga:3768) Bug#11764168 List-Archive: http://lists.mysql.com/commits/133019 X-Bug: 11764168 Message-Id: <201103151304.p2FD4o0E020697@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============9033730689081405304==" --===============9033730689081405304== 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-trunk/ based on revid:jon.hauglid@stripped 3768 Dmitry Shulga 2011-03-15 [merge] Auto-merge from mysql-5.5 for Bug#11764168 (56976: Severe denial of service in prepared statements). 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-02-22 05:37:44 +0000 +++ b/mysql-test/r/mysqld--help-notwin.result 2011-03-15 13:03:22 +0000 @@ -320,6 +320,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=# @@ -850,6 +854,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-02-22 05:37:44 +0000 +++ b/mysql-test/r/mysqld--help-win.result 2011-03-15 13:03:22 +0000 @@ -319,6 +319,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=# @@ -853,6 +857,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 08:52:44 +0000 +++ b/mysql-test/r/variables.result 2011-03-15 13:03:22 +0000 @@ -1529,6 +1529,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.binlog_cache_size=DEFAULT; SET @@global.max_join_size=DEFAULT; === 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-15 12:57:36 +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-15 12:57:36 +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 08:52:44 +0000 +++ b/mysql-test/t/variables.test 2011-03-15 13:03:22 +0000 @@ -1268,6 +1268,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.binlog_cache_size=DEFAULT; === modified file 'sql/item.cc' --- a/sql/item.cc 2011-03-11 09:35:38 +0000 +++ b/sql/item.cc 2011-03-15 13:03:22 +0000 @@ -2976,6 +2976,16 @@ 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-14 13:21:47 +0000 +++ b/sql/mysqld.cc 2011-03-15 13:03:22 +0000 @@ -323,6 +323,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; @@ -481,6 +482,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. @@ -7417,6 +7423,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; } @@ -7643,6 +7653,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 10:08:09 +0000 +++ b/sql/mysqld.h 2011-03-15 13:03:22 +0000 @@ -130,6 +130,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; @@ -412,7 +413,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-11 09:35:38 +0000 +++ b/sql/sql_prepare.cc 2011-03-15 13:03:22 +0000 @@ -2785,6 +2785,7 @@ void mysql_sql_stmt_close(THD *thd) } } + /** Handle long data in pieces from client. @@ -2841,16 +2842,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->get_command(), NullS); @@ -3390,6 +3400,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; @@ -3657,12 +3674,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-22 02:58:40 +0000 +++ b/sql/sys_vars.cc 2011-03-15 13:03:22 +0000 @@ -1272,6 +1272,23 @@ static Sys_var_ulong Sys_max_length_for_ SESSION_VAR(max_length_for_sort_data), CMD_LINE(REQUIRED_ARG), VALID_RANGE(4, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1)); +static Sys_var_harows Sys_sql_max_join_size( + "sql_max_join_size", "Alias for max_join_size", + SESSION_VAR(max_join_size), NO_CMD_LINE, + VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1), + 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:22:03 +0000 +++ b/tests/mysql_client_test.c 2011-03-15 13:03:22 +0000 @@ -19470,6 +19470,56 @@ static void test_bug49972() } +/* + 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; +} + + /** Bug#57058 SERVER_QUERY_WAS_SLOW not wired up. */ @@ -19844,6 +19894,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 } }; --===============9033730689081405304== 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\ # 2a0zhequpu9q8dyt # target_branch: file:///Users/shulga/projects/mysql/mysql-trunk/ # testament_sha1: 4d61d132889806e7f70fd323161bf11fdf6aaeed # timestamp: 2011-03-15 19:04:44 +0600 # source_branch: file:///Users/shulga/projects/mysql/mysql-5.5/ # base_revision_id: jon.hauglid@stripped\ # i7xey1x3kz0qmh5z # # Begin bundle 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 oVTkuC5+K+HFfMPYhiB4S//F3JFOFCQYmzAaAA== --===============9033730689081405304==--