#At file:///Users/kgeorge/mysql/work/B55755-5.0/ based on revid:alexander.nozdrin@stripped
2895 Georgi Kodinov 2011-01-17
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 can fit into a my_time_t
* 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.
modified:
configure.in
include/config-win.h
include/my_time.h
mysql-test/r/func_time.result
mysql-test/t/func_time.test
sql-common/my_time.c
sql/mysqld.cc
sql/set_var.cc
sql/sql_class.h
=== modified file 'configure.in'
--- a/configure.in 2010-12-28 18:57:23 +0000
+++ b/configure.in 2011-01-17 16:43:43 +0000
@@ -1956,6 +1956,15 @@ dnl
MYSQL_CHECK_TIME_T
+dnl
+dnl check size of time_t
+dnl
+
+AC_CHECK_SIZEOF(time_t, 8)
+if test "$ac_cv_sizeof_time_t" -eq 0
+then
+ AC_MSG_ERROR("MySQL needs a time_t type.")
+fi
# do we need #pragma interface/#pragma implementation ?
# yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin
=== modified file 'include/config-win.h'
--- a/include/config-win.h 2009-07-31 19:22:02 +0000
+++ b/include/config-win.h 2011-01-17 16:43:43 +0000
@@ -167,6 +167,7 @@ typedef uint rf_SetTimer;
#define SIZEOF_LONG 4
#define SIZEOF_LONG_LONG 8
#define SIZEOF_OFF_T 8
+#define SIZEOF_TIME_T 8
#ifdef _WIN64
#define SIZEOF_CHARP 8
#else
=== modified file 'include/my_time.h'
--- a/include/my_time.h 2008-04-03 15:32:00 +0000
+++ b/include/my_time.h 2011-01-17 16:43:43 +0000
@@ -44,6 +44,17 @@ typedef long my_time_t;
#define MY_TIME_T_MIN LONG_MIN
+/*
+ check for valid times only if the range of time_t is greater than
+ the range of my_time_t
+*/
+#if SIZEOF_TIME_T > SIZEOF_LONG
+# define IS_VALID_TIME_T(x) ((x) <= (time_t) MY_TIME_T_MAX && \
+ (x) >= (time_t) MY_TIME_T_MIN)
+#else
+# define IS_VALID_TIME_T(x) (1 > 0)
+#endif
+
/* Time handling defaults */
#define TIMESTAMP_MAX_YEAR 2038
#define YY_PART_YEAR 70
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2008-12-23 14:08:04 +0000
+++ b/mysql-test/r/func_time.result 2011-01-17 16:43:43 +0000
@@ -1323,4 +1323,15 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SE
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
+#
+# 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();
End of 5.0 tests
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2008-12-23 14:08:04 +0000
+++ b/mysql-test/t/func_time.test 2011-01-17 16:43:43 +0000
@@ -838,4 +838,19 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SE
--error ER_PARSE_ERROR
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
+
+--echo #
+--echo # Bug #52315 part 2 : utc_date() crashes when system time > year 2037
+--echo #
+
+--disable_result_log
+--error ER_WRONG_VALUE_FOR_VAR
+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();
+--enable_result_log
+
+
--echo End of 5.0 tests
=== modified file 'sql-common/my_time.c'
--- a/sql-common/my_time.c 2009-09-17 15:10:30 +0000
+++ b/sql-common/my_time.c 2011-01-17 16:43:43 +0000
@@ -984,8 +984,16 @@ my_system_gmt_sec(const MYSQL_TIME *t_sr
So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms
with unsigned time_t tmp+= shift*86400L might result in a number,
larger then TIMESTAMP_MAX_VALUE, so another check will work.
+
+ tmp being larger than TIMESTAMP_MAX_VALUE can only happen on
+ platforms where the size of time_t is larger than the size of
+ TIMESTAMP_MAX_VALUE (currently INT32 : 4 bytes).
+ #ifdef to avoid the compilation warnings on these platforms (OpenBSD).
*/
- if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE))
+ if ((tmp < TIMESTAMP_MIN_VALUE)
+#if SIZEOF_TIME_T > 4
+ || (tmp > TIMESTAMP_MAX_VALUE))
+#endif
tmp= 0;
return (my_time_t) tmp;
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-12-28 18:57:23 +0000
+++ b/sql/mysqld.cc 2011-01-17 16:43:43 +0000
@@ -2836,13 +2836,6 @@ static int init_common_variables(const c
max_system_variables.pseudo_thread_id= (ulong)~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())
return 1;
mysql_init_variables();
@@ -2882,6 +2875,13 @@ static int init_common_variables(const c
mysql_slow_log.init_pthread_objects();
mysql_bin_log.init_pthread_objects();
+ /* TODO: remove this when my_time_t is 64 bit compatible */
+ if (!IS_VALID_TIME_T(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"));
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2010-12-28 18:57:23 +0000
+++ b/sql/set_var.cc 2011-01-17 16:43:43 +0000
@@ -2714,14 +2714,22 @@ int set_var_collation_client::update(THD
bool sys_var_timestamp::check(THD *thd, set_var *var)
{
- time_t val;
+ longlong val;
+ time_t time_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;
+ time_val= (time_t) val;
+ if (val != 0 // this is how you set the default value
+ && (val < TIMESTAMP_MIN_VALUE
+ || val != (longlong) time_val
+#if SIZEOF_TIME_T > 4
+ || val > TIMESTAMP_MAX_VALUE
+#endif
+ )
+ )
{
- 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;
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-12-28 18:57:23 +0000
+++ b/sql/sql_class.h 2011-01-17 16:43:43 +0000
@@ -1710,7 +1710,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_VALID_TIME_T(start_time));
}
inline void insert_id(ulonglong id_arg)
{
Attachment: [text/bzr-bundle] bzr/georgi.kodinov@oracle.com-20110117164343-5zm9uufk45yngrnc.bundle