Commit 629c1231 authored by evgen@sunlight.local's avatar evgen@sunlight.local

Bug#25126: Wrongly resolved field leads to a crash.

When the ORDER BY clause gets fixed it's allowed to search in the current
item_list in order to find aliased fields and expressions. This is ok for a
SELECT but wrong for an UPDATE statement. If the ORDER BY clause will
contain a non-existing field which is mentioned in the UPDATE set list
then the server will crash due to using of non-existing (0x0) field.

When an Item_field is getting fixed it's allowed to search item list for
aliased expressions and fields only for selects.
parent cf9aca84
...@@ -377,3 +377,7 @@ create table t1(f1 int, `*f2` int); ...@@ -377,3 +377,7 @@ create table t1(f1 int, `*f2` int);
insert into t1 values (1,1); insert into t1 values (1,1);
update t1 set `*f2`=1; update t1 set `*f2`=1;
drop table t1; drop table t1;
create table t1(f1 int);
update t1 set f2=1 order by f2;
ERROR 42S22: Unknown column 'f2' in 'order clause'
drop table t1;
...@@ -306,4 +306,12 @@ create table t1(f1 int, `*f2` int); ...@@ -306,4 +306,12 @@ create table t1(f1 int, `*f2` int);
insert into t1 values (1,1); insert into t1 values (1,1);
update t1 set `*f2`=1; update t1 set `*f2`=1;
drop table t1; drop table t1;
#
# Bug#25126: Wrongly resolved field leads to a crash
#
create table t1(f1 int);
--error 1054
update t1 set f2=1 order by f2;
drop table t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -2518,11 +2518,14 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -2518,11 +2518,14 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
{ {
reg2 Item *item; reg2 Item *item;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
bool save_is_item_list_lookup;
DBUG_ENTER("setup_fields"); DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id; thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func; thd->allow_sum_func= allow_sum_func;
thd->where="field list"; thd->where="field list";
save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup;
thd->lex->current_select->is_item_list_lookup= 0;
/* /*
To prevent fail on forward lookup we fill it with zerows, To prevent fail on forward lookup we fill it with zerows,
...@@ -2543,7 +2546,10 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -2543,7 +2546,10 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
{ {
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) || if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
(item= *(it.ref()))->check_cols(1)) (item= *(it.ref()))->check_cols(1))
{
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
}
if (ref) if (ref)
*(ref++)= item; *(ref++)= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
...@@ -2551,6 +2557,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -2551,6 +2557,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
item->split_sum_func(thd, ref_pointer_array, *sum_func_list); item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables(); thd->used_tables|=item->used_tables();
} }
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(test(thd->net.report_error)); DBUG_RETURN(test(thd->net.report_error));
} }
...@@ -2747,6 +2754,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2747,6 +2754,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
table_map not_null_tables= 0; table_map not_null_tables= 0;
Item_arena *arena= 0, backup; Item_arena *arena= 0, backup;
bool save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup;
thd->lex->current_select->is_item_list_lookup= 0;
DBUG_ENTER("setup_conds"); DBUG_ENTER("setup_conds");
thd->set_query_id=1; thd->set_query_id=1;
...@@ -2756,7 +2765,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2756,7 +2765,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
thd->where="where clause"; thd->where="where clause";
if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) || if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
(*conds)->check_cols(1)) (*conds)->check_cols(1))
{
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(1); DBUG_RETURN(1);
}
not_null_tables= (*conds)->not_null_tables(); not_null_tables= (*conds)->not_null_tables();
} }
...@@ -2772,7 +2784,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2772,7 +2784,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (!table->on_expr->fixed && if (!table->on_expr->fixed &&
table->on_expr->fix_fields(thd, tables, &table->on_expr) || table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1)) table->on_expr->check_cols(1))
{
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(1); DBUG_RETURN(1);
}
thd->lex->current_select->cond_count++; thd->lex->current_select->cond_count++;
/* /*
...@@ -2794,7 +2809,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2794,7 +2809,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
} }
if ((*conds) && !(*conds)->fixed && if ((*conds) && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds)) (*conds)->fix_fields(thd, tables, conds))
{
thd->lex->current_select->is_item_list_lookup=
save_is_item_list_lookup;
DBUG_RETURN(1); DBUG_RETURN(1);
}
} }
} }
if (table->natural_join) if (table->natural_join)
...@@ -2846,7 +2865,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2846,7 +2865,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
if (!(*conds)->fixed && if (!(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds)) (*conds)->fix_fields(thd, tables, conds))
{
thd->lex->current_select->is_item_list_lookup=
save_is_item_list_lookup;
DBUG_RETURN(1); DBUG_RETURN(1);
}
} }
} }
else else
...@@ -2859,7 +2882,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2859,7 +2882,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
if (!table->on_expr->fixed && if (!table->on_expr->fixed &&
table->on_expr->fix_fields(thd, tables, &table->on_expr)) table->on_expr->fix_fields(thd, tables, &table->on_expr))
DBUG_RETURN(1); {
thd->lex->current_select->is_item_list_lookup=
save_is_item_list_lookup;
DBUG_RETURN(1);
}
} }
} }
} }
...@@ -2881,9 +2908,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2881,9 +2908,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
*/ */
thd->lex->current_select->where= *conds; thd->lex->current_select->where= *conds;
} }
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(test(thd->net.report_error)); DBUG_RETURN(test(thd->net.report_error));
err: err:
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
if (arena) if (arena)
thd->restore_backup_item_arena(arena, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -265,6 +265,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -265,6 +265,7 @@ JOIN::prepare(Item ***rref_pointer_array,
select_lex->join= this; select_lex->join= this;
union_part= (unit_arg->first_select()->next_select() != 0); union_part= (unit_arg->first_select()->next_select() != 0);
thd->lex->current_select->is_item_list_lookup= 1;
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
if (setup_tables(tables_list) || if (setup_tables(tables_list) ||
...@@ -8702,16 +8703,12 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, ...@@ -8702,16 +8703,12 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
'it' reassigned in if condition because fix_field can change it. 'it' reassigned in if condition because fix_field can change it.
*/ */
thd->lex->current_select->is_item_list_lookup= 1;
if (!it->fixed && if (!it->fixed &&
(it->fix_fields(thd, tables, order->item) || (it->fix_fields(thd, tables, order->item) ||
(it= *order->item)->check_cols(1) || (it= *order->item)->check_cols(1) ||
thd->is_fatal_error)) thd->is_fatal_error))
{
thd->lex->current_select->is_item_list_lookup= 0;
return 1; // Wrong field return 1; // Wrong field
}
thd->lex->current_select->is_item_list_lookup= 0;
uint el= all_fields.elements; uint el= all_fields.elements;
all_fields.push_front(it); // Add new field to field list all_fields.push_front(it); // Add new field to field list
ref_pointer_array[el]= it; ref_pointer_array[el]= it;
......
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