Commit 121e0473 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #52315: utc_date() crashes when system time > year 2037

            
Some of the server implementations don't support dates later
than 2038 due to the internal time type being 32 bit.
Added checks so that the server will refuse dates that cannot
be handled by either throwing an error when setting date at 
runtime or by refusing to start or shutting down the server if 
the system date cannot be stored in my_time_t.
parent bd9fa7da
...@@ -910,3 +910,11 @@ set global thread_cache_size =@my_thread_cache_size; ...@@ -910,3 +910,11 @@ set global thread_cache_size =@my_thread_cache_size;
# Test 'myisam_mmap_size' option is not dynamic # Test 'myisam_mmap_size' option is not dynamic
SET @@myisam_mmap_size= 500M; SET @@myisam_mmap_size= 500M;
ERROR HY000: Variable 'myisam_mmap_size' is a read only variable ERROR HY000: Variable 'myisam_mmap_size' is a read only variable
#
# Bug #52315: utc_date() crashes when system time > year 2037
#
SET TIMESTAMP=2*1024*1024*1024;
#Should not crash
SELECT UTC_DATE();
SET TIMESTAMP=DEFAULT;
End of 5.0 tests
...@@ -771,3 +771,17 @@ set global thread_cache_size =@my_thread_cache_size; ...@@ -771,3 +771,17 @@ set global thread_cache_size =@my_thread_cache_size;
--echo # Test 'myisam_mmap_size' option is not dynamic --echo # Test 'myisam_mmap_size' option is not dynamic
--error ER_INCORRECT_GLOBAL_LOCAL_VAR --error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@myisam_mmap_size= 500M; SET @@myisam_mmap_size= 500M;
--echo #
--echo # Bug #52315: utc_date() crashes when system time > year 2037
--echo #
--error 0, ER_UNKNOWN_ERROR
SET TIMESTAMP=2*1024*1024*1024;
--echo #Should not crash
--disable_result_log
SELECT UTC_DATE();
--enable_result_log
SET TIMESTAMP=DEFAULT;
--echo End of 5.0 tests
...@@ -2835,6 +2835,14 @@ static int init_common_variables(const char *conf_file_name, int argc, ...@@ -2835,6 +2835,14 @@ static int init_common_variables(const char *conf_file_name, int argc,
max_system_variables.pseudo_thread_id= (ulong)~0; max_system_variables.pseudo_thread_id= (ulong)~0;
server_start_time= flush_status_time= time((time_t*) 0); server_start_time= flush_status_time= time((time_t*) 0);
/* TODO: remove this when my_time_t is 64 bit compatible */
if (server_start_time >= (time_t) MY_TIME_T_MAX)
{
sql_print_error("This MySQL server doesn't support dates later then 2038");
return 1;
}
if (init_thread_environment()) if (init_thread_environment())
return 1; return 1;
mysql_init_variables(); mysql_init_variables();
......
...@@ -2712,10 +2712,26 @@ int set_var_collation_client::update(THD *thd) ...@@ -2712,10 +2712,26 @@ int set_var_collation_client::update(THD *thd)
/****************************************************************************/ /****************************************************************************/
bool sys_var_timestamp::check(THD *thd, set_var *var)
{
time_t 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)
{
my_message(ER_UNKNOWN_ERROR,
"This version of MySQL doesn't support dates later than 2038",
MYF(0));
return TRUE;
}
return FALSE;
}
bool sys_var_timestamp::update(THD *thd, set_var *var) bool sys_var_timestamp::update(THD *thd, set_var *var)
{ {
thd->set_time((time_t) var->save_result.ulonglong_value); thd->set_time((time_t) var->save_result.ulonglong_value);
return 0; return FALSE;
} }
......
...@@ -536,6 +536,7 @@ class sys_var_timestamp :public sys_var ...@@ -536,6 +536,7 @@ class sys_var_timestamp :public sys_var
{ {
public: public:
sys_var_timestamp(const char *name_arg) :sys_var(name_arg) {} sys_var_timestamp(const char *name_arg) :sys_var(name_arg) {}
bool check(THD *thd, set_var *var);
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
......
...@@ -1707,6 +1707,11 @@ public: ...@@ -1707,6 +1707,11 @@ public:
inline void end_time() { safe_time(&start_time); } inline void end_time() { safe_time(&start_time); }
inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; } inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; }
inline void lock_time() { safe_time(&time_after_lock); } inline void lock_time() { safe_time(&time_after_lock); }
/*TODO: this will be obsolete when we have support for 64 bit my_time_t */
inline bool is_valid_time()
{
return (start_time < (time_t) MY_TIME_T_MAX);
}
inline void insert_id(ulonglong id_arg) inline void insert_id(ulonglong id_arg)
{ {
last_insert_id= id_arg; last_insert_id= id_arg;
......
...@@ -1771,6 +1771,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1771,6 +1771,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->enable_slow_log= TRUE; thd->enable_slow_log= TRUE;
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
thd->set_time(); thd->set_time();
if (!thd->is_valid_time())
{
/*
If the time has got past 2038 we need to shut this server down
We do this by making sure every command is a shutdown and we
have enough privileges to shut the server down
TODO: remove this when we have full 64 bit my_time_t support
*/
thd->security_ctx->master_access|= SHUTDOWN_ACL;
command= COM_SHUTDOWN;
}
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id= global_query_id; thd->query_id= global_query_id;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment