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 */