diff options
-rw-r--r-- | config.h.cmake | 5 | ||||
-rw-r--r-- | configure.cmake | 11 | ||||
-rw-r--r-- | include/my_time.h | 13 | ||||
-rw-r--r-- | mysql-test/r/func_time.result | 18 | ||||
-rw-r--r-- | mysql-test/t/func_time.test | 18 | ||||
-rw-r--r-- | mysql-test/t/variables.test | 2 | ||||
-rw-r--r-- | sql-common/my_time.c | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 13 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 12 |
10 files changed, 81 insertions, 15 deletions
diff --git a/config.h.cmake b/config.h.cmake index 65ebd077da6..7de8f716e77 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -614,4 +614,9 @@ #define PROTOCOL_VERSION 10 +/* time_t related defines */ + +#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@ +#cmakedefine TIME_T_UNSIGNED @TIME_T_UNSIGNED@ + #endif diff --git a/configure.cmake b/configure.cmake index 954b60a45f6..90a01ff913c 100644 --- a/configure.cmake +++ b/configure.cmake @@ -574,6 +574,7 @@ MY_CHECK_TYPE_SIZE(uint32 UINT32) MY_CHECK_TYPE_SIZE(u_int32_t U_INT32_T) MY_CHECK_TYPE_SIZE(int64 INT64) MY_CHECK_TYPE_SIZE(uint64 UINT64) +MY_CHECK_TYPE_SIZE(time_t TIME_T) SET (CMAKE_EXTRA_INCLUDE_FILES sys/types.h) MY_CHECK_TYPE_SIZE(bool BOOL) SET(CMAKE_EXTRA_INCLUDE_FILES) @@ -593,6 +594,16 @@ ENDIF() # Code tests # +# check whether time_t is unsigned +CHECK_C_SOURCE_COMPILES(" +int main() +{ + int array[(((time_t)-1) > 0) ? 1 : -1]; + return 0; +}" +TIME_T_UNSIGNED) + + CHECK_C_SOURCE_COMPILES(" #ifdef _WIN32 #include <winsock2.h> diff --git a/include/my_time.h b/include/my_time.h index fdfe130c45f..68f9c2e739f 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -50,6 +50,19 @@ typedef long my_time_t; /* two-digit years < this are 20..; >= this are 19.. */ #define YY_PART_YEAR 70 +/* + check for valid times only if the range of time_t is greater than + the range of my_time_t +*/ +#if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED) +# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ + ((x) <= TIMESTAMP_MAX_VALUE && \ + (x) >= TIMESTAMP_MIN_VALUE) +#else +# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ + ((x) >= TIMESTAMP_MIN_VALUE) +#endif + /* Flags to str_to_datetime */ #define TIME_FUZZY_DATE 1 #define TIME_DATETIME_ONLY 2 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 34987530b5a..2a95b234548 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1273,6 +1273,24 @@ date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond) select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond); date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond) 1000-01-01 00:00:01.020000 +# +# Bug #52315 part 2 : utc_date() crashes when system time > year 2037 +# +SET TIMESTAMP=-147490000; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=2147483648; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=2147483646; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=2147483647; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=0; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=-1; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=1; +SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=0; End of 5.0 tests select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND); date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND) diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 25600a2d583..153266055d7 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -802,6 +802,24 @@ select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND; select date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond); select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond); + +--echo # +--echo # Bug #52315 part 2 : utc_date() crashes when system time > year 2037 +--echo # + +--disable_result_log +SET TIMESTAMP=-147490000; SELECT UTC_TIMESTAMP(); +--error ER_WRONG_VALUE_FOR_VAR +SET TIMESTAMP=2147483648; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=2147483646; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=2147483647; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=0; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=-1; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=1; SELECT UTC_TIMESTAMP(); +SET TIMESTAMP=0; +--enable_result_log + + --echo End of 5.0 tests # diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index d31939ed3dd..b766c1c7dc6 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -779,7 +779,7 @@ SET @@myisam_mmap_size= 500M; --echo # Bug #52315: utc_date() crashes when system time > year 2037 --echo # ---error 0, ER_UNKNOWN_ERROR +--error 0, ER_WRONG_VALUE_FOR_VAR SET TIMESTAMP=2*1024*1024*1024; --echo #Should not crash --disable_result_log diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 38384600fc1..39eee57a1c0 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -992,7 +992,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, with unsigned time_t tmp+= shift*86400L might result in a number, larger then TIMESTAMP_MAX_VALUE, so another check will work. */ - if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) + if (!IS_TIME_T_VALID_FOR_TIMESTAMP(tmp)) tmp= 0; return (my_time_t) tmp; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 188ed7c6885..cf1627ced57 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3080,12 +3080,6 @@ static int init_common_variables() max_system_variables.pseudo_thread_id= (ulong)~0; server_start_time= flush_status_time= my_time(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; - } rpl_filter= new Rpl_filter; binlog_filter= new Rpl_filter; @@ -3124,6 +3118,13 @@ static int init_common_variables() */ mysql_bin_log.init_pthread_objects(); + /* TODO: remove this when my_time_t is 64 bit compatible */ + if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time)) + { + sql_print_error("This MySQL server doesn't support dates later then 2038"); + return 1; + } + if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0) { strmake(glob_hostname, STRING_WITH_LEN("localhost")); diff --git a/sql/sql_class.h b/sql/sql_class.h index 8b05497388e..137a0c48ead 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2280,7 +2280,7 @@ public: /*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); + return (IS_TIME_T_VALID_FOR_TIMESTAMP(start_time)); } void set_time_after_lock() { utime_after_lock= my_micro_time(); } ulonglong current_utime() { return my_micro_time(); } diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 68bb77d467f..ce1dcb4a33c 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2430,17 +2430,17 @@ static ulonglong read_timestamp(THD *thd) static bool check_timestamp(sys_var *self, THD *thd, set_var *var) { - time_t val; + longlong val; if (!var->value) return FALSE; - 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; |