Commit 08ecbd5a authored by Tor Didriksen's avatar Tor Didriksen

Bug#11765255 - 58201: VALGRIND/CRASH WHEN ORDERING BY MULTIPLE AGGREGATE FUNCTIONS

We must allocate a larger ref_pointer_array. We failed to account for extra
items allocated here:
#0  find_order_in_list 
  uint el= all_fields.elements;
  all_fields.push_front(order_item); /* Add new field to field list. */
  ref_pointer_array[el]= order_item;
  order->item= ref_pointer_array + el;
#1  setup_order
#2  setup_without_group
#3  JOIN::prepare


mysql-test/r/order_by.result:
  New test case.
mysql-test/r/union.result:
  New test case.
mysql-test/t/order_by.test:
  New test case.
mysql-test/t/union.test:
  New test case.
sql/sql_lex.cc:
  find_order_in_list() may need some extra space, so multiply og_num by two.
sql/sql_union.cc:
  For UNION, the 'n_sum_items' are accumulated in the "global_parameters" select_lex.
  This number must be propagated to setup_ref_array()
  
  When preparing a 'fake_select_lex' we need to use global_parameters->order_list
  rather than fake_select_lex->order_list (see comments inside st_select_lex_unit::cleanup)
parent e1fbd911
...@@ -1664,4 +1664,11 @@ a 1 ...@@ -1664,4 +1664,11 @@ a 1
3 1 3 1
2 1 2 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug#11765255 58201:
# VALGRIND/CRASH WHEN ORDERING BY MULTIPLE AGGREGATE FUNCTIONS
#
select 1 order by max(1) + min(1);
1
1
End of 5.1 tests End of 5.1 tests
...@@ -1647,4 +1647,61 @@ b ...@@ -1647,4 +1647,61 @@ b
1 1
2 2
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug#11765255 58201:
# VALGRIND/CRASH WHEN ORDERING BY MULTIPLE AGGREGATE FUNCTIONS
#
select 1 as foo
union
select 2
union
select 3
union
select 4
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
;
foo
1
prepare stmt1 from 'select 1 as foo
union
select 2
union
select 3
union
select 4
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
';
execute stmt1;
foo
1
execute stmt1;
foo
1
select 1 as foo
union
select 2
union
select 3
union
(select 4)
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
;
foo
1
prepare stmt1 from 'select 1 as foo
union
select 2
union
select 3
union
(select 4)
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
';
execute stmt1;
foo
1
execute stmt1;
foo
1
deallocate prepare stmt1;
End of 5.1 tests End of 5.1 tests
...@@ -1508,4 +1508,11 @@ SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC; ...@@ -1508,4 +1508,11 @@ SELECT DISTINCT a,1 FROM t1 WHERE a <> 1 ORDER BY a DESC;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#11765255 58201:
--echo # VALGRIND/CRASH WHEN ORDERING BY MULTIPLE AGGREGATE FUNCTIONS
--echo #
select 1 order by max(1) + min(1);
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -1156,4 +1156,45 @@ SELECT * FROM t2 UNION SELECT * FROM t2 ...@@ -1156,4 +1156,45 @@ SELECT * FROM t2 UNION SELECT * FROM t2
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # Bug#11765255 58201:
--echo # VALGRIND/CRASH WHEN ORDERING BY MULTIPLE AGGREGATE FUNCTIONS
--echo #
let $my_stmt=
select 1 as foo
union
select 2
union
select 3
union
select 4
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
;
eval $my_stmt;
eval prepare stmt1 from '$my_stmt';
execute stmt1;
execute stmt1;
let $my_stmt=
select 1 as foo
union
select 2
union
select 3
union
(select 4)
order by max(42) + max(1) + max(1) + max(1) + max(1) + max(1)
;
eval $my_stmt;
eval prepare stmt1 from '$my_stmt';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -1987,6 +1987,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) ...@@ -1987,6 +1987,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
if (ref_pointer_array) if (ref_pointer_array)
return 0; return 0;
// find_order_in_list() may need some extra space, so multiply by two.
order_group_num*= 2;
/* /*
We have to create array in prepared statement memory if it is We have to create array in prepared statement memory if it is
prepared statement prepared statement
......
/* /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -403,15 +402,27 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, ...@@ -403,15 +402,27 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
fake_select_lex->table_list.empty(); fake_select_lex->table_list.empty();
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
/*
Fake st_select_lex should have item list for correct ref_array
allocation.
*/
fake_select_lex->item_list= item_list; fake_select_lex->item_list= item_list;
thd_arg->lex->current_select= fake_select_lex; thd_arg->lex->current_select= fake_select_lex;
/*
We need to add up n_sum_items in order to make the correct
allocation in setup_ref_array().
*/
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
saved_error= fake_select_lex->join-> saved_error= fake_select_lex->join->
prepare(&fake_select_lex->ref_pointer_array, prepare(&fake_select_lex->ref_pointer_array,
fake_select_lex->table_list.first, fake_select_lex->table_list.first,
0, 0, 0, 0,
fake_select_lex->order_list.elements, global_parameters->order_list.elements, // og_num
fake_select_lex->order_list.first, global_parameters->order_list.first, // order
NULL, NULL, NULL, NULL, NULL, NULL,
fake_select_lex, this); fake_select_lex, this);
fake_select_lex->table_list.empty(); fake_select_lex->table_list.empty();
...@@ -579,11 +590,21 @@ bool st_select_lex_unit::exec() ...@@ -579,11 +590,21 @@ bool st_select_lex_unit::exec()
} }
fake_select_lex->join->no_const_tables= TRUE; fake_select_lex->join->no_const_tables= TRUE;
/* /*
Fake st_select_lex should have item list for correctref_array Fake st_select_lex should have item list for correct ref_array
allocation. allocation.
*/ */
fake_select_lex->item_list= item_list; fake_select_lex->item_list= item_list;
/*
We need to add up n_sum_items in order to make the correct
allocation in setup_ref_array().
Don't add more sum_items if we have already done JOIN::prepare
for this (with a different join object)
*/
if (!fake_select_lex->ref_pointer_array)
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array, saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list, &result_table_list,
0, item_list, NULL, 0, item_list, NULL,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment