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.
This commit is contained in:
parent
e95a3e3ce8
commit
ef55f2dcdb
@ -32,3 +32,9 @@ ts from_unixtime(ts)
|
||||
1048989599 2003-03-30 03:59:59
|
||||
1048989601 2003-03-30 04:00:01
|
||||
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'));
|
||||
SELECT ts,from_unixtime(ts) FROM 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');
|
||||
|
14
sql/field.cc
14
sql/field.cc
@ -2583,22 +2583,18 @@ static longlong fix_datetime(longlong nr, TIME *time_res)
|
||||
void Field_timestamp::store(longlong nr)
|
||||
{
|
||||
TIME l_time;
|
||||
time_t timestamp;
|
||||
time_t timestamp= 0;
|
||||
|
||||
if ((nr= fix_datetime(nr, &l_time)))
|
||||
{
|
||||
long not_used;
|
||||
|
||||
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
|
||||
{
|
||||
timestamp= my_gmt_sec(&l_time, ¬_used);
|
||||
|
||||
if (!timestamp)
|
||||
current_thd->cuted_fields++;
|
||||
timestamp=0;
|
||||
}
|
||||
else
|
||||
timestamp=my_gmt_sec(&l_time, ¬_used);
|
||||
}
|
||||
else
|
||||
timestamp=0;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (table->db_low_byte_first)
|
||||
{
|
||||
|
@ -116,6 +116,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
|
||||
/* Time handling defaults */
|
||||
#define TIMESTAMP_MAX_YEAR 2038
|
||||
#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_FLOAT 24
|
||||
|
||||
|
19
sql/time.cc
19
sql/time.cc
@ -63,6 +63,9 @@ long my_gmt_sec(TIME *t, long *my_timezone)
|
||||
struct tm *l_time,tm_tmp;
|
||||
long diff, current_timezone;
|
||||
|
||||
if (t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR)
|
||||
return 0;
|
||||
|
||||
if (t->hour >= 24)
|
||||
{ /* Fix for time-loop */
|
||||
t->day+=t->hour/24;
|
||||
@ -125,8 +128,10 @@ long my_gmt_sec(TIME *t, long *my_timezone)
|
||||
tmp-=t->minute*60 + t->second; // Move to previous hour
|
||||
}
|
||||
*my_timezone= current_timezone;
|
||||
if (tmp < 0 && t->year <= 1900+YY_PART_YEAR)
|
||||
|
||||
if (tmp < TIMESTAMP_MIN_VALUE || tmp > TIMESTAMP_MAX_VALUE)
|
||||
tmp= 0;
|
||||
|
||||
return (long) tmp;
|
||||
} /* my_gmt_sec */
|
||||
|
||||
@ -444,15 +449,13 @@ time_t str_to_timestamp(const char *str,uint length)
|
||||
{
|
||||
TIME l_time;
|
||||
long not_used;
|
||||
time_t timestamp= 0;
|
||||
|
||||
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
|
||||
return(0);
|
||||
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
|
||||
{
|
||||
if (str_to_TIME(str,length,&l_time,0) != TIMESTAMP_NONE &&
|
||||
!(timestamp= my_gmt_sec(&l_time, ¬_used)))
|
||||
current_thd->cuted_fields++;
|
||||
return(0);
|
||||
}
|
||||
return(my_gmt_sec(&l_time, ¬_used));
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user