#At file:///export/home/didrik/repo/5.5-foo/ based on revid:joerg@stripped
3326 Tor Didriksen 2011-02-15
Bug #11766860 - 60085: CRASH IN ITEM::SAVE_IN_FIELD() WITH TIME DATA TYPE
This assumption in Item_cache_datetime::cache_value_int
was wrong:
- /* Assume here that the underlying item will do correct conversion.*/
- int_value= example->val_int_result();
@ mysql-test/r/subselect_innodb.result
New test case.
@ mysql-test/t/subselect_innodb.test
New test case.
@ sql/item.cc
In Item_cache_datetime::cache_value_int()
- call get_time() or get_date() depending on desired type
- convert the returned MYSQL_TIME value to longlong depending on desired type
@ sql/item.h
The cached int_value in Item_cache_datetime should not be unsigned:
- it is used mostly in signed context
- it can actually have negative value (for TIME data type)
@ sql/item_subselect.cc
Add some DBUG_TRACE for easier bug-hunting.
modified:
mysql-test/r/subselect_innodb.result
mysql-test/t/subselect_innodb.test
sql/item.cc
sql/item.h
sql/item_subselect.cc
=== modified file 'mysql-test/r/subselect_innodb.result'
--- a/mysql-test/r/subselect_innodb.result 2006-01-26 16:54:34 +0000
+++ b/mysql-test/r/subselect_innodb.result 2011-02-15 10:27:30 +0000
@@ -245,3 +245,12 @@ x
NULL
drop procedure p1;
drop tables t1,t2,t3;
+#
+# Bug#60085 crash in Item::save_in_field() with time data type
+#
+CREATE TABLE t1(a date, b int, unique(b), unique(a), key(b)) engine=innodb;
+INSERT INTO t1 VALUES ('2011-05-13', 0);
+SELECT 1 FROM t1 WHERE b < (SELECT CAST(a as date) FROM t1 GROUP BY a);
+1
+1
+DROP TABLE t1;
=== modified file 'mysql-test/t/subselect_innodb.test'
--- a/mysql-test/t/subselect_innodb.test 2006-01-26 16:54:34 +0000
+++ b/mysql-test/t/subselect_innodb.test 2011-02-15 10:27:30 +0000
@@ -238,3 +238,12 @@ call p1();
call p1();
drop procedure p1;
drop tables t1,t2,t3;
+
+--echo #
+--echo # Bug#60085 crash in Item::save_in_field() with time data type
+--echo #
+
+CREATE TABLE t1(a date, b int, unique(b), unique(a), key(b)) engine=innodb;
+INSERT INTO t1 VALUES ('2011-05-13', 0);
+SELECT 1 FROM t1 WHERE b < (SELECT CAST(a as date) FROM t1 GROUP BY a);
+DROP TABLE t1;
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2011-01-12 12:58:47 +0000
+++ b/sql/item.cc 2011-02-15 10:27:30 +0000
@@ -1059,7 +1059,9 @@ int Item::save_in_field_no_warnings(Fiel
ulonglong sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+
res= save_in_field(field, no_conversions);
+
thd->count_cuted_fields= tmp;
dbug_tmp_restore_column_map(table->write_set, old_map);
thd->variables.sql_mode= sql_mode;
@@ -7462,16 +7464,43 @@ longlong Item_cache_int::val_int()
bool Item_cache_datetime::cache_value_int()
{
if (!example)
- return FALSE;
+ return false;
- value_cached= TRUE;
+ value_cached= true;
// Mark cached string value obsolete
- str_value_cached= FALSE;
- /* Assume here that the underlying item will do correct conversion.*/
- int_value= example->val_int_result();
+ str_value_cached= false;
+
+ MYSQL_TIME ltime;
+ const bool eval_error=
+ (field_type() == MYSQL_TYPE_TIME) ?
+ example->get_time(<ime) :
+ example->get_date(<ime, TIME_FUZZY_DATE);
+
+ if (eval_error)
+ int_value= 0;
+ else
+ {
+ switch(field_type())
+ {
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ int_value= TIME_to_ulonglong_datetime(<ime);
+ break;
+ case MYSQL_TYPE_TIME:
+ int_value= TIME_to_ulonglong_time(<ime);
+ break;
+ default:
+ int_value= TIME_to_ulonglong_date(<ime);
+ break;
+ }
+ if (ltime.neg)
+ int_value= -int_value;
+ }
+
null_value= example->null_value;
unsigned_flag= example->unsigned_flag;
- return TRUE;
+
+ return true;
}
=== modified file 'sql/item.h'
--- a/sql/item.h 2011-02-08 15:47:33 +0000
+++ b/sql/item.h 2011-02-15 10:27:30 +0000
@@ -3449,7 +3449,7 @@ class Item_cache_datetime: public Item_c
{
protected:
String str_value;
- ulonglong int_value;
+ longlong int_value;
bool str_value_cached;
public:
Item_cache_datetime(enum_field_types field_type_arg):
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2011-01-12 12:15:22 +0000
+++ b/sql/item_subselect.cc 2011-02-15 10:27:30 +0000
@@ -256,30 +256,31 @@ bool Item_subselect::walk(Item_processor
bool Item_subselect::exec()
{
- int res;
+ DBUG_ENTER("Item_subselect::exec");
/*
Do not execute subselect in case of a fatal error
or if the query has been killed.
*/
if (thd->is_error() || thd->killed)
- return 1;
+ DBUG_RETURN(true);
DBUG_ASSERT(!thd->lex->context_analysis_only);
/*
Simulate a failure in sub-query execution. Used to test e.g.
out of memory or query being killed conditions.
*/
- DBUG_EXECUTE_IF("subselect_exec_fail", return 1;);
+ DBUG_EXECUTE_IF("subselect_exec_fail", DBUG_RETURN(true););
- res= engine->exec();
+ bool res= engine->exec();
if (engine_changed)
{
engine_changed= 0;
- return exec();
+ res= exec();
+ DBUG_RETURN(res);
}
- return (res);
+ DBUG_RETURN(res);
}
Item::Type Item_subselect::type() const
Attachment: [text/bzr-bundle] bzr/tor.didriksen@oracle.com-20110215102730-rpuhq1lo9jsv2llr.bundle