From a70c34bf0f34703fd330f8cb828e48b303c5296a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Feb 2011 18:51:35 +0200 Subject: Fixes for Bug #55755 and Bug #52315 part 2 Bug #55755 : Date STD variable signness breaks server on FreeBSD and OpenBSD * Added a check to configure on the size of time_t * Created a macro to check for a valid time_t that is safe to use with datetime functions and store in TIMESTAMP columns. * Used the macro consistently instead of the ad-hoc checks introduced by 52315 * Fixed compliation warnings on platforms where the size of time_t is smaller than the size of a long (e.g. OpenBSD 4.8 64 amd64). Bug #52315: utc_date() crashes when system time > year 2037 * Added a correct check for the timestamp range instead of just variable size check to SET TIMESTAMP. * Added overflow checking before converting to time_t. * Using a correct localized error message in this case instead of the generic error. * Added a test suite. * fixed the checks so that they check for unsigned time_t as well. Used the checks consistently across the source code. * fixed the original test case to expect the new error code. --- sql/set_var.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sql/set_var.cc') diff --git a/sql/set_var.cc b/sql/set_var.cc index 9c327504577..fbc7cdbc232 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2714,14 +2714,14 @@ int set_var_collation_client::update(THD *thd) bool sys_var_timestamp::check(THD *thd, set_var *var) { - time_t val; + longlong val; var->save_result.ulonglong_value= var->value->val_int(); - val= (time_t) var->save_result.ulonglong_value; - if (val < (time_t) MY_TIME_T_MIN || val > (time_t) MY_TIME_T_MAX) + val= (longlong) var->save_result.ulonglong_value; + if (val != 0 && // this is how you set the default value + (val < TIMESTAMP_MIN_VALUE || val > TIMESTAMP_MAX_VALUE)) { - my_message(ER_UNKNOWN_ERROR, - "This version of MySQL doesn't support dates later than 2038", - MYF(0)); + char buf[64]; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "timestamp", llstr(val, buf)); return TRUE; } return FALSE; -- cgit v1.2.1 From 6503226743a2fa24c7330d4541560a5b8fa821d6 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Thu, 17 Feb 2011 12:43:53 +0100 Subject: Bug#48053 String::c_ptr has a race and/or does an invalid memory reference There are two issues present here. 1) There is a possibility that we test a byte beyond the allocated buffer 2) We compare a byte that might never have been initalized to see if it's 0. The first issue is not triggered by existing code, but an ASSERT has been added to safe-guard against introducing new code that triggers it. The second issue is what triggers the Valgrind warnings reported in the bug report. A buffer is allocated in class String to hold the value. This buffer is populated by the character data constituting the string, but is not zero-terminated in most cases. Testing if it is indeed zero-terminated means that we check a byte that has never been explicitly set, thus causing Valgrind to trigger. Note that issue 2 is not a serious problem. The variable is read, and if it's not zero, we will set it to zero. There are no further consequences. Note that this patch does not fix the underlying problems with issue 1, as it is deemed too risky to fix at this point (as noted in the bug report). As discussed in the report, the c_ptr() method should probably be replaced, but this requires a thorough analysis of the ~200 calls to the method. sql/set_var.cc: These two cases have been reported to fail with Valgrind. --- sql/set_var.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/set_var.cc') diff --git a/sql/set_var.cc b/sql/set_var.cc index d297be3fc10..26c9b06a912 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1828,7 +1828,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) } var->save_result.ulong_value= ((ulong) - find_set(enum_names, res->c_ptr(), + find_set(enum_names, res->c_ptr_safe(), res->length(), NULL, &error, &error_len, @@ -2941,7 +2941,7 @@ bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var) my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); return 1; } - const char *locale_str= res->c_ptr(); + const char *locale_str= res->c_ptr_safe(); if (!(locale_match= my_locale_by_name(locale_str))) { my_printf_error(ER_UNKNOWN_ERROR, -- cgit v1.2.1 From 5f55c23208c746bd1211c09237fe85303dd49567 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 18 Feb 2011 16:12:36 +0300 Subject: Bug#11765108 (Bug#58036) client utf32, utf16, ucs2 should be disallowed, they crash server A separate fix for 5.1 (as 5.1 and 5.5 have seriously differged in the related pieces of the code). A patch for 5.5 was approved earlier. Problem: ucs2 was correctly disallowed in "SET NAMES" only, while mysql_real_connect() and mysql_change_user() still allowed to use ucs2, which made server crash. Fix: disallow ucs2 in mysql_real_connect() and mysql_change_user(). @ sql/sql_priv.h - changing return type for thd_init_client_charset() to bool, to return errors to the caller @ sql/sql_var.cc - using new function @ sql/sql_connect.cc - thd_client_charset_init: in case of unsupported client character set send error and return true; in case of success return false - check_connection: Return error if character set initialization failed @ sql/sql_parse.cc - check charset in the very beginnig of the CMD_CHANGE_USER handling code @ tests/mysql_client_test.c - adding tests --- sql/set_var.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/set_var.cc') diff --git a/sql/set_var.cc b/sql/set_var.cc index 26c9b06a912..831b68bbe14 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2187,7 +2187,7 @@ bool sys_var_character_set_client::check(THD *thd, set_var *var) if (sys_var_character_set_sv::check(thd, var)) return 1; /* Currently, UCS-2 cannot be used as a client character set */ - if (var->save_result.charset->mbminlen > 1) + if (!is_supported_parser_charset(var->save_result.charset)) { my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, var->save_result.charset->csname); -- cgit v1.2.1 From 9320dca994fdae18c549cb59266d49846dc1f839 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 15 Mar 2011 17:36:12 +0600 Subject: Fixed Bug#11764168 "56976: SEVERE DENIAL OF SERVICE IN PREPARED STATEMENTS". The problem was that server didn't check resulting size of prepared statement argument which was set using mysql_send_long_data() API. By calling mysql_send_long_data() several times it was possible to create overly big string and thus force server to allocate memory for it. There was no way to limit this allocation. The solution is to add check for size of result string against value of max_long_data_size start-up parameter. When intermediate string exceeds max_long_data_size value an appropriate error message is emitted. We can't use existing max_allowed_packet parameter for this purpose since its value is limited by 1GB and therefore using it as a limit for data set through mysql_send_long_data() API would have been an incompatible change. Newly introduced max_long_data_size parameter gets value from max_allowed_packet parameter unless its value is specified explicitly. This new parameter is marked as deprecated and will be eventually replaced by max_allowed_packet parameter. Value of max_long_data_size parameter can be set only at server startup. mysql-test/t/variables.test: Added checking for new start-up parameter max_long_data_size. sql/item.cc: Added call to my_message() when accumulated string exceeds max_long_data_size value. my_message() calls error handler that was installed in mysql_stmt_get_longdata before call to Item_param::set_longdata. The error handler then sets state, last_error and last_errno fields for current statement to values which correspond to error which was caught. sql/mysql_priv.h: Added max_long_data_size variable declaration. sql/mysqld.cc: Added support for start-up parameter 'max_long_data_size'. This parameter limits size of data which can be sent from client to server using mysql_send_long_data() API. sql/set_var.cc: Added variable 'max_long_data_size' into list of variables displayed by command 'show variables'. sql/sql_prepare.cc: Added error handler class Set_longdata_error_handler. This handler is used to catch any errors that can be generated during execution of Item_param::set_longdata(). Source code snippet that makes checking for statement's state during statement execution is moved from Prepared_statement::execute() to Prepared_statement::execute_loop() in order not to call set_parameters() when statement has failed during set_long_data() execution. If this hadn't been done the call to set_parameters() would have failed. tests/mysql_client_test.c: A testcase for the bug #56976 was added. --- sql/set_var.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sql/set_var.cc') diff --git a/sql/set_var.cc b/sql/set_var.cc index 831b68bbe14..333fb90c795 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -394,6 +394,12 @@ static sys_var_thd_ulong sys_max_seeks_for_key(&vars, "max_seeks_for_key", &SV::max_seeks_for_key); static sys_var_thd_ulong sys_max_length_for_sort_data(&vars, "max_length_for_sort_data", &SV::max_length_for_sort_data); +static sys_var_const sys_max_long_data_size(&vars, + "max_long_data_size", + OPT_GLOBAL, SHOW_LONG, + (uchar*) + &max_long_data_size); + #ifndef TO_BE_DELETED /* Alias for max_join_size */ static sys_var_thd_ha_rows sys_sql_max_join_size(&vars, "sql_max_join_size", &SV::max_join_size, -- cgit v1.2.1 From dcf6b68d08acfbfdc3183b0a13f041af51573eb1 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 25 Mar 2011 12:57:27 +0200 Subject: Bug #11766769: 59959: SMALL VALUES OF --MAX-ALLOWED-PACKET ARE NOT BEING HONORED max_allowed_packet works in conjunction with net_buffer_length. max_allowed_packet is an upper bound of net_buffer_length. So it doesn't make sense to set the upper limit lower than the value. Added a warning (using ER_UNKNOWN_ERRROR and a specific message) when this is done (in the log at startup and when setting either max_allowed_packet or the net_buffer_length variables) Added a test case. Fixed several tests that broke the above rule. --- sql/set_var.cc | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'sql/set_var.cc') diff --git a/sql/set_var.cc b/sql/set_var.cc index 333fb90c795..76957e32536 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -147,6 +147,8 @@ static void sys_default_general_log_path(THD *thd, enum_var_type type); static bool sys_update_slow_log_path(THD *thd, set_var * var); static void sys_default_slow_log_path(THD *thd, enum_var_type type); static uchar *get_myisam_mmap_size(THD *thd); +static int check_max_allowed_packet(THD *thd, set_var *var); +static int check_net_buffer_length(THD *thd, set_var *var); /* Variable definition list @@ -360,7 +362,8 @@ static sys_var_const sys_lower_case_table_names(&vars, (uchar*) &lower_case_table_names); static sys_var_thd_ulong_session_readonly sys_max_allowed_packet(&vars, "max_allowed_packet", - &SV::max_allowed_packet); + &SV::max_allowed_packet, + check_max_allowed_packet); static sys_var_ulonglong_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size", &max_binlog_cache_size); static sys_var_long_ptr sys_max_binlog_size(&vars, "max_binlog_size", @@ -450,7 +453,8 @@ static sys_var_const sys_named_pipe(&vars, "named_pipe", /* purecov: end */ #endif static sys_var_thd_ulong_session_readonly sys_net_buffer_length(&vars, "net_buffer_length", - &SV::net_buffer_length); + &SV::net_buffer_length, + check_net_buffer_length); static sys_var_thd_ulong sys_net_read_timeout(&vars, "net_read_timeout", &SV::net_read_timeout, 0, fix_net_read_timeout); @@ -4312,6 +4316,36 @@ uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type, } #endif + +int +check_max_allowed_packet(THD *thd, set_var *var) +{ + longlong val= var->value->val_int(); + if (val < (longlong) global_system_variables.net_buffer_length) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "The value of 'max_allowed_packet' should be no less than " + "the value of 'net_buffer_length'"); + } + return 0; +} + + +int +check_net_buffer_length(THD *thd, set_var *var) +{ + longlong val= var->value->val_int(); + if (val > (longlong) global_system_variables.max_allowed_packet) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "The value of 'max_allowed_packet' should be no less than " + "the value of 'net_buffer_length'"); + } + return 0; +} + /**************************************************************************** Used templates ****************************************************************************/ -- cgit v1.2.1