From 07ef11b2cce540ccc09cb6ef8cf3d080a1c28926 Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Fri, 10 May 2013 19:18:21 +0530 Subject: [PATCH] Bug#16119355:PREPARED STATEMENT: READ OF FREED MEMORY WITH STRING CONVERSION FUNCTIONS Reverting fix for Bug#16119355 in 5.1 as this needs two patches from 5.5+ to work for a certain case --- sql/item_func.h | 7 --- sql/sql_select.cc | 106 ++++++++++++++++++---------------------------- 2 files changed, 41 insertions(+), 72 deletions(-) diff --git a/sql/item_func.h b/sql/item_func.h index c3ef3d12d71..22fb38e176d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1391,13 +1391,6 @@ public: :Item_func(b), cached_result_type(INT_RESULT), entry(NULL), entry_thread_id(0), name(a) {} - Item_func_set_user_var(THD *thd, Item_func_set_user_var *item) - :Item_func(thd, item), cached_result_type(item->cached_result_type), - entry(item->entry), entry_thread_id(item->entry_thread_id), - value(item->value), decimal_buff(item->decimal_buff), - null_item(item->null_item), save_result(item->save_result), - name(item->name) - {} enum Functype functype() const { return SUSERVAR_FUNC; } double val_real(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fabf2c81cc1..7b1a8cf9e82 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15779,88 +15779,64 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, res_selected_fields.empty(); res_all_fields.empty(); - uint border= all_fields.elements - elements; - for (uint i= 0; (item= it++); i++) + uint i, border= all_fields.elements - elements; + for (i= 0; (item= it++); i++) { Field *field; - if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) + + if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) || + (item->type() == Item::FUNC_ITEM && + ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC)) item_field= item; - else if (item->type() == Item::FIELD_ITEM) - item_field= item->get_tmp_table_item(thd); - else if (item->type() == Item::FUNC_ITEM && - ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC) + else { - field= item->get_tmp_table_field(); - if( field != NULL) + if (item->type() == Item::FIELD_ITEM) { - /* - Replace "@:=" with "@:=". Otherwise, we - would re-evaluate , and if expression were a subquery, this - would access already-unlocked tables. - */ - Item_func_set_user_var* suv= - new Item_func_set_user_var(thd, (Item_func_set_user_var*) item); - Item_field *new_field= new Item_field(field); - if (!suv || !new_field) - DBUG_RETURN(true); // Fatal error - /* - We are replacing the argument of Item_func_set_user_var after its value - has been read. The argument's null_value should be set by now, so we - must set it explicitly for the replacement argument since the null_value - may be read without any preceeding call to val_*(). - */ - new_field->update_null_value(); - List list; - list.push_back(new_field); - suv->set_arguments(list); - item_field= suv; + item_field= item->get_tmp_table_item(thd); + } + else if ((field= item->get_tmp_table_field())) + { + if (item->type() == Item::SUM_FUNC_ITEM && field->table->group) + item_field= ((Item_sum*) item)->result_item(field); + else + item_field= (Item*) new Item_field(field); + if (!item_field) + DBUG_RETURN(TRUE); // Fatal error + + if (item->real_item()->type() != Item::FIELD_ITEM) + field->orig_table= 0; + item_field->name= item->name; + if (item->type() == Item::REF_ITEM) + { + Item_field *ifield= (Item_field *) item_field; + Item_ref *iref= (Item_ref *) item; + ifield->table_name= iref->table_name; + ifield->db_name= iref->db_name; + } +#ifndef DBUG_OFF + if (!item_field->name) + { + char buff[256]; + String str(buff,sizeof(buff),&my_charset_bin); + str.length(0); + item->print(&str, QT_ORDINARY); + item_field->name= sql_strmake(str.ptr(),str.length()); + } +#endif } else item_field= item; } - else if ((field= item->get_tmp_table_field())) - { - if (item->type() == Item::SUM_FUNC_ITEM && field->table->group) - item_field= ((Item_sum*) item)->result_item(field); - else - item_field= (Item*) new Item_field(field); - if (!item_field) - DBUG_RETURN(true); // Fatal error - - if (item->real_item()->type() != Item::FIELD_ITEM) - field->orig_table= 0; - item_field->name= item->name; - if (item->type() == Item::REF_ITEM) - { - Item_field *ifield= (Item_field *) item_field; - Item_ref *iref= (Item_ref *) item; - ifield->table_name= iref->table_name; - ifield->db_name= iref->db_name; - } -#ifndef DBUG_OFF - if (!item_field->name) - { - char buff[256]; - String str(buff,sizeof(buff),&my_charset_bin); - str.length(0); - item->print(&str, QT_ORDINARY); - item_field->name= sql_strmake(str.ptr(),str.length()); - } -#endif - } - else - item_field= item; - res_all_fields.push_back(item_field); ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]= item_field; } List_iterator_fast itr(res_all_fields); - for (uint i= 0; i < border; i++) + for (i= 0; i < border; i++) itr++; itr.sublist(res_selected_fields, elements); - DBUG_RETURN(false); + DBUG_RETURN(FALSE); }