From: Dmitry Shulga Date: March 15 2011 12:58pm Subject: bzr commit into mysql-5.5 branch (Dmitry.Shulga:3370) Bug#11764168 List-Archive: http://lists.mysql.com/commits/133017 X-Bug: 11764168 Message-Id: <201103151259.p2FCx8DA014310@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6226441882705103504==" --===============6226441882705103504== 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:jon.hauglid@stripped 3370 Dmitry Shulga 2011-03-15 [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-15 12:57:36 +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-15 12:57:36 +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-15 12:57:36 +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-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 07:34:22 +0000 +++ b/mysql-test/t/variables.test 2011-03-15 12:57:36 +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-08 17:39:25 +0000 +++ b/sql/item.cc 2011-03-15 12:57:36 +0000 @@ -2885,6 +2885,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:03:48 +0000 +++ b/sql/mysqld.cc 2011-03-15 12:57:36 +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. @@ -7160,6 +7166,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; } @@ -7386,6 +7396,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-15 12:57:36 +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-08 17:39:25 +0000 +++ b/sql/sql_prepare.cc 2011-03-15 12:57:36 +0000 @@ -2784,6 +2784,7 @@ void mysql_sql_stmt_close(THD *thd) } } + /** Handle long data in pieces from client. @@ -2840,16 +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); @@ -3389,6 +3399,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 +3673,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-15 12:57:36 +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-15 12:57:36 +0000 @@ -19464,6 +19464,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. */ @@ -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 } }; --===============6226441882705103504== 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\ # kq4hehzxckulrk3z # target_branch: file:///Users/shulga/projects/mysql/mysql-5.5/ # testament_sha1: a83cc64d78fa3c5eda79b98df0b33071fca02ac2 # timestamp: 2011-03-15 18:59:02 +0600 # source_branch: file:///Users/shulga/projects/mysql/mysql-5.1-\ # bug58887/ # base_revision_id: jon.hauglid@stripped\ # 7hlmt4zbwj8czevz # # Begin bundle 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 cGYAckWot1ozR2D4jTYuyf/F3JFOFCQH7OdNAA== --===============6226441882705103504==--