From 5fdb531d77e025cdf1738c424207b13e0a7608f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Aug 2013 17:08:03 +0300 Subject: [PATCH] Fix bug MDEV-4895 Valgrind warnings (Conditional jump or move depends on uninitialised value) in Field_datetime::get_date on GREATEST(..) IS NULL Analysis: The cause of the valgrind warning was an attempt to evaluate a Field that was not yet read. The reason was that on one hand Item_func_isnotnull was marked as constant by Item_func_isnotnull::update_used_tables, and this allowed eval_const_cond() to be called. On the other hand Item_func_isnotnull::val_int() evaluated its argument as if it was not constant. Solution: The fix make sure that Item_func_isnotnull::val_int() doesn't evaluate its argument when it is constant and cannot be NULL, because the result is known in this case. --- mysql-test/r/null.result | 30 ++++++++++++++++++++++++++++++ mysql-test/t/null.test | 28 ++++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 4 ++++ 3 files changed, 62 insertions(+) diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index ac72e1e303e..647b943df1e 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -343,3 +343,33 @@ Field Type Null Key Default Extra IFNULL(NULL, b) decimal(1,0) YES NULL DROP TABLE t1, t2; # End of 5.0 tests +# +# MDEV-4895 Valgrind warnings (Conditional jump or move depends on uninitialised value) in Field_datetime::get_date on GREATEST(..) IS NULL +# +CREATE TABLE t1 (dt DATETIME NOT NULL); +INSERT INTO t1 VALUES (NOW()),(NOW()); +EXPLAIN +SELECT * FROM t1 WHERE concat( dt, '2012-12-21 12:12:12' ) IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +SELECT * FROM t1 WHERE concat( dt, '2012-12-21 12:12:12' ) IS NULL; +dt +drop table t1; +CREATE TABLE t1 (dt INT NOT NULL); +INSERT INTO t1 VALUES (1),(2); +EXPLAIN +SELECT * FROM t1 WHERE concat( dt, '1' ) IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +SELECT * FROM t1 WHERE concat( dt, '1' ) IS NULL; +dt +drop table t1; +CREATE TABLE t1 (dt INT NOT NULL); +INSERT INTO t1 VALUES (1),(2); +EXPLAIN +SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL); +dt +drop table t1; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 2878b54c357..4a45240ec68 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -255,3 +255,31 @@ DESCRIBE t2; DROP TABLE t1, t2; --echo # End of 5.0 tests + +--echo # +--echo # MDEV-4895 Valgrind warnings (Conditional jump or move depends on uninitialised value) in Field_datetime::get_date on GREATEST(..) IS NULL +--echo # + +CREATE TABLE t1 (dt DATETIME NOT NULL); +INSERT INTO t1 VALUES (NOW()),(NOW()); + +EXPLAIN +SELECT * FROM t1 WHERE concat( dt, '2012-12-21 12:12:12' ) IS NULL; +SELECT * FROM t1 WHERE concat( dt, '2012-12-21 12:12:12' ) IS NULL; + +DROP TABLE t1; +CREATE TABLE t1 (dt INT NOT NULL); +INSERT INTO t1 VALUES (1),(2); +EXPLAIN +SELECT * FROM t1 WHERE concat( dt, '1' ) IS NULL; +SELECT * FROM t1 WHERE concat( dt, '1' ) IS NULL; + +DROP TABLE t1; +CREATE TABLE t1 (dt INT NOT NULL); +INSERT INTO t1 VALUES (1),(2); + +EXPLAIN +SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL); +SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL); + +DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index de34a937262..fd688181c92 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4621,6 +4621,8 @@ Item *and_expressions(Item *a, Item *b, Item **org_item) longlong Item_func_isnull::val_int() { DBUG_ASSERT(fixed == 1); + if (const_item() && !args[0]->maybe_null) + return 0; return args[0]->is_null() ? 1: 0; } @@ -4628,6 +4630,8 @@ longlong Item_is_not_null_test::val_int() { DBUG_ASSERT(fixed == 1); DBUG_ENTER("Item_is_not_null_test::val_int"); + if (const_item() && !args[0]->maybe_null) + DBUG_RETURN(1); if (args[0]->is_null()) { DBUG_PRINT("info", ("null"));