Commit ef55f2dc authored by unknown's avatar unknown

Fix for bug #2523 '"func_time" test fails on QNX'.

Moved all range checks for TIMESTAMP value to my_gmt_sec().
Also fixed check of upper boundary of TIMESTAMP range (which 
also now will catch datetime values which are too small for
TIMESTAMP in case if time_t is unsigned).  


mysql-test/r/timezone.result:
  Added test which checks if TIMESTAMP range is checked 
  correctly (current time zone is honoured and both upper 
  and lower bounds of TIMESTAMP range are checked).
mysql-test/t/timezone.test:
  Added test which checks if TIMESTAMP range is checked 
  correctly (current time zone is honoured and both upper 
  and lower bounds of TIMESTAMP range are checked).
sql/field.cc:
  Check if datetime value is in TIMESTAMP range has moved to 
  my_gmt_sec() function.
sql/mysql_priv.h:
  Added more constants for checking if datetime is in allowed
  range for TIMESTAMP.
sql/time.cc:
  Check if datetime value is in TIMESTAMP range has moved to 
  my_gmt_sec() function. Fixed check of its return value
  to catch overflows in both directions and also overflows in 
  case of unsigned time_t.
parent e95a3e3c
...@@ -32,3 +32,9 @@ ts from_unixtime(ts) ...@@ -32,3 +32,9 @@ ts from_unixtime(ts)
1048989599 2003-03-30 03:59:59 1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01 1048989601 2003-03-30 04:00:01
DROP TABLE t1; DROP TABLE t1;
select unix_timestamp('1970-01-01 01:00:00'),
unix_timestamp('1970-01-01 01:00:01'),
unix_timestamp('2038-01-01 00:59:59'),
unix_timestamp('2038-01-01 01:00:00');
unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00')
0 1 2145916799 0
...@@ -38,3 +38,10 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01')); ...@@ -38,3 +38,10 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1; SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Test for fix for Bug#2523
#
select unix_timestamp('1970-01-01 01:00:00'),
unix_timestamp('1970-01-01 01:00:01'),
unix_timestamp('2038-01-01 00:59:59'),
unix_timestamp('2038-01-01 01:00:00');
...@@ -2583,22 +2583,18 @@ static longlong fix_datetime(longlong nr, TIME *time_res) ...@@ -2583,22 +2583,18 @@ static longlong fix_datetime(longlong nr, TIME *time_res)
void Field_timestamp::store(longlong nr) void Field_timestamp::store(longlong nr)
{ {
TIME l_time; TIME l_time;
time_t timestamp; time_t timestamp= 0;
if ((nr= fix_datetime(nr, &l_time))) if ((nr= fix_datetime(nr, &l_time)))
{ {
long not_used; long not_used;
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) timestamp= my_gmt_sec(&l_time, &not_used);
{
if (!timestamp)
current_thd->cuted_fields++; current_thd->cuted_fields++;
timestamp=0;
}
else
timestamp=my_gmt_sec(&l_time, &not_used);
} }
else
timestamp=0;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first) if (table->db_low_byte_first)
{ {
......
...@@ -116,6 +116,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); ...@@ -116,6 +116,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
/* Time handling defaults */ /* Time handling defaults */
#define TIMESTAMP_MAX_YEAR 2038 #define TIMESTAMP_MAX_YEAR 2038
#define YY_PART_YEAR 70 #define YY_PART_YEAR 70
#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
#define TIMESTAMP_MAX_VALUE 2145916799
#define TIMESTAMP_MIN_VALUE 1
#define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_DOUBLE 53
#define PRECISION_FOR_FLOAT 24 #define PRECISION_FOR_FLOAT 24
......
...@@ -63,6 +63,9 @@ long my_gmt_sec(TIME *t, long *my_timezone) ...@@ -63,6 +63,9 @@ long my_gmt_sec(TIME *t, long *my_timezone)
struct tm *l_time,tm_tmp; struct tm *l_time,tm_tmp;
long diff, current_timezone; long diff, current_timezone;
if (t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR)
return 0;
if (t->hour >= 24) if (t->hour >= 24)
{ /* Fix for time-loop */ { /* Fix for time-loop */
t->day+=t->hour/24; t->day+=t->hour/24;
...@@ -125,8 +128,10 @@ long my_gmt_sec(TIME *t, long *my_timezone) ...@@ -125,8 +128,10 @@ long my_gmt_sec(TIME *t, long *my_timezone)
tmp-=t->minute*60 + t->second; // Move to previous hour tmp-=t->minute*60 + t->second; // Move to previous hour
} }
*my_timezone= current_timezone; *my_timezone= current_timezone;
if (tmp < 0 && t->year <= 1900+YY_PART_YEAR)
if (tmp < TIMESTAMP_MIN_VALUE || tmp > TIMESTAMP_MAX_VALUE)
tmp= 0; tmp= 0;
return (long) tmp; return (long) tmp;
} /* my_gmt_sec */ } /* my_gmt_sec */
...@@ -444,15 +449,13 @@ time_t str_to_timestamp(const char *str,uint length) ...@@ -444,15 +449,13 @@ time_t str_to_timestamp(const char *str,uint length)
{ {
TIME l_time; TIME l_time;
long not_used; long not_used;
time_t timestamp= 0;
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) if (str_to_TIME(str,length,&l_time,0) != TIMESTAMP_NONE &&
return(0); !(timestamp= my_gmt_sec(&l_time, &not_used)))
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
{
current_thd->cuted_fields++; current_thd->cuted_fields++;
return(0);
} return timestamp;
return(my_gmt_sec(&l_time, &not_used));
} }
......
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