Commit 72773f4f authored by unknown's avatar unknown
Browse files

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.


sql/sql_base.cc:
  Bug#25126: Wrongly resolved field leads to a crash.
  When an Item_field is getting fixed it's allowed to search item list for
  aliased expressions and fields only for selects.
sql/sql_select.cc:
  Bug#25126: Wrongly resolved field leads to a crash.
  When an Item_field is getting fixed it's allowed to search item list for
  aliased expressions and fields only for selects.
mysql-test/r/update.result:
  Added a test case for bug#25126: Wrongly resolved field leads to a crash.
mysql-test/t/update.test:
  Added a test case for bug#25126: Wrongly resolved field leads to a crash.
parent af1f49b7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -377,3 +377,7 @@ create table t1(f1 int, `*f2` int);
insert into t1 values (1,1);
update t1 set `*f2`=1;
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;
+8 −0
Original line number Diff line number Diff line
@@ -306,4 +306,12 @@ create table t1(f1 int, `*f2` int);
insert into t1 values (1,1);
update t1 set `*f2`=1;
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
+30 −1
Original line number Diff line number Diff line
@@ -2518,11 +2518,14 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
{
  reg2 Item *item;
  List_iterator<Item> it(fields);
  bool save_is_item_list_lookup;
  DBUG_ENTER("setup_fields");

  thd->set_query_id=set_query_id;
  thd->allow_sum_func= allow_sum_func;
  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,
@@ -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()) ||
	(item= *(it.ref()))->check_cols(1))
    {
      thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
      DBUG_RETURN(-1); /* purecov: inspected */
    }
    if (ref)
      *(ref++)= 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,
      item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
    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));
}

@@ -2747,6 +2754,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
  table_map not_null_tables= 0;
  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");

  thd->set_query_id=1;
@@ -2756,7 +2765,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
    thd->where="where clause";
    if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
	(*conds)->check_cols(1))
    {
      thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
      DBUG_RETURN(1);
    }
    not_null_tables= (*conds)->not_null_tables();
  }

@@ -2772,7 +2784,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
      if (!table->on_expr->fixed &&
	  table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
	  table->on_expr->check_cols(1))
      {
        thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
	DBUG_RETURN(1);
      }
      thd->lex->current_select->cond_count++;

      /*
@@ -2794,9 +2809,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
        }
	if ((*conds) && !(*conds)->fixed &&
	    (*conds)->fix_fields(thd, tables, conds))
        {
          thd->lex->current_select->is_item_list_lookup=
            save_is_item_list_lookup;
	  DBUG_RETURN(1);
        }
      }
    }
    if (table->natural_join)
    {
      arena= thd->change_arena_if_needed(&backup);
@@ -2846,9 +2865,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
          {
            if (!(*conds)->fixed && 
                (*conds)->fix_fields(thd, tables, conds))
            {
              thd->lex->current_select->is_item_list_lookup=
                save_is_item_list_lookup;
              DBUG_RETURN(1);
            }
          }
        }
        else
        {
          table->on_expr= and_conds(table->on_expr, cond_and);
@@ -2859,10 +2882,14 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
          {
            if (!table->on_expr->fixed && 
                table->on_expr->fix_fields(thd, tables, &table->on_expr))
            {
              thd->lex->current_select->is_item_list_lookup=
                save_is_item_list_lookup;
              DBUG_RETURN(1);
            }
          }
        }
      }
      else if (arena)
      {
        thd->restore_backup_item_arena(arena, &backup);
@@ -2881,9 +2908,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **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));

err:
  thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
  if (arena)
    thd->restore_backup_item_arena(arena, &backup);
  DBUG_RETURN(1);
+2 −5
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ JOIN::prepare(Item ***rref_pointer_array,
  select_lex->join= this;
  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 */

  if (setup_tables(tables_list) ||
@@ -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.
  */
  thd->lex->current_select->is_item_list_lookup= 1;
  if (!it->fixed &&
      (it->fix_fields(thd, tables, order->item) ||
       (it= *order->item)->check_cols(1) ||
       thd->is_fatal_error))
  {
    thd->lex->current_select->is_item_list_lookup= 0;
    return 1;					// Wrong field 
  }
  thd->lex->current_select->is_item_list_lookup= 0;

  uint el= all_fields.elements;
  all_fields.push_front(it);		        // Add new field to field list
  ref_pointer_array[el]= it;