diff options
author | Galina Shalygina <galina.shalygina@mariadb.com> | 2018-05-12 20:32:16 +0200 |
---|---|---|
committer | Galina Shalygina <galina.shalygina@mariadb.com> | 2018-05-12 20:32:16 +0200 |
commit | 6c0f3dd3414a97266912651fb169f630a36f2659 (patch) | |
tree | 5eefead4a36d975a55cf023e056e64657f13d4e3 /sql/item_cmpfunc.cc | |
parent | 8b26fea83572cf5c043721b7835c3828937f9c27 (diff) | |
download | mariadb-git-6c0f3dd3414a97266912651fb169f630a36f2659.tar.gz |
MDEV-16090: Server crash in in Item_func_in::val_int or assertion `in_item'
failure upon SELECT with impossible condition
The problem appears because of a wrong implementation of the
Item_func_in::build_clone() method. It didn't clone 'array' and 'cmp_fields'
fields for the cloned IN predicate and this could cause crashes.
The Item_func_in::fix_length_and_dec() method was refactored and a new method
named Item_func_in::create_array() was created. It allowed to create 'array'
for cloned IN predicates in a proper way.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 121 |
1 files changed, 75 insertions, 46 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 72a4d99c968..f552a3eca58 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4117,6 +4117,67 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) (uchar *) y->ptr(),y->length()); } + +/* + Create 'array' for this IN predicate with the respect to its result type + and put values from <in value list> in 'array'. +*/ + +bool Item_func_in::create_array(THD *thd) +{ + Item *date_arg= 0; + + switch (m_compare_type) { + case STRING_RESULT: + array=new (thd->mem_root) in_string(thd, arg_count - 1, + (qsort2_cmp) srtcmp_in, + cmp_collation.collation); + break; + case INT_RESULT: + array= new (thd->mem_root) in_longlong(thd, arg_count - 1); + break; + case REAL_RESULT: + array= new (thd->mem_root) in_double(thd, arg_count - 1); + break; + case ROW_RESULT: + /* + The row comparator was created at the beginning but only DATETIME + items comparators were initialized. Call store_value() to setup + others. + */ + ((in_row*)array)->tmp.store_value(args[0]); + break; + case DECIMAL_RESULT: + array= new (thd->mem_root) in_decimal(thd, arg_count - 1); + break; + case TIME_RESULT: + date_arg= find_date_time_item(thd, args, arg_count, 0, true); + array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1); + break; + } + if (!array || thd->is_fatal_error) // OOM + return true; + uint j=0; + for (uint i=1 ; i < arg_count ; i++) + { + array->set(j,args[i]); + if (!args[i]->null_value) + j++; // include this cell in the array. + else + { + /* + We don't put NULL values in array to avoid erronous matches in + bisection. + */ + have_null= 1; + } + } + if ((array->used_count= j)) + array->sort(); + return false; +} + + void Item_func_in::fix_length_and_dec() { Item **arg, **arg_end; @@ -4244,53 +4305,8 @@ void Item_func_in::fix_length_and_dec() m_compare_type= INT_RESULT; } } - switch (m_compare_type) { - case STRING_RESULT: - array=new (thd->mem_root) in_string(thd, arg_count - 1, - (qsort2_cmp) srtcmp_in, - cmp_collation.collation); - break; - case INT_RESULT: - array= new (thd->mem_root) in_longlong(thd, arg_count - 1); - break; - case REAL_RESULT: - array= new (thd->mem_root) in_double(thd, arg_count - 1); - break; - case ROW_RESULT: - /* - The row comparator was created at the beginning but only DATETIME - items comparators were initialized. Call store_value() to setup - others. - */ - ((in_row*)array)->tmp.store_value(args[0]); - break; - case DECIMAL_RESULT: - array= new (thd->mem_root) in_decimal(thd, arg_count - 1); - break; - case TIME_RESULT: - date_arg= find_date_time_item(thd, args, arg_count, 0, true); - array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1); - break; - } - if (!array || thd->is_fatal_error) // OOM + if (create_array(thd)) return; - uint j=0; - for (uint i=1 ; i < arg_count ; i++) - { - array->set(j,args[i]); - if (!args[i]->null_value) - j++; // include this cell in the array. - else - { - /* - We don't put NULL values in array, to avoid erronous matches in - bisection. - */ - have_null= 1; - } - } - if ((array->used_count= j)) - array->sort(); } else { @@ -4399,6 +4415,19 @@ longlong Item_func_in::val_int() } +Item *Item_func_in::build_clone(THD *thd, MEM_ROOT *mem_root) +{ + Item_func_in *clone= (Item_func_in *) Item_func::build_clone(thd, mem_root); + if (clone) + { + if (array && clone->create_array(thd)) + return NULL; + memcpy(&clone->cmp_items, &cmp_items, sizeof(cmp_items)); + } + return clone; +} + + longlong Item_func_bit_or::val_int() { DBUG_ASSERT(fixed == 1); |