summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
authorTor Didriksen <tor.didriksen@oracle.com>2013-03-14 15:33:25 +0100
committerTor Didriksen <tor.didriksen@oracle.com>2013-03-14 15:33:25 +0100
commitc70ea724107a53d798026b46f9a6403e468d5926 (patch)
treea3fcd24bd28fc55e218bf7c6f9274bfd4b608d9d /sql/sql_lex.cc
parent662feebc92d87a936d16f18ce017cfd3aadeb43a (diff)
downloadmariadb-git-c70ea724107a53d798026b46f9a6403e468d5926.tar.gz
Bug#16359402 CRASH WITH AGGREGATES: ASSERTION FAILED: N < M_SIZE
We need to take 'n_sum_items' into the calculation when allocating the ref_ptr_array.
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc35
1 files changed, 25 insertions, 10 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index bf0982efddd..ac5ec1ba1e4 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
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
@@ -1758,6 +1758,7 @@ void st_select_lex::init_query()
cond_count= between_count= with_wild= 0;
max_equal_elems= 0;
ref_pointer_array= 0;
+ ref_pointer_array_size= 0;
select_n_where_fields= 0;
select_n_having_items= 0;
n_child_sum_items= 0;
@@ -2134,9 +2135,6 @@ ulong st_select_lex::get_table_join_options()
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
- if (ref_pointer_array)
- return 0;
-
// find_order_in_list() may need some extra space, so multiply by two.
order_group_num*= 2;
@@ -2145,12 +2143,29 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
prepared statement
*/
Query_arena *arena= thd->stmt_arena;
- return (ref_pointer_array=
- (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
- item_list.elements +
- select_n_having_items +
- select_n_where_fields +
- order_group_num)*5)) == 0;
+ const uint n_elems= (n_sum_items +
+ n_child_sum_items +
+ item_list.elements +
+ select_n_having_items +
+ select_n_where_fields +
+ order_group_num) * 5;
+ if (ref_pointer_array != NULL)
+ {
+ /*
+ We need to take 'n_sum_items' into account when allocating the array,
+ and this may actually increase during the optimization phase due to
+ MIN/MAX rewrite in Item_in_subselect::single_value_transformer.
+ In the usual case we can reuse the array from the prepare phase.
+ If we need a bigger array, we must allocate a new one.
+ */
+ if (ref_pointer_array_size >= n_elems)
+ return false;
+ }
+ ref_pointer_array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems));
+ if (ref_pointer_array != NULL)
+ ref_pointer_array_size= n_elems;
+
+ return ref_pointer_array == NULL;
}