diff options
author | Tor Didriksen <tor.didriksen@oracle.com> | 2012-03-14 13:25:14 +0100 |
---|---|---|
committer | Tor Didriksen <tor.didriksen@oracle.com> | 2012-03-14 13:25:14 +0100 |
commit | 13053fbe54534cfc8d673c55459d368f7da4694f (patch) | |
tree | 89a4ce6fd8cf69097195b200cbdef6b91bd37489 /sql/item.cc | |
parent | 1a2e4afe355759e9c8259a3ff79c2509dfd54bb0 (diff) | |
download | mariadb-git-13053fbe54534cfc8d673c55459d368f7da4694f.tar.gz |
Bug#13721076 CRASH WITH TIME TYPE/TIMESTAMP() AND WARNINGS IN SUBQUERY
The table contains one time value: '00:00:32'
This value is converted to timestamp by a subquery.
In convert_constant_item we call (*item)->is_null()
which triggers execution of the Item_singlerow_subselect subquery,
and the string "0000-00-00 00:00:32" is cached
by Item_cache_datetime.
We continue execution and call update_null_value, which calls val_int()
on the cached item, which converts the time value to ((longlong) 32)
Then we continue to do (*item)->save_in_field()
which ends up in Item_cache_datetime::val_str() which fails,
since (32 < 101) in number_to_datetime, and val_str() returns NULL.
Item_singlerow_subselect::val_str isnt prepared for this:
if exec() succeeds, and return !null_value, then val_str()
*must* succeed.
Solution: refuse to cache strings like "0000-00-00 00:00:32"
in Item_cache_datetime::cache_value, and return NULL instead.
This is similar to the solution for
Bug#11766860 - 60085: CRASH IN ITEM::SAVE_IN_FIELD() WITH TIME DATA TYPE
This patch is for 5.5 only.
The issue is not present after WL#946, since a time value
will be converted to a proper timestamp, with the current date
rather than "0000-00-00"
mysql-test/r/subselect.result:
New test case.
mysql-test/t/subselect.test:
New test case.
sql/item.cc:
Verify proper date format before caching timestamps.
sql/item_timefunc.cc:
Use named constant for readability.
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sql/item.cc b/sql/item.cc index 45ce1cac961..22b5adc4597 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7647,6 +7647,33 @@ bool Item_cache_datetime::cache_value() str_value.copy(*res); null_value= example->null_value; unsigned_flag= example->unsigned_flag; + + if (!null_value) + { + switch(field_type()) + { + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + { + MYSQL_TIME ltime; + int was_cut; + const timestamp_type tt= + str_to_datetime(str_value.charset(), + str_value.ptr(), + str_value.length(), + <ime, + TIME_DATETIME_ONLY, + &was_cut); + if (tt != MYSQL_TIMESTAMP_DATETIME || was_cut) + null_value= true; + else + my_datetime_to_str(<ime, const_cast<char*>(str_value.ptr())); + } + default: + {} + } + } + return TRUE; } |