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,
*/
Item_aggregate_ref *item_ref;
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();
ref_pointer_array[el]= real_itm;
......@@ -5907,7 +5912,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
const char *field_name_arg,
bool alias_name_used_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;
/*
......@@ -5950,7 +5955,7 @@ class Dependency_marker: public Field_enumerator
Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item,
const char *field_name_arg, bool alias_name_used_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;
/*
......@@ -6033,6 +6038,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (!ref || ref == not_found_item)
{
DBUG_ASSERT(reference_trough_name != 0);
if (!(ref= resolve_ref_in_select_and_group(thd, this,
context->select_lex)))
goto error; /* Some error occurred (e.g. ambiguous names). */
......@@ -6308,6 +6314,11 @@ void Item_ref::cleanup()
DBUG_ENTER("Item_ref::cleanup");
Item_ident::cleanup();
result_field= 0;
if (reference_trough_name)
{
/* We have to reset the reference as it may been freed */
ref= 0;
}
DBUG_VOID_RETURN;
}
......
......@@ -2417,11 +2417,12 @@ class Item_ref :public Item_ident
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */
Item **ref;
bool reference_trough_name;
Item_ref(Name_resolution_context *context_arg,
const char *db_arg, const char *table_name_arg,
const char *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:
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