mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
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.
This commit is contained in:
@@ -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
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
|
||||||
2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 9 Using filesort
|
2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 9 Using filesort
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@@ -2073,3 +2073,10 @@ SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
|
|||||||
|
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@@ -7066,7 +7066,10 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
|||||||
if (!cond)
|
if (!cond)
|
||||||
cond= new Item_cond_and(eq_list);
|
cond= new Item_cond_and(eq_list);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(cond->type() == Item::COND_ITEM);
|
||||||
((Item_cond *) cond)->add_at_head(&eq_list);
|
((Item_cond *) cond)->add_at_head(&eq_list);
|
||||||
|
}
|
||||||
|
|
||||||
cond->quick_fix_field();
|
cond->quick_fix_field();
|
||||||
cond->update_used_tables();
|
cond->update_used_tables();
|
||||||
@@ -7151,6 +7154,11 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
|||||||
while ((item_equal= it++))
|
while ((item_equal= it++))
|
||||||
{
|
{
|
||||||
cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user