Commit 8ba5a687 authored by unknown's avatar unknown
Browse files

Fixed bug#17366: Unchecked Item_int results in server crash

When there is conjunction of conds, the substitute_for_best_equal_field()
will call the eliminate_item_equal() function in loop to build final
expression. But if eliminate_item_equal() finds that some cond will always
evaluate to 0, then that cond will be substituted by Item_int with value ==
0. In this case on the next iteration eliminate_item_equal() will get that 
Item_int and treat it as Item_cond. This is leads to memory corruption and
server crash on cleanup phase.

To the eliminate_item_equal() function was added DBUG_ASSERT for checking
that all items treaten as Item_cond are really Item_cond.
The substitute_for_best_equal_field() now checks that if
eliminate_item_equal() returns Item_int and it's value is 0 then this 
value is returned as the result of whole conjunction.


mysql-test/t/subselect.test:
  Added test for bug#17366: Unchecked Item_int results in server crash
mysql-test/r/subselect.result:
   Added test for bug#17366: Unchecked Item_int results in server crash
sql/sql_select.cc:
  Fixed bug#17366: Unchecked Item_int results in server crash
   
  To the eliminate_item_equal() function was added DBUG_ASSERT for checking
  that all items treaten as Item_cond are really Item_cond.
  The substitute_for_best_equal_field() now checks that if
  eliminate_item_equal() returns something other than Item_cond and if it is
  then this value is returned as the result of whole conjunction.
parent 19ed1c4b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3157,3 +3157,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	9	Using where
2	DEPENDENT SUBQUERY	t1	index	NULL	a	8	NULL	9	Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
select tt.t from (select 'crash1' as t, f2 from t1) as tt left join t1 on tt.t = 'crash2' and tt.f2 = t1.f2 where tt.t = 'crash1';
t
crash1
crash1
drop table t1;
+7 −0
Original line number Diff line number Diff line
@@ -2073,3 +2073,10 @@ SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);

DROP TABLE t1;

#
# Bug#17366: Unchecked Item_int results in server crash
#
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
select tt.t from (select 'crash1' as t, f2 from t1) as tt left join t1 on tt.t = 'crash2' and tt.f2 = t1.f2 where tt.t = 'crash1';
drop table t1;
+8 −0
Original line number Diff line number Diff line
@@ -7066,7 +7066,10 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
  if (!cond)
    cond= new Item_cond_and(eq_list);
  else
  {
    DBUG_ASSERT(cond->type() == Item::COND_ITEM);
    ((Item_cond *) cond)->add_at_head(&eq_list);
  }

  cond->quick_fix_field();
  cond->update_used_tables();
@@ -7151,6 +7154,11 @@ static COND* substitute_for_best_equal_field(COND *cond,
      while ((item_equal= it++))
      {
        cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
        // This occurs when eliminate_item_equal() founds that cond is
        // always false and substitues it with Item_int 0.
        // Due to this, value of item_equal will be 0, so just return it.
        if (cond->type() != Item::ITEM_COND)
          break;
      }
    }
  }