diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 766f3b6bfaa0cc68ed1dfae83c019b81862814a9..ae48eb1e0ff2d8c868cafddbbd0d4938115196a2 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -995,6 +995,7 @@ SELECT 1 FROM 1 1 DROP TABLE t1; +End of 5.0 tests # # Bug #52397: another crash with explain extended and group_concat # @@ -1010,4 +1011,22 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 select 1 AS `1` from (select group_concat(`test`.`t1`.`a` order by `test`.`t1`.`a` ASC separator ',') AS `GROUP_CONCAT(t1.a ORDER BY t1.a ASC)` from `test`.`t1` `t2` join `test`.`t1` group by `test`.`t1`.`a`) `d` DROP TABLE t1; -End of 5.0 tests +# +# Bug #54476: crash when group_concat and 'with rollup' in prepared statements +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index e832ea316eb1356a5f289559119c8aca3ae9e485..926c1f92855e20da7d2d843ef0bf579347fbe9b1 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -708,6 +708,7 @@ SELECT 1 FROM DROP TABLE t1; +--echo End of 5.0 tests --echo # --echo # Bug #52397: another crash with explain extended and group_concat @@ -719,5 +720,18 @@ EXPLAIN EXTENDED SELECT 1 FROM t1 t2, t1 GROUP BY t1.a) AS d; DROP TABLE t1; +--echo # +--echo # Bug #54476: crash when group_concat and 'with rollup' in prepared statements +--echo # ---echo End of 5.0 tests +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 228e36fc9f9c807196ca844c5df08f7663117085..1048bd3d6ff9a6925aec686b799c7ce354a7fc88 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3034,7 +3034,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, tree(item->tree), unique_filter(item->unique_filter), table(item->table), - order(item->order), context(item->context), arg_count_order(item->arg_count_order), arg_count_field(item->arg_count_field), @@ -3047,6 +3046,24 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, { quick_group= item->quick_group; result.set_charset(collation.collation); + + /* + Since the ORDER structures pointed to by the elements of the 'order' array + may be modified in find_order_in_list() called from + Item_func_group_concat::setup(), create a copy of those structures so that + such modifications done in this object would not have any effect on the + object being copied. + */ + ORDER *tmp; + if (!(order= (ORDER **) thd->alloc(sizeof(ORDER *) * arg_count_order + + sizeof(ORDER) * arg_count_order))) + return; + tmp= (ORDER *)(order + arg_count_order); + for (uint i= 0; i < arg_count_order; i++, tmp++) + { + memcpy(tmp, item->order[i], sizeof(ORDER)); + order[i]= tmp; + } } diff --git a/sql/table.h b/sql/table.h index 3ef3c5e0cb24fac18c8da1616bbec63b93f650a0..9088b3b69651a47ba6d13f3b1c0648e5864cdf8a 100644 --- a/sql/table.h +++ b/sql/table.h @@ -55,7 +55,6 @@ typedef struct st_order { struct st_order *next; Item **item; /* Point at item in select fields */ Item *item_ptr; /* Storage for initial item */ - Item **item_copy; /* For SPs; the original item ptr */ int counter; /* position in SELECT list, correct only if counter_used is true*/ bool asc; /* true if ascending */