From: Tor Didriksen Date: May 25 2011 10:23am Subject: bzr commit into mysql-trunk branch (tor.didriksen:3103) List-Archive: http://lists.mysql.com/commits/138060 Message-Id: <20110525102330.90F333588@atum07.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8264344417289415948==" --===============8264344417289415948== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/didrik/repo/trunk-bug11765255-arraycheck/ based on revid:marko.makela@stripped 3103 Tor Didriksen 2011-05-25 bounds check on ref_ptr_array modified: sql/item.cc sql/item_subselect.cc sql/item_sum.cc sql/sql_array.h sql/sql_base.cc sql/sql_base.h sql/sql_do.cc sql/sql_insert.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_load.cc sql/sql_prepare.cc sql/sql_select.cc sql/sql_select.h sql/sql_union.cc sql/sql_update.cc === modified file 'sql/item.cc' --- a/sql/item.cc 2011-05-18 10:43:46 +0000 +++ b/sql/item.cc 2011-05-25 10:23:24 +0000 @@ -4346,7 +4346,7 @@ resolve_ref_in_select_and_group(THD *thd return NULL; } DBUG_ASSERT((*select_ref)->fixed); - return (select->ref_pointer_array + counter); + return &select->ref_pointer_array[counter]; } if (group_by_ref) return group_by_ref; @@ -6234,13 +6234,13 @@ Item *Item_field::update_value_transform type() != Item::TRIGGER_FIELD_ITEM) { List *all_fields= &select->join->all_fields; - Item **ref_pointer_array= select->ref_pointer_array; + Ref_ptr_array &ref_pointer_array= select->ref_pointer_array; int el= all_fields->elements; Item_ref *ref; ref_pointer_array[el]= (Item*)this; all_fields->push_front((Item*)this); - ref= new Item_ref(&select->context, ref_pointer_array + el, + ref= new Item_ref(&select->context, &ref_pointer_array[el], table_name, field_name); return ref; } === modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2011-04-06 11:13:33 +0000 +++ b/sql/item_subselect.cc 2011-05-25 10:23:24 +0000 @@ -1126,7 +1126,7 @@ Item_in_subselect::single_value_transfor (ALL && (> || =>)) || (ANY && (< || =<)) for ALL condition is inverted */ - item= new Item_sum_max(*select_lex->ref_pointer_array); + item= new Item_sum_max(select_lex->ref_pointer_array[0]); } else { @@ -1134,11 +1134,11 @@ Item_in_subselect::single_value_transfor (ALL && (< || =<)) || (ANY && (> || =>)) for ALL condition is inverted */ - item= new Item_sum_min(*select_lex->ref_pointer_array); + item= new Item_sum_min(select_lex->ref_pointer_array[0]); } if (upper_item) upper_item->set_sum_test(item); - *select_lex->ref_pointer_array= item; + select_lex->ref_pointer_array[0]= item; { List_iterator it(select_lex->item_list); it++; @@ -1220,7 +1220,8 @@ Item_in_subselect::single_value_transfor DBUG_RETURN(RES_OK); /* Perform the IN=>EXISTS transformation. */ - DBUG_RETURN(single_value_in_to_exists_transformer(join, func)); + const trans_res retval= single_value_in_to_exists_transformer(join, func); + DBUG_RETURN(retval); } @@ -1274,8 +1275,8 @@ Item_in_subselect::single_value_in_to_ex Item *item= func->create(expr, new Item_ref_null_helper(&select_lex->context, this, - select_lex-> - ref_pointer_array, + &select_lex-> + ref_pointer_array[0], (char *)"", this->full_name())); if (!abort_on_null && left_expr->maybe_null) @@ -1393,7 +1394,7 @@ Item_in_subselect::single_value_in_to_ex Item *new_having= func->create(expr, new Item_ref_null_helper(&select_lex->context, this, - select_lex->ref_pointer_array, + &select_lex->ref_pointer_array[0], (char *)"", (char *)"")); if (!abort_on_null && left_expr->maybe_null) @@ -1570,14 +1571,14 @@ Item_in_subselect::row_value_in_to_exist (char *)in_left_expr_name), new Item_ref(&select_lex->context, - select_lex->ref_pointer_array + i, + &select_lex->ref_pointer_array[i], (char *)"", (char *)"") ); Item *item_isnull= new Item_func_isnull(new Item_ref(&select_lex->context, - select_lex->ref_pointer_array+i, + &select_lex->ref_pointer_array[i], (char *)"", (char *)"") ); @@ -1592,8 +1593,8 @@ Item_in_subselect::row_value_in_to_exist Item *item_nnull_test= new Item_is_not_null_test(this, new Item_ref(&select_lex->context, - select_lex-> - ref_pointer_array + i, + &select_lex-> + ref_pointer_array[i], (char *)"", (char *)"")); if (!abort_on_null && left_expr->element_index(i)->maybe_null) @@ -1648,8 +1649,8 @@ Item_in_subselect::row_value_in_to_exist (char *)in_left_expr_name), new Item_direct_ref(&select_lex->context, - select_lex-> - ref_pointer_array+i, + &select_lex-> + ref_pointer_array[i], (char *)"", (char *)"") ); @@ -1659,7 +1660,7 @@ Item_in_subselect::row_value_in_to_exist new Item_is_not_null_test(this, new Item_ref(&select_lex->context, - select_lex->ref_pointer_array + i, + &select_lex->ref_pointer_array[i], (char *)"", (char *)"")); @@ -1667,8 +1668,8 @@ Item_in_subselect::row_value_in_to_exist item_isnull= new Item_func_isnull(new Item_direct_ref(&select_lex->context, - select_lex-> - ref_pointer_array+i, + &select_lex-> + ref_pointer_array[i], (char *)"", (char *)"") ); === modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2011-04-12 10:31:30 +0000 +++ b/sql/item_sum.cc 2011-05-25 10:23:24 +0000 @@ -3306,7 +3306,8 @@ bool Item_func_group_concat::setup(THD * tmp table columns. */ if (arg_count_order && - setup_order(thd, args, context->table_list, list, all_fields, *order)) + setup_order(thd, Ref_ptr_array(args, arg_count), + context->table_list, list, all_fields, *order)) DBUG_RETURN(TRUE); count_field_types(select_lex, tmp_table_param, all_fields, 0); === modified file 'sql/sql_array.h' --- a/sql/sql_array.h 2010-11-05 22:14:29 +0000 +++ b/sql/sql_array.h 2011-05-25 10:23:24 +0000 @@ -18,6 +18,61 @@ #include +/** + A wrapper class which provides array bounds checking. + We do *not* own the array, we simply have a pointer to the first element, + and a length. + + @remark + We want the compiler-generated versions of + - the copy CTOR (memberwise initialization) + - the assignment operator (memberwise assignment) + + @param Element_type The type of the elements of the container. + Elements must be copyable. + */ +template class Bounds_checked_array +{ +public: + Bounds_checked_array() : m_array(NULL), m_size(0) {} + + Bounds_checked_array(Element_type *el, size_t size) + : m_array(el), m_size(size) + {} + + void reset() { m_array= NULL; m_size= 0; } + + Element_type &operator[](size_t n) + { + DBUG_ASSERT(n < m_size); + return m_array[n]; + } + + const Element_type &operator[](size_t n) const + { + DBUG_ASSERT(n < m_size); + return m_array[n]; + } + + size_t element_size() const { return sizeof(Element_type); } + size_t size() const { return m_size; } + + operator bool() const { return m_array != NULL; } + + void pop_front() + { + DBUG_ASSERT(m_size > 0); + m_array+= 1; + m_size-= 1; + } + + Element_type *array() const { return m_array; } + +private: + Element_type *m_array; + size_t m_size; +}; + /* A typesafe wrapper around DYNAMIC_ARRAY */ === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2011-05-21 08:25:33 +0000 +++ b/sql/sql_base.cc 2011-05-25 10:23:24 +0000 @@ -8002,7 +8002,7 @@ int setup_wild(THD *thd, TABLE_LIST *tab ** Check that all given fields exists and fill struct with current data ****************************************************************************/ -bool setup_fields(THD *thd, Item **ref_pointer_array, +bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &fields, enum_mark_columns mark_used_columns, List *sum_func_list, bool allow_sum_func) { @@ -8033,7 +8033,7 @@ bool setup_fields(THD *thd, Item **ref_p ref_pointer_array */ if (ref_pointer_array) - bzero(ref_pointer_array, sizeof(Item *) * fields.elements); + bzero(ref_pointer_array.array(), sizeof(Item *) * fields.elements); /* We call set_entry() there (before fix_fields() of the whole list of field @@ -8051,7 +8051,7 @@ bool setup_fields(THD *thd, Item **ref_p while ((var= li++)) var->set_entry(thd, FALSE); - Item **ref= ref_pointer_array; + Ref_ptr_array ref= ref_pointer_array; thd->lex->current_select->cur_pos_in_select_list= 0; while ((item= it++)) { @@ -8065,10 +8065,13 @@ bool setup_fields(THD *thd, Item **ref_p DBUG_RETURN(TRUE); /* purecov: inspected */ } if (ref) - *(ref++)= item; + { + ref[0]= item; + ref.pop_front(); + } if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && sum_func_list) - item->split_sum_func(thd, ref_pointer_array, *sum_func_list); + item->split_sum_func(thd, ref_pointer_array.array(), *sum_func_list); thd->used_tables|= item->used_tables(); thd->lex->current_select->cur_pos_in_select_list++; } === modified file 'sql/sql_base.h' --- a/sql/sql_base.h 2011-05-04 07:51:15 +0000 +++ b/sql/sql_base.h 2011-05-25 10:23:24 +0000 @@ -184,7 +184,7 @@ bool insert_fields(THD *thd, Name_resolu List_iterator *it, bool any_privileges); int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, List *sum_func_list, uint wild_num); -bool setup_fields(THD *thd, Item** ref_pointer_array, +bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &item, enum_mark_columns mark_used_columns, List *sum_func_list, bool allow_sum_func); bool fill_record(THD *thd, Field **field, List &values, @@ -350,7 +350,7 @@ inline TABLE_LIST *find_table_in_local_l } -inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, +inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, List &item, enum_mark_columns mark_used_columns, List *sum_func_list, === modified file 'sql/sql_do.cc' --- a/sql/sql_do.cc 2010-07-27 15:01:56 +0000 +++ b/sql/sql_do.cc 2011-05-25 10:23:24 +0000 @@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List &valu List_iterator li(values); Item *value; DBUG_ENTER("mysql_do"); - if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0)) DBUG_RETURN(TRUE); while ((value = li++)) value->val_int(); === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2011-05-21 08:25:33 +0000 +++ b/sql/sql_insert.cc 2011-05-25 10:23:24 +0000 @@ -256,7 +256,7 @@ static int check_insert_fields(THD *thd, */ table_list->next_local= 0; context->resolve_in_table_list_only(table_list); - res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0); + res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0); /* Restore the current context. */ ctx_state.restore_state(context, table_list); @@ -347,7 +347,8 @@ static int check_update_fields(THD *thd, } /* Check the fields we are going to modify */ - if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + update_fields, MARK_COLUMNS_WRITE, 0, 0)) return -1; if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE && @@ -762,7 +763,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto abort; } - if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0)) goto abort; } its.rewind (); @@ -1377,7 +1378,8 @@ bool mysql_prepare_insert(THD *thd, TABL table_list->next_local= 0; context->resolve_in_table_list_only(table_list); - res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_READ, 0, 0) || check_insert_fields(thd, context->table_list, fields, *values, !insert_into_view, 0, &map)); @@ -1393,7 +1395,8 @@ bool mysql_prepare_insert(THD *thd, TABL } if (!res) - res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0); + res= setup_fields(thd, Ref_ptr_array(), + update_values, MARK_COLUMNS_READ, 0, 0); if (!res && duplic == DUP_UPDATE) { @@ -3231,7 +3234,7 @@ select_insert::prepare(List &value /* Errors during check_insert_fields() should not be ignored. */ lex->current_select->no_error= FALSE; - res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) || check_insert_fields(thd, table_list, *fields, values, !insert_into_view, 1, &map)); @@ -3279,7 +3282,7 @@ select_insert::prepare(List &value table_list->next_name_resolution_table= ctx_state.get_first_name_resolution_table(); - res= res || setup_fields(thd, 0, *info.update_values, + res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values, MARK_COLUMNS_READ, 0, 0); if (!res) { === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2011-04-01 14:04:52 +0000 +++ b/sql/sql_lex.cc 2011-05-25 10:23:24 +0000 @@ -1732,6 +1732,8 @@ void st_select_lex_unit::init_query() void st_select_lex::init_query() { + DBUG_ENTER("st_select_lex::init_query"); + DBUG_PRINT("info", ("this %p", this)); st_select_lex_node::init_query(); table_list.empty(); top_join_list.empty(); @@ -1757,7 +1759,7 @@ void st_select_lex::init_query() parent_lex->push_context(&context); cond_count= between_count= with_wild= 0; max_equal_elems= 0; - ref_pointer_array= 0; + ref_pointer_array.reset(); select_n_where_fields= 0; select_n_having_items= 0; subquery_in_having= explicit_limit= 0; @@ -1769,15 +1771,19 @@ void st_select_lex::init_query() exclude_from_table_unique_test= no_wrap_view_item= FALSE; nest_level= 0; link_next= 0; + DBUG_VOID_RETURN; } void st_select_lex::init_select() { + DBUG_ENTER("st_select_lex::init_select"); + DBUG_PRINT("info", ("this %p", this)); st_select_lex_node::init_select(); sj_nests.empty(); group_list.empty(); type= db= 0; having= 0; + //m_select_n_having_items= 0; // didrik ??? table_join_options= 0; in_sum_expr= with_wild= 0; options= 0; @@ -1800,6 +1806,7 @@ void st_select_lex::init_select() cond_value= having_value= Item::COND_UNDEF; inner_refs_list.empty(); full_group_by_flag= 0; + DBUG_VOID_RETURN; } /* @@ -2132,20 +2139,33 @@ ulong st_select_lex::get_table_join_opti bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { - if (ref_pointer_array) - return 0; + DBUG_ENTER("st_select_lex::setup_ref_array"); /* We have to create array in prepared statement memory if it is 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; + uint n_elems= (n_child_sum_items + + item_list.elements + + select_n_having_items + + select_n_where_fields + + order_group_num) * 5; + DBUG_PRINT("info", ("setup_ref_array %4u : %4u %4u %4u %4u %4u", + n_elems, + n_child_sum_items, + item_list.elements, + select_n_having_items, + select_n_where_fields, + order_group_num)); + if (ref_pointer_array) { + DBUG_ASSERT(ref_pointer_array.size() == n_elems); + DBUG_RETURN(0); + } + Item **array= (Item **)arena->alloc(sizeof(Item*) * n_elems); + ref_pointer_array= Ref_ptr_array(array, n_elems); + + DBUG_RETURN(array == NULL); } === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2011-05-12 17:29:19 +0000 +++ b/sql/sql_lex.h 2011-05-25 10:23:24 +0000 @@ -24,6 +24,7 @@ #include "sql_trigger.h" #include "item.h" /* From item_subselect.h: subselect_union_engine */ #include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */ +#include "sql_array.h" /* YACC and LEX Definitions */ @@ -602,6 +603,7 @@ public: }; typedef class st_select_lex_unit SELECT_LEX_UNIT; +typedef Bounds_checked_array Ref_ptr_array; /* SELECT_LEX - store information of parsed SELECT statment @@ -656,7 +658,7 @@ public: SQL_I_List *gorder_list; Item *select_limit, *offset_limit; /* LIMIT clause parameters */ // Arrays of pointers to top elements of all_fields list - Item **ref_pointer_array; + Ref_ptr_array ref_pointer_array; /* number of items in select_list and HAVING clause used to get number === modified file 'sql/sql_load.cc' --- a/sql/sql_load.cc 2011-05-12 17:29:19 +0000 +++ b/sql/sql_load.cc 2011-05-25 10:23:24 +0000 @@ -268,15 +268,18 @@ int mysql_load(THD *thd,sql_exchange *ex Let us also prepare SET clause, altough it is probably empty in this case. */ - if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + set_fields, MARK_COLUMNS_WRITE, 0, 0) || + setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) DBUG_RETURN(TRUE); } else { // Part field list /* TODO: use this conds for 'WITH CHECK OPTIONS' */ - if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || + if (setup_fields(thd, Ref_ptr_array(), + fields_vars, MARK_COLUMNS_WRITE, 0, 0) || + setup_fields(thd, Ref_ptr_array(), + set_fields, MARK_COLUMNS_WRITE, 0, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* @@ -295,7 +298,7 @@ int mysql_load(THD *thd,sql_exchange *ex } } /* Fix the expressions in SET clause */ - if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) DBUG_RETURN(TRUE); } === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2011-05-21 09:31:19 +0000 +++ b/sql/sql_prepare.cc 2011-05-25 10:23:24 +0000 @@ -1294,7 +1294,7 @@ static bool mysql_test_insert(Prepared_s my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto error; } - if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0)) goto error; } } @@ -1373,7 +1373,8 @@ static int mysql_test_update(Prepared_st table_list->register_want_access(want_privilege); #endif thd->lex->select_lex.no_wrap_view_item= TRUE; - res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0); + res= setup_fields(thd, Ref_ptr_array(), + select->item_list, MARK_COLUMNS_READ, 0, 0); thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) goto error; @@ -1384,7 +1385,8 @@ static int mysql_test_update(Prepared_st (SELECT_ACL & ~table_list->table->grant.privilege); table_list->register_want_access(SELECT_ACL); #endif - if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) goto error; /* TODO: here we should send types of placeholders to the client. */ DBUG_RETURN(0); @@ -1530,7 +1532,8 @@ static bool mysql_test_do_fields(Prepare if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL)) DBUG_RETURN(TRUE); - DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0)); + DBUG_RETURN(setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_NONE, 0, 0)); } === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2011-05-18 10:43:46 +0000 +++ b/sql/sql_select.cc 2011-05-25 10:23:24 +0000 @@ -203,7 +203,7 @@ static int remove_dup_with_hash_index(TH static bool cmp_buffer_with_ref(THD *thd, TABLE *table, TABLE_REF *tab_ref); static bool setup_new_fields(THD *thd, List &fields, List &all_fields, ORDER *new_order); -static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array, +static ORDER *create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array, ORDER *order, List &fields, List &all_fields, bool *all_order_by_fields_used); @@ -213,12 +213,12 @@ static void calc_group_buffer(JOIN *join static bool make_group_fields(JOIN *main_join, JOIN *curr_join); static bool alloc_group_fields(JOIN *join,ORDER *group); // Create list for using with tempory table -static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, +static bool change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &new_list1, List &new_list2, uint elements, List &items); // Create list for using with tempory table -static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, +static bool change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &new_list1, List &new_list2, uint elements, List &items); @@ -460,7 +460,7 @@ bool handle_select(THD *thd, LEX *lex, s bool fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, - Item **ref_pointer_array, ORDER *group_list) + Ref_ptr_array ref_pointer_array, ORDER *group_list) { Item_outer_ref *ref; @@ -487,7 +487,7 @@ fix_inner_refs(THD *thd, List &all If it's needed reset each Item_ref item that refers this field with a new reference taken from ref_pointer_array. */ - item_ref= ref_pointer_array + el; + item_ref= &ref_pointer_array[el]; } if (ref->in_sum_func) @@ -546,7 +546,7 @@ fix_inner_refs(THD *thd, List &all /** Function to setup clauses without sum functions. */ -inline int setup_without_group(THD *thd, Item **ref_pointer_array, +inline int setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, TABLE_LIST *leaves, List &fields, @@ -600,7 +600,7 @@ inline int setup_without_group(THD *thd, 0 on success */ int -JOIN::prepare(Item ***rref_pointer_array, +JOIN::prepare(Ref_ptr_array *rref_pointer_array, TABLE_LIST *tables_init, uint wild_num, Item *conds_init, uint og_num, ORDER *order_init, ORDER *group_init, @@ -647,15 +647,24 @@ JOIN::prepare(Item ***rref_pointer_array table_ptr= table_ptr->next_leaf) tables++; - if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || - select_lex->setup_ref_array(thd, og_num) || - setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ, - &all_fields, 1) || - setup_without_group(thd, (*rref_pointer_array), tables_list, + if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num)) + DBUG_RETURN(-1); + + // find_order_in_list() may need some extra space!! + if (select_lex->setup_ref_array(thd, og_num*2)) + DBUG_RETURN(-1); + + // Freeze ref_pointer_array !!! + select_lex->parsing_place= NO_MATTER; + + if (setup_fields(thd, *rref_pointer_array, fields_list, MARK_COLUMNS_READ, + &all_fields, 1)) + DBUG_RETURN(-1); + if (setup_without_group(thd, (*rref_pointer_array), tables_list, select_lex->leaf_tables, fields_list, all_fields, &conds, order, group_list, &hidden_group_fields)) - DBUG_RETURN(-1); /* purecov: inspected */ + DBUG_RETURN(-1); ref_pointer_array= *rref_pointer_array; @@ -712,14 +721,14 @@ JOIN::prepare(Item ***rref_pointer_array real_order= TRUE; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) - item->split_sum_func(thd, ref_pointer_array, all_fields); + item->split_sum_func(thd, ref_pointer_array.array(), all_fields); } if (!real_order) order= NULL; } if (having && having->with_sum_func) - having->split_sum_func2(thd, ref_pointer_array, all_fields, + having->split_sum_func2(thd, ref_pointer_array.array(), all_fields, &having, TRUE); if (select_lex->inner_sum_func_list) { @@ -728,7 +737,7 @@ JOIN::prepare(Item ***rref_pointer_array do { item_sum= item_sum->next; - item_sum->split_sum_func2(thd, ref_pointer_array, + item_sum->split_sum_func2(thd, ref_pointer_array.array(), all_fields, item_sum->ref_by, FALSE); } while (item_sum != end); } @@ -755,7 +764,7 @@ JOIN::prepare(Item ***rref_pointer_array int el= all_fields.elements; ref_pointer_array[el]= field; all_fields.push_front(field); - ord->item= ref_pointer_array + el; + ord->item= &ref_pointer_array[el]; } } } @@ -824,7 +833,6 @@ JOIN::prepare(Item ***rref_pointer_array /* Init join struct */ count_field_types(select_lex, &tmp_table_param, all_fields, 0); - ref_pointer_array_size= all_fields.elements*sizeof(Item*); this->group= group_list != 0; unit= unit_arg; @@ -3034,7 +3042,8 @@ JOIN::exec() curr_join->all_fields= *curr_all_fields; if (!items1) { - items1= items0 + all_fields.elements; + items1= Ref_ptr_array(&ref_pointer_array[2 * all_fields.elements], + all_fields.elements); if (sort_and_group || curr_tmp_table->group || tmp_table_param.precomputed_group_by) { @@ -3199,7 +3208,8 @@ JOIN::exec() // No sum funcs anymore if (!items2) { - items2= items1 + all_fields.elements; + items2= Ref_ptr_array(&ref_pointer_array[3 * all_fields.elements], + all_fields.elements); if (change_to_use_tmp_fields(thd, items2, tmp_fields_list2, tmp_all_fields2, fields_list.elements, tmp_all_fields1)) @@ -3256,7 +3266,8 @@ JOIN::exec() { if (!items0) init_items_ref_array(); - items3= ref_pointer_array + (all_fields.elements*4); + items3= Ref_ptr_array(&ref_pointer_array[4 * all_fields.elements], + all_fields.elements); setup_copy_fields(thd, &curr_join->tmp_table_param, items3, tmp_fields_list3, tmp_all_fields3, curr_fields_list->elements, *curr_all_fields); @@ -3609,7 +3620,7 @@ void JOIN::cleanup_item_list(List */ bool -mysql_select(THD *thd, Item ***rref_pointer_array, +mysql_select(THD *thd, Ref_ptr_array *rref_pointer_array, TABLE_LIST *tables, uint wild_num, List &fields, Item *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulonglong select_options, @@ -21087,7 +21098,7 @@ cp_buffer_from_ref(THD *thd, TABLE *tabl */ static bool -find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, ORDER *order, List &fields, List &all_fields, bool is_group_field) { @@ -21111,7 +21122,7 @@ find_order_in_list(THD *thd, Item **ref_ order_item->full_name(), thd->where); return TRUE; } - order->item= ref_pointer_array + count - 1; + order->item= &ref_pointer_array[count - 1]; order->in_field_list= 1; order->counter= count; order->counter_used= 1; @@ -21172,7 +21183,7 @@ find_order_in_list(THD *thd, Item **ref_ 'shadowed' a table field with the same name, the table field will be chosen over the derived field. */ - order->item= ref_pointer_array + counter; + order->item= &ref_pointer_array[counter]; order->in_field_list=1; return FALSE; } @@ -21230,7 +21241,7 @@ find_order_in_list(THD *thd, Item **ref_ 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; + order->item= &ref_pointer_array[el]; return FALSE; } @@ -21242,7 +21253,7 @@ find_order_in_list(THD *thd, Item **ref_ the field list. */ -int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order) { thd->where="order clause"; @@ -21283,7 +21294,7 @@ int setup_order(THD *thd, Item **ref_poi */ int -setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, bool *hidden_group_fields) { @@ -21414,13 +21425,14 @@ setup_new_fields(THD *thd, List &f */ ORDER * -create_distinct_group(THD *thd, Item **ref_pointer_array, +create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array, ORDER *order_list, List &fields, List &all_fields, bool *all_order_by_fields_used) { List_iterator li(fields); - Item *item, **orig_ref_pointer_array= ref_pointer_array; + Item *item; + Ref_ptr_array orig_ref_pointer_array= ref_pointer_array; ORDER *order,*group,**prev; *all_order_by_fields_used= 1; @@ -21474,7 +21486,7 @@ create_distinct_group(THD *thd, Item **r int el= all_fields.elements; orig_ref_pointer_array[el]= new_item; all_fields.push_front(new_item); - ord->item= orig_ref_pointer_array + el; + ord->item= &orig_ref_pointer_array[el]; } else { @@ -21483,14 +21495,14 @@ create_distinct_group(THD *thd, Item **r simple indexing of ref_pointer_array (order in the array and in the list are same) */ - ord->item= ref_pointer_array; + ord->item= &ref_pointer_array[0]; } ord->direction= ORDER::ORDER_ASC; *prev=ord; prev= &ord->next; } next_item: - ref_pointer_array++; + ref_pointer_array.pop_front(); } *prev=0; return group; @@ -21805,7 +21817,7 @@ int test_if_item_cache_changed(List &res_selected_fields, List &res_all_fields, uint elements, List &all_fields) { @@ -22086,7 +22098,7 @@ bool JOIN::make_sum_func_list(List */ static bool -change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, +change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &res_selected_fields, List &res_all_fields, uint elements, List &all_fields) @@ -22177,7 +22189,7 @@ change_to_use_tmp_fields(THD *thd, Item */ static bool -change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, +change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &res_selected_fields, List &res_all_fields, uint elements, List &all_fields) @@ -22552,15 +22564,20 @@ bool JOIN::rollup_init() */ tmp_table_param.group_parts= send_group_parts; - if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) + - sizeof(Item**) + - sizeof(List) + - ref_pointer_array_size) - * send_group_parts ))) - return 1; - - rollup.fields= (List*) (rollup.null_items + send_group_parts); - rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); + Item_null_result **null_items= + static_cast(thd->alloc(sizeof(Item*)*send_group_parts)); + + rollup.null_items=Item_null_array(null_items, send_group_parts); + rollup.ref_pointer_arrays= + static_cast + (thd->alloc((sizeof(Ref_ptr_array) + + all_fields.elements * sizeof(Item*)) * send_group_parts)); + rollup.fields= + static_cast*>(thd->alloc(sizeof(List) * send_group_parts)); + + if (!rollup.null_items || !rollup.ref_pointer_arrays || !rollup.fields) + return true; + ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); /* @@ -22572,7 +22589,7 @@ bool JOIN::rollup_init() rollup.null_items[i]= new (thd->mem_root) Item_null_result(); List *rollup_fields= &rollup.fields[i]; rollup_fields->empty(); - rollup.ref_pointer_arrays[i]= ref_array; + rollup.ref_pointer_arrays[i]= Ref_ptr_array(ref_array, all_fields.elements); ref_array+= all_fields.elements; } for (i= 0 ; i < send_group_parts; i++) @@ -22718,11 +22735,11 @@ bool JOIN::rollup_make_fields(List bool real_fields= 0; Item *item; List_iterator new_it(rollup.fields[pos]); - Item **ref_array_start= rollup.ref_pointer_arrays[pos]; + Ref_ptr_array ref_array_start= rollup.ref_pointer_arrays[pos]; ORDER *start_group; /* Point to first hidden field */ - Item **ref_array= ref_array_start + fields_arg.elements-1; + Item **ref_array= &ref_array_start[fields_arg.elements-1]; /* Remember where the sum functions ends for the previous level */ sum_funcs_end[pos+1]= *func; @@ -22739,7 +22756,7 @@ bool JOIN::rollup_make_fields(List if (item == first_field) { real_fields= 1; // End of hidden fields - ref_array= ref_array_start; + ref_array= &ref_array_start[0]; } if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() && @@ -22823,9 +22840,7 @@ int JOIN::rollup_send_data(uint idx) for (i= send_group_parts ; i-- > idx ; ) { /* Get reference pointers to sum functions in place */ - memcpy((char*) ref_pointer_array, - (char*) rollup.ref_pointer_arrays[i], - ref_pointer_array_size); + copy_ref_ptr_array(ref_pointer_array, rollup.ref_pointer_arrays[i]); if ((!having || having->val_int())) { if (send_records < unit->select_limit_cnt && do_send_rows && @@ -22865,9 +22880,7 @@ int JOIN::rollup_write_data(uint idx, TA for (i= send_group_parts ; i-- > idx ; ) { /* Get reference pointers to sum functions in place */ - memcpy((char*) ref_pointer_array, - (char*) rollup.ref_pointer_arrays[i], - ref_pointer_array_size); + copy_ref_ptr_array(ref_pointer_array, rollup.ref_pointer_arrays[i]); if ((!having || having->val_int())) { int write_error; === modified file 'sql/sql_select.h' --- a/sql/sql_select.h 2011-05-18 10:43:46 +0000 +++ b/sql/sql_select.h 2011-05-25 10:23:24 +0000 @@ -1598,12 +1598,14 @@ typedef struct st_position : public Sql_ } POSITION; +typedef Bounds_checked_array Item_null_array; + typedef struct st_rollup { enum State { STATE_NONE, STATE_INITED, STATE_READY }; State state; - Item_null_result **null_items; - Item ***ref_pointer_arrays; + Item_null_array null_items; + Ref_ptr_array *ref_pointer_arrays; List *fields; } ROLLUP; @@ -1879,10 +1881,15 @@ public: FirstMatch strategy. */ JOIN_TAB *return_tab; - Item **ref_pointer_array; /// &all_fields, List &send_fields, bool before_group_by, bool recompute= FALSE); - inline void set_items_ref_array(Item **ptr) + void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr) + { + DBUG_ASSERT(dst_arr.size() >= src_arr.size()); + void *dest= dst_arr.array(); + const void *src= src_arr.array(); + memcpy(dest, src, src_arr.size() * src_arr.element_size()); + } + inline void set_items_ref_array(Ref_ptr_array ptr) { - memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size); + copy_ref_ptr_array(ref_pointer_array, ptr); current_ref_pointer_array= ptr; } inline void init_items_ref_array() { - items0= ref_pointer_array + all_fields.elements; - memcpy(items0, ref_pointer_array, ref_pointer_array_size); + items0= Ref_ptr_array(&ref_pointer_array[all_fields.elements], + all_fields.elements); + copy_ref_ptr_array(items0, Ref_ptr_array(&ref_pointer_array[0], + all_fields.elements)); current_ref_pointer_array= items0; } @@ -2073,7 +2093,7 @@ void free_tmp_table(THD *thd, TABLE *ent void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, List &fields, bool reset_with_sum_func); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, - Item **ref_pointer_array, + Ref_ptr_array ref_pointer_array, List &new_list1, List &new_list2, uint elements, List &fields); void copy_fields(TMP_TABLE_PARAM *param); @@ -2262,17 +2282,17 @@ Item *remove_eq_conds(THD *thd, Item *co int get_quick_record(SQL_SELECT *select); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length, SORT_FIELD *sortorder); -int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order); -int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, bool *hidden_group_fields); bool fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, - Item **ref_pointer_array, ORDER *group_list= NULL); + Ref_ptr_array ref_pointer_array, ORDER *group_list= NULL); bool handle_select(THD *thd, LEX *lex, select_result *result, ulong setup_tables_done_option); -bool mysql_select(THD *thd, Item ***rref_pointer_array, +bool mysql_select(THD *thd, Ref_ptr_array *rref_pointer_array, TABLE_LIST *tables, uint wild_num, List &list, Item *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulonglong select_type, === modified file 'sql/sql_union.cc' --- a/sql/sql_union.cc 2011-03-17 17:39:31 +0000 +++ b/sql/sql_union.cc 2011-05-25 10:23:24 +0000 @@ -836,6 +836,9 @@ bool st_select_lex::cleanup() { bool error= FALSE; DBUG_ENTER("st_select_lex::cleanup()"); + DBUG_PRINT("info", ("this %p", this)); + + parsing_place= NO_MATTER; // didrik: here or in reinit_stmt_before_use if (join) { === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2011-05-12 17:29:19 +0000 +++ b/sql/sql_update.cc 2011-05-25 10:23:24 +0000 @@ -328,7 +328,8 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; table_list->register_want_access(want_privilege); #endif - if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0)) + if (setup_fields_with_no_wrap(thd, Ref_ptr_array(), + fields, MARK_COLUMNS_WRITE, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ if (table_list->view && check_fields(thd, fields)) { @@ -359,7 +360,7 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif - if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0)) { free_underlaid_joins(thd, select_lex); DBUG_RETURN(1); /* purecov: inspected */ @@ -1148,7 +1149,8 @@ int mysql_multi_update_prepare(THD *thd) UPDATE_ACL, SELECT_ACL)) DBUG_RETURN(TRUE); - if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0)) + if (setup_fields_with_no_wrap(thd, Ref_ptr_array(), + *fields, MARK_COLUMNS_WRITE, 0, 0)) DBUG_RETURN(TRUE); for (tl= table_list; tl ; tl= tl->next_local) @@ -1422,7 +1424,8 @@ int multi_update::prepare(List &no reference tables */ - int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0); + int error= setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_READ, 0, 0); for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf) { --===============8264344417289415948== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/tor.didriksen@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: tor.didriksen@stripped\ # f3bpae2ynnvuz0u6 # target_branch: file:///export/home/didrik/repo/trunk-bug11765255-\ # arraycheck/ # testament_sha1: 50fc072105ec0e5ccc9c2b63fb9888aee6dbaef4 # timestamp: 2011-05-25 12:23:30 +0200 # base_revision_id: marko.makela@stripped\ # vjmufmstzrymzwfg # # Begin bundle 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 --===============8264344417289415948==--