summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
authorTor Didriksen <tor.didriksen@oracle.com>2012-03-14 13:25:14 +0100
committerTor Didriksen <tor.didriksen@oracle.com>2012-03-14 13:25:14 +0100
commit13053fbe54534cfc8d673c55459d368f7da4694f (patch)
tree89a4ce6fd8cf69097195b200cbdef6b91bd37489 /sql/item.cc
parent1a2e4afe355759e9c8259a3ff79c2509dfd54bb0 (diff)
downloadmariadb-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.cc27
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(),
+ &ltime,
+ TIME_DATETIME_ONLY,
+ &was_cut);
+ if (tt != MYSQL_TIMESTAMP_DATETIME || was_cut)
+ null_value= true;
+ else
+ my_datetime_to_str(&ltime, const_cast<char*>(str_value.ptr()));
+ }
+ default:
+ {}
+ }
+ }
+
return TRUE;
}