diff options
author | dlenev@mysql.com <> | 2004-11-19 18:35:36 +0300 |
---|---|---|
committer | dlenev@mysql.com <> | 2004-11-19 18:35:36 +0300 |
commit | cb7e272e46fbeb99dd45aa65ea631e85479f5750 (patch) | |
tree | a195ead1015ae682d794d4a7c6022a10d363c17a /sql | |
parent | 03c28bf12f107d901a35d8342ce6e8c244d07247 (diff) | |
parent | b02f5aa6926ecf80748066ca9da82d90ea95f746 (diff) | |
download | mariadb-git-cb7e272e46fbeb99dd45aa65ea631e85479f5750.tar.gz |
Manual merge of fix for bug #6266 "Invalid DATETIME value is not handled
properly" with main tree.
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 bbd21247b8e..72c27b6adf9 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 0e7a2b50b51..31c35e87cd4 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 d81ed2cd014..a790e6fe9d8 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; |