From 96badb16afcf8a6ae3d03918419fc51ace4be236 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 31 Jul 2015 22:09:46 +0200 Subject: [PATCH] MDEV-7821 Server crashes in Item_func_group_concat::fix_fields on 2nd execution of PS Correct fix for this bug. The problem was that Item_func_group_concat() was calling setup_order(), passing args as the second argument, ref_pointer_array. While ref_pointer_array should have free space at the end, as setup_order() can append elements to it. In this particular case args[] elements were overwritten when setup_order() was pushing new elements into ref_pointer_array. --- sql/item_sum.cc | 16 ++++++++++------ sql/item_sum.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a24307b131bf0..9000289fd339d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3300,8 +3300,6 @@ void Item_func_group_concat::cleanup() from Item_func_group_concat::setup() to point to runtime created objects, we need to reset them back to the original arguments of the function. - - The very same applies to args array. */ ORDER **order_ptr= order; for (uint i= 0; i < arg_count_order; i++) @@ -3309,7 +3307,6 @@ void Item_func_group_concat::cleanup() (*order_ptr)->item= &args[arg_count_field + i]; order_ptr++; } - memcpy(args, orig_args, sizeof(Item *) * arg_count); DBUG_VOID_RETURN; } @@ -3517,9 +3514,16 @@ bool Item_func_group_concat::setup(THD *thd) "all_fields". The resulting field list is used as input to create tmp table columns. */ - if (arg_count_order && - setup_order(thd, args, context->table_list, list, all_fields, *order)) - DBUG_RETURN(TRUE); + if (arg_count_order) + { + uint n_elems= arg_count_order + all_fields.elements; + ref_pointer_array= static_cast(thd->alloc(sizeof(Item*) * n_elems)); + memcpy(ref_pointer_array, args, arg_count * sizeof(Item*)); + if (!ref_pointer_array || + setup_order(thd, ref_pointer_array, context->table_list, list, + all_fields, *order)) + DBUG_RETURN(TRUE); + } count_field_types(select_lex, tmp_table_param, all_fields, 0); tmp_table_param->force_copy_fields= force_copy_fields; diff --git a/sql/item_sum.h b/sql/item_sum.h index f074cc6c822b1..86093f5d4f58d 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1394,6 +1394,7 @@ class Item_func_group_concat : public Item_sum String *separator; TREE tree_base; TREE *tree; + Item **ref_pointer_array; /** If DISTINCT is used with this GROUP_CONCAT, this member is used to filter