Commit d175160b authored by Evgeny Potemkin's avatar Evgeny Potemkin

Bug#37870: Usage of uninitialized value caused failed assertion.

The convert_constant_item function converts a constant to integer using
field for condition like 'field = a_constant'. In some cases the
convert_constant_item is called for a subquery when outer select is already
being executed, so convert_constant_item saves field's value to prevent its
corruption. For EXPLAIN and at the prepare phase field's value isn't
initialized yet, thus when convert_constant_item tries to restore saved
value it fails assertion.

Now the convert_constant_item doesn't save/restore field's value if it's
haven't been read yet. Outer constant values are always saved.

mysql-test/r/explain.result:
  Added a test case for the bug#37870.
mysql-test/t/explain.test:
  Added a test case for the bug#37870.
sql/item_cmpfunc.cc:
  Bug#37870: Usage of uninitialized value caused failed assertion.
  Now the convert_constant_item doesn't save/restore field's value if it's
  haven't been read yet. Outer constant values are always saved.
parent 8cd655de
...@@ -80,7 +80,7 @@ path=`dirname $0` ...@@ -80,7 +80,7 @@ path=`dirname $0`
. "$path/check-cpu" . "$path/check-cpu"
export AM_MAKEFLAGS export AM_MAKEFLAGS
AM_MAKEFLAGS="-j 4" AM_MAKEFLAGS="-j 6"
# SSL library to use.--with-ssl will select our bundled yaSSL # SSL library to use.--with-ssl will select our bundled yaSSL
# implementation of SSL. To use openSSl you will nee too point out # implementation of SSL. To use openSSl you will nee too point out
...@@ -105,7 +105,7 @@ if [ "x$warning_mode" != "xpedantic" ]; then ...@@ -105,7 +105,7 @@ if [ "x$warning_mode" != "xpedantic" ]; then
cxx_warnings="$cxx_warnings -Wreorder" cxx_warnings="$cxx_warnings -Wreorder"
cxx_warnings="$cxx_warnings -Wctor-dtor-privacy -Wnon-virtual-dtor" cxx_warnings="$cxx_warnings -Wctor-dtor-privacy -Wnon-virtual-dtor"
# Added unless --with-debug=full # Added unless --with-debug=full
debug_extra_cflags="-O1 -Wuninitialized" debug_extra_cflags="-O0 -g3 -gdwarf-2" #1 -Wuninitialized"
else else
warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE"
c_warnings="$warnings" c_warnings="$warnings"
......
...@@ -158,15 +158,27 @@ DROP TABLE t1,t2; ...@@ -158,15 +158,27 @@ DROP TABLE t1,t2;
# #
# Bug#37870: Usage of uninitialized value caused failed assertion. # Bug#37870: Usage of uninitialized value caused failed assertion.
# #
create table t1 (dt datetime not null); create table t1 (dt datetime not null, t time not null);
create table t2 (dt datetime not null); create table t2 (dt datetime not null);
insert into t1 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1'); insert into t1 values ('2001-01-01 1:1:1', '1:1:1'),
('2001-01-01 1:1:1', '1:1:1');
insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1'); insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
flush tables; flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL ); EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY INNR ALL NULL NULL NULL NULL 2 Using where 2 DEPENDENT SUBQUERY INNR ALL NULL NULL NULL NULL 2 Using where
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL ); SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
dt dt
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY INNR ALL NULL NULL NULL NULL 2 Using where
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
dt
2001-01-01 01:01:01
2001-01-01 01:01:01
drop tables t1, t2; drop tables t1, t2;
...@@ -126,13 +126,19 @@ DROP TABLE t1,t2; ...@@ -126,13 +126,19 @@ DROP TABLE t1,t2;
--echo # --echo #
--echo # Bug#37870: Usage of uninitialized value caused failed assertion. --echo # Bug#37870: Usage of uninitialized value caused failed assertion.
--echo # --echo #
create table t1 (dt datetime not null); create table t1 (dt datetime not null, t time not null);
create table t2 (dt datetime not null); create table t2 (dt datetime not null);
insert into t1 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1'); insert into t1 values ('2001-01-01 1:1:1', '1:1:1'),
('2001-01-01 1:1:1', '1:1:1');
insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1'); insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
flush tables; flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL ); EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL ); SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
drop tables t1, t2; drop tables t1, t2;
# End of 5.0 tests. # End of 5.0 tests.
...@@ -413,11 +413,15 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, ...@@ -413,11 +413,15 @@ static bool convert_constant_item(THD *thd, Item_field *field_item,
thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/* /*
Store the value of the field/constant if it references an outer field because Store the value of the field/constant if it references an outer field
the call to save_in_field below overrides that value. because the call to save_in_field below overrides that value.
Don't save value of the field for EXPLAIN since it's not initialized. Don't save field value if no data has been read yet.
Outer constant values are always saved.
*/ */
if (field_item->depended_from && (!thd->lex->describe || field_item->const_item())) bool save_field_value= (field_item->depended_from &&
(field_item->const_item() ||
!(field->table->status & STATUS_NO_RECORD)));
if (save_field_value)
orig_field_val= field->val_int(); orig_field_val= field->val_int();
if (!(*item)->is_null() && !(*item)->save_in_field(field, 1)) if (!(*item)->is_null() && !(*item)->save_in_field(field, 1))
{ {
...@@ -428,7 +432,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, ...@@ -428,7 +432,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item,
result= 1; // Item was replaced result= 1; // Item was replaced
} }
/* Restore the original field value. */ /* Restore the original field value. */
if (field_item->depended_from && (!thd->lex->describe || field_item->const_item())) if (save_field_value)
{ {
result= field->store(orig_field_val, TRUE); result= field->store(orig_field_val, TRUE);
/* orig_field_val must be a valid value that can be restored back. */ /* orig_field_val must be a valid value that can be restored back. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment