diff options
author | Tor Didriksen <tor.didriksen@oracle.com> | 2013-03-14 15:33:25 +0100 |
---|---|---|
committer | Tor Didriksen <tor.didriksen@oracle.com> | 2013-03-14 15:33:25 +0100 |
commit | c70ea724107a53d798026b46f9a6403e468d5926 (patch) | |
tree | a3fcd24bd28fc55e218bf7c6f9274bfd4b608d9d /sql/sql_lex.cc | |
parent | 662feebc92d87a936d16f18ce017cfd3aadeb43a (diff) | |
download | mariadb-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.cc | 35 |
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; } |