mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
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
This commit is contained in:
parent
1ee94dc2f7
commit
fc5953250b
2 changed files with 15 additions and 3 deletions
15
sql/item.cc
15
sql/item.cc
|
@ -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 @@ public:
|
|||
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 @@ public:
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue