From: Dmitry Shulga Date: March 15 2011 1:06pm Subject: bzr push into mysql-5.5 branch (Dmitry.Shulga:3369 to 3370) Bug#11764168 List-Archive: http://lists.mysql.com/commits/133021 X-Bug: 11764168 Message-Id: <201103151307.p2FD73IH005686@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6148783937534253388==" --===============6148783937534253388== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 3369 Jon Olav Hauglid 2011-03-15 Bug #11765416 (former 58381) FAILED DROP DATABASE CAN BREAK STATEMENT BASED REPLICATION The first phase of DROP DATABASE is to delete the tables in the database. If deletion of one or more of the tables fail (e.g. due to a FOREIGN KEY constraint), DROP DATABASE will be aborted. However, some tables could still have been deleted. The problem was that nothing would be written to the binary log in this case, so any slaves would not delete these tables. Therefore the master and the slaves would get out of sync. This patch fixes the problem by making sure that DROP TABLE is written to the binary log for the tables that were in fact deleted by the failed DROP DATABASE statement. Test case added to binlog.binlog_database.test. modified: mysql-test/extra/binlog_tests/database.test mysql-test/suite/binlog/r/binlog_database.result sql/sql_db.cc === 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 } }; --===============6148783937534253388== 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 19:06:58 +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== --===============6148783937534253388==--