diff options
author | unknown <dlenev@brandersnatch.localdomain> | 2004-11-15 15:44:29 +0300 |
---|---|---|
committer | unknown <dlenev@brandersnatch.localdomain> | 2004-11-15 15:44:29 +0300 |
commit | 5d9f7edd6dfb0d6759a5374ac61c0153db48b1f7 (patch) | |
tree | aff5a1316b48a5f38063f5b0a42141d52f545d81 /sql | |
parent | 7fd0cc2d1265ac425e602f24894005539468c429 (diff) | |
download | mariadb-git-5d9f7edd6dfb0d6759a5374ac61c0153db48b1f7.tar.gz |
Fix for bug #6266 "Invalid DATETIME value is not handled properly".
In server we assume that datetime values stored in MYSQL_TIME struct
are normalized (and year is not greater than 9999), so we should
perform range checks in all places then we convert something to
MYSQL_TIME.
include/my_time.h:
Added one more argument to set_zero_time() function to make it more
convinient.
Added comment clarifying why MAX_DATE_STRING_REP_LENGTH value is 30.
include/mysql_time.h:
Documented MySQL's internal assumptions for members of MYSQL_TIME
structure.
libmysql/libmysql.c:
It does not make sense to set MYSQL_TIME::time_type twice in case of
errors.
mysql-test/r/type_datetime.result:
Added test for bug #6266 "Invalid DATETIME value not handled properly".
mysql-test/t/type_datetime.test:
Added test for bug #6266 "Invalid DATETIME value not handled properly".
sql-common/my_time.c:
str_to_datetime(): Added missing check for too big year values.
set_zero_time(): added time_type argument, since MYSQL_TIMESTAMP_NONE
is not the value that we want in most cases.
sql/field.cc:
Field_datetime::store_time():
clarified why we don't perform any range checks here.
sql/item.cc:
Item_param::set_time():
Added comment describing this method and range checking for TIME
values.
sql/sql_prepare.cc:
Removed comments about range checking for TIME values in prepared
statements, which are no longer true.
set_zero_time() has one more argument now.
tests/client_test.c:
Added test for bug #6266 "Invalid DATETIME value not handled properly"
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 4 | ||||
-rw-r--r-- | sql/item.cc | 26 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 23 |
3 files changed, 34 insertions, 19 deletions
diff --git a/sql/field.cc b/sql/field.cc index 24bd0c48c92..7d1627ef521 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4086,6 +4086,10 @@ int Field_datetime::store(longlong nr) void Field_datetime::store_time(TIME *ltime,timestamp_type type) { longlong tmp; + /* + We don't perform range checking here since values stored in TIME + structure always fit into DATETIME range. + */ if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME) tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+ (ltime->hour*10000L+ltime->minute*100+ltime->second)); diff --git a/sql/item.cc b/sql/item.cc index 7dc7e9e542c..382b85f9dc1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -837,6 +837,21 @@ void Item_param::set_double(double d) } +/* + Set parameter value from TIME value. + + SYNOPSIS + set_time() + tm - datetime value to set (time_type is ignored) + type - type of datetime value + max_length_arg - max length of datetime value as string + + NOTE + If we value to be stored is not normalized, zero value will be stored + instead and proper warning will be produced. This function relies on + the fact that even wrong value sent over binary protocol fits into + MAX_DATE_STRING_REP_LENGTH buffer. +*/ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg) { DBUG_ENTER("Item_param::set_time"); @@ -844,6 +859,17 @@ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg) value.time= *tm; value.time.time_type= type; + if (value.time.year > 9999 || value.time.month > 12 || + value.time.day > 31 || + type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 || + value.time.minute > 59 || value.time.second > 59) + { + char buff[MAX_DATE_STRING_REP_LENGTH]; + uint length= my_TIME_to_str(&value.time, buff); + make_truncated_value_warning(current_thd, buff, length, type); + set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR); + } + state= TIME_VALUE; maybe_null= 0; max_length= max_length_arg; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4ae69e40342..089853456e4 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -349,12 +349,6 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len) tm.neg= (bool) to[0]; day= (uint) sint4korr(to+1); - /* - Note, that though ranges of hour, minute and second are not checked - here we rely on them being < 256: otherwise - we'll get buffer overflow in make_{date,time} functions, - which are called when time value is converted to string. - */ tm.hour= (uint) to[5] + day * 24; tm.minute= (uint) to[6]; tm.second= (uint) to[7]; @@ -369,7 +363,7 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len) tm.day= tm.year= tm.month= 0; } else - set_zero_time(&tm); + set_zero_time(&tm, MYSQL_TIMESTAMP_TIME); param->set_time(&tm, MYSQL_TIMESTAMP_TIME, MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); *pos+= length; @@ -388,11 +382,6 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len) tm.year= (uint) sint2korr(to); tm.month= (uint) to[2]; tm.day= (uint) to[3]; - /* - Note, that though ranges of hour, minute and second are not checked - here we rely on them being < 256: otherwise - we'll get buffer overflow in make_{date,time} functions. - */ if (length > 4) { tm.hour= (uint) to[4]; @@ -405,7 +394,7 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len) tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0; } else - set_zero_time(&tm); + set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME); param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME, MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); *pos+= length; @@ -419,11 +408,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) if (length >= 4) { uchar *to= *pos; - /* - Note, that though ranges of hour, minute and second are not checked - here we rely on them being < 256: otherwise - we'll get buffer overflow in make_{date,time} functions. - */ + tm.year= (uint) sint2korr(to); tm.month= (uint) to[2]; tm.day= (uint) to[3]; @@ -433,7 +418,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) tm.neg= 0; } else - set_zero_time(&tm); + set_zero_time(&tm, MYSQL_TIMESTAMP_DATE); param->set_time(&tm, MYSQL_TIMESTAMP_DATE, MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); *pos+= length; |