From 0e6560398cea2e3277a7384d86186b0cb65ecfb2 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 22 Jun 2010 22:53:08 +0400 Subject: Bug#54477: Crash on IN / CASE with NULL arguments Incorrect handling of NULL arguments could lead to a crash on the IN or CASE operations when either NULL arguments were passed explicitly as arguments (IN) or implicitly generated by the WITH ROLLUP modifier (both IN and CASE). Item_func_case::find_item() assumed all necessary comparators to be instantiated in fix_length_and_dec(). However, in the presence of WITH ROLLUP modifier, arguments could be substituted with an Item_null leading to an "unexpected" STRING_RESULT comparator being invoked. In addition to the problem identical to the above, Item_func_in::val_int() could crash even with explicitly passed NULL arguments due to an optimization in fix_length_and_dec() leading to NULL arguments being ignored during comparators creation. mysql-test/r/func_in.result: Test cases for bug#54477. mysql-test/t/func_in.test: Test cases for bug#54477. sql/item_cmpfunc.cc: Added additional checks for Item_nulls in Item_func_case::find_item() and Item_func_in::val_int(). --- sql/item_cmpfunc.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6e38220abd1..9ff72d56050 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2773,6 +2773,8 @@ Item *Item_func_case::find_item(String *str) /* Compare every WHEN argument with it and return the first match */ for (uint i=0 ; i < ncases ; i+=2) { + if (args[i]->real_item()->type() == NULL_ITEM) + continue; cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); DBUG_ASSERT(cmp_type != ROW_RESULT); DBUG_ASSERT(cmp_items[(uint)cmp_type]); @@ -4002,9 +4004,17 @@ longlong Item_func_in::val_int() return (longlong) (!null_value && tmp != negated); } + if ((null_value= args[0]->real_item()->type() == NULL_ITEM)) + return 0; + have_null= 0; for (uint i= 1 ; i < arg_count ; i++) { + if (args[i]->real_item()->type() == NULL_ITEM) + { + have_null= TRUE; + continue; + } Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); in_item= cmp_items[(uint)cmp_type]; DBUG_ASSERT(in_item); -- cgit v1.2.1