Commit 25f78956 authored by Michael Widenius's avatar Michael Widenius

Fixed unlikely reference to freed memory in item->print().


sql/item.cc:
  If a item_ref is referenced by name, we have to reset it's ref in item_ref::cleanup() as the reference may be to a memory that is freed.
  This happens at least when you have 'HAVING MAX()' in a sub query and you execute 'cond_having->print()' which tries to access items before fix fields.
sql/item.h:
  Added 'reference_trough_name' as a marker for Item_ref that needs to have ref reset during cleanup
parent 33ec8526
...@@ -1495,6 +1495,11 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, ...@@ -1495,6 +1495,11 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
*/ */
Item_aggregate_ref *item_ref; Item_aggregate_ref *item_ref;
uint el= fields.elements; uint el= fields.elements;
/*
If this is an item_ref, get the original item
This is a safety measure if this is called for things that is
already a reference.
*/
Item *real_itm= real_item(); Item *real_itm= real_item();
ref_pointer_array[el]= real_itm; ref_pointer_array[el]= real_itm;
...@@ -5907,7 +5912,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, ...@@ -5907,7 +5912,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
const char *field_name_arg, const char *field_name_arg,
bool alias_name_used_arg) bool alias_name_used_arg)
:Item_ident(context_arg, NullS, table_name_arg, field_name_arg), :Item_ident(context_arg, NullS, table_name_arg, field_name_arg),
result_field(0), ref(item) result_field(0), ref(item), reference_trough_name(0)
{ {
alias_name_used= alias_name_used_arg; alias_name_used= alias_name_used_arg;
/* /*
...@@ -5950,7 +5955,7 @@ class Dependency_marker: public Field_enumerator ...@@ -5950,7 +5955,7 @@ class Dependency_marker: public Field_enumerator
Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item, Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item,
const char *field_name_arg, bool alias_name_used_arg) const char *field_name_arg, bool alias_name_used_arg)
:Item_ident(view_arg, field_name_arg), :Item_ident(view_arg, field_name_arg),
result_field(NULL), ref(item) result_field(NULL), ref(item), reference_trough_name(0)
{ {
alias_name_used= alias_name_used_arg; alias_name_used= alias_name_used_arg;
/* /*
...@@ -6033,6 +6038,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -6033,6 +6038,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (!ref || ref == not_found_item) if (!ref || ref == not_found_item)
{ {
DBUG_ASSERT(reference_trough_name != 0);
if (!(ref= resolve_ref_in_select_and_group(thd, this, if (!(ref= resolve_ref_in_select_and_group(thd, this,
context->select_lex))) context->select_lex)))
goto error; /* Some error occurred (e.g. ambiguous names). */ goto error; /* Some error occurred (e.g. ambiguous names). */
...@@ -6308,6 +6314,11 @@ void Item_ref::cleanup() ...@@ -6308,6 +6314,11 @@ void Item_ref::cleanup()
DBUG_ENTER("Item_ref::cleanup"); DBUG_ENTER("Item_ref::cleanup");
Item_ident::cleanup(); Item_ident::cleanup();
result_field= 0; result_field= 0;
if (reference_trough_name)
{
/* We have to reset the reference as it may been freed */
ref= 0;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -2417,11 +2417,12 @@ class Item_ref :public Item_ident ...@@ -2417,11 +2417,12 @@ class Item_ref :public Item_ident
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF }; enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */ Field *result_field; /* Save result here */
Item **ref; Item **ref;
bool reference_trough_name;
Item_ref(Name_resolution_context *context_arg, Item_ref(Name_resolution_context *context_arg,
const char *db_arg, const char *table_name_arg, const char *db_arg, const char *table_name_arg,
const char *field_name_arg) const char *field_name_arg)
:Item_ident(context_arg, db_arg, table_name_arg, field_name_arg), :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
result_field(0), ref(0) {} result_field(0), ref(0), reference_trough_name(1) {}
/* /*
This constructor is used in two scenarios: This constructor is used in two scenarios:
A) *item = NULL A) *item = NULL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment