summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h.cmake5
-rw-r--r--configure.cmake11
-rw-r--r--include/my_time.h13
-rw-r--r--mysql-test/r/func_time.result18
-rw-r--r--mysql-test/t/func_time.test18
-rw-r--r--mysql-test/t/variables.test2
-rw-r--r--sql-common/my_time.c2
-rw-r--r--sql/mysqld.cc13
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sys_vars.cc12
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;