From 47f0135d7aba57d160d1d95ff7f1f6b7bb07c2fb Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 26 Sep 2023 08:54:34 -0700 Subject: [PATCH] MDEV-32245 Test from subselect.test fails with statement memory protection With this patch st_select_lex::ref_pointer_array is never re-allocated. Approved by Oleksandr Byelkin --- sql/sql_lex.cc | 55 +++++++++++++++++++++++--------------------------- sql/sql_lex.h | 3 +++ 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 019377061a0..dfb9580721a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2413,6 +2413,7 @@ void st_select_lex::init_query() max_equal_elems= 0; ref_pointer_array.reset(); select_n_where_fields= 0; + order_group_num= 0; select_n_reserved= 0; select_n_having_items= 0; n_sum_items= 0; @@ -2978,46 +2979,40 @@ ulong st_select_lex::get_table_join_options() } -bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) +uint st_select_lex::get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg) { - if (!((options & SELECT_DISTINCT) && !group_list.elements)) hidden_bit_fields= 0; - // find_order_in_list() may need some extra space, so multiply by two. - order_group_num*= 2; + if (!order_group_num) + order_group_num= order_group_num_arg; /* - We have to create array in prepared statement memory if it is a - prepared statement + find_order_in_list() may need some extra space, + so multiply order_group_num by 2 */ - Query_arena *arena= thd->stmt_arena; - const size_t n_elems= (n_sum_items + - n_child_sum_items + - item_list.elements + - select_n_reserved + - select_n_having_items + - select_n_where_fields + - order_group_num + - hidden_bit_fields + - fields_in_window_functions) * (size_t) 5; - DBUG_ASSERT(n_elems % 5 == 0); + uint n= n_sum_items + + n_child_sum_items + + item_list.elements + + select_n_reserved + + select_n_having_items + + select_n_where_fields + + order_group_num * 2 + + hidden_bit_fields + + fields_in_window_functions; + return n; +} + + +bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) +{ + uint n_elems= get_cardinality_of_ref_ptrs_slice(order_group_num) * 5; if (!ref_pointer_array.is_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; - } - Item **array= static_cast(arena->alloc(sizeof(Item*) * n_elems)); + return false; + Item **array= static_cast(thd->stmt_arena->alloc(sizeof(Item*) * + n_elems)); if (likely(array != NULL)) ref_pointer_array= Ref_ptr_array(array, n_elems); - return array == NULL; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a2c5fec03e5..d47f196d679 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1176,6 +1176,8 @@ public: and all inner subselects. */ uint select_n_where_fields; + /* Total number of elements in group by and order by lists */ + uint order_group_num; /* reserved for exists 2 in */ uint select_n_reserved; /* @@ -1416,6 +1418,7 @@ public: init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); + uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg); void print(THD *thd, String *str, enum_query_type query_type); void print_item_list(THD *thd, String *str, enum_query_type query_type); void print_set_clause(THD *thd, String *str, enum_query_type query_type);