mirror of
https://github.com/MariaDB/server.git
synced 2025-04-29 21:37:04 +03:00
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.
This commit is contained in:
parent
f48306344a
commit
07e95b39c4
@ -750,4 +750,24 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# Bug#54477: Crash on IN / CASE with NULL arguments
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
SELECT 1 IN (NULL, a) FROM t1;
|
||||||
|
1 IN (NULL, a)
|
||||||
|
1
|
||||||
|
NULL
|
||||||
|
SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
a IN (a, a)
|
||||||
|
1
|
||||||
|
1
|
||||||
|
NULL
|
||||||
|
SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
CASE a WHEN a THEN a END
|
||||||
|
1
|
||||||
|
2
|
||||||
|
NULL
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
@ -539,6 +539,21 @@ EXPLAIN SELECT * FROM t1 WHERE c_char IN (NULL, NULL);
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#54477: Crash on IN / CASE with NULL arguments
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
|
||||||
|
SELECT 1 IN (NULL, a) FROM t1;
|
||||||
|
|
||||||
|
SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
@ -2773,6 +2773,8 @@ Item *Item_func_case::find_item(String *str)
|
|||||||
/* Compare every WHEN argument with it and return the first match */
|
/* Compare every WHEN argument with it and return the first match */
|
||||||
for (uint i=0 ; i < ncases ; i+=2)
|
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());
|
cmp_type= item_cmp_type(left_result_type, args[i]->result_type());
|
||||||
DBUG_ASSERT(cmp_type != ROW_RESULT);
|
DBUG_ASSERT(cmp_type != ROW_RESULT);
|
||||||
DBUG_ASSERT(cmp_items[(uint)cmp_type]);
|
DBUG_ASSERT(cmp_items[(uint)cmp_type]);
|
||||||
@ -4002,9 +4004,17 @@ longlong Item_func_in::val_int()
|
|||||||
return (longlong) (!null_value && tmp != negated);
|
return (longlong) (!null_value && tmp != negated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((null_value= args[0]->real_item()->type() == NULL_ITEM))
|
||||||
|
return 0;
|
||||||
|
|
||||||
have_null= 0;
|
have_null= 0;
|
||||||
for (uint i= 1 ; i < arg_count ; i++)
|
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());
|
Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type());
|
||||||
in_item= cmp_items[(uint)cmp_type];
|
in_item= cmp_items[(uint)cmp_type];
|
||||||
DBUG_ASSERT(in_item);
|
DBUG_ASSERT(in_item);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user