Skip to content

Commit 6b2cd78

Browse files
dmitryshulgasanja-byelkin
authored andcommitted
MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT, UBSAN runtime error: member call on null pointer of type 'struct TABLE_LIST' in Item_param::save_in_field
This is the prerequisite patch to refactor the method Item_default_value::fix_fields. The former implementation of this method was extracted and placed into the standalone function make_default_field() and the method Item_default_value::tie_field(). The motivation for this modification is upcoming changes for core implementation of the task MDEV-15703 since these functions will be used from several places within the source code.
1 parent 85db534 commit 6b2cd78

File tree

4 files changed

+104
-62
lines changed

4 files changed

+104
-62
lines changed

extra/wolfssl/wolfssl

Submodule wolfssl updated 1154 files

libmariadb

sql/item.cc

Lines changed: 99 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4969,6 +4969,44 @@ bool Item_param::append_for_log(THD *thd, String *str)
49694969
}
49704970

49714971

4972+
/**
4973+
Allocate a memory and create on it a copy of Field object.
4974+
4975+
@param thd thread handler
4976+
@param field_arg an instance of Field the new Field object be based on
4977+
4978+
@return a new created Field object on success, nullptr on error.
4979+
*/
4980+
4981+
static Field *make_default_field(THD *thd, Field *field_arg)
4982+
{
4983+
Field *def_field;
4984+
4985+
if (!(def_field= (Field*) thd->alloc(field_arg->size_of())))
4986+
return nullptr;
4987+
4988+
memcpy((void *)def_field, (void *)field_arg, field_arg->size_of());
4989+
def_field->reset_fields();
4990+
// If non-constant default value expression or a blob
4991+
if (def_field->default_value &&
4992+
(def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
4993+
{
4994+
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
4995+
if (!newptr)
4996+
return nullptr;
4997+
4998+
if (should_mark_column(thd->column_usage))
4999+
def_field->default_value->expr->update_used_tables();
5000+
def_field->move_field(newptr + 1, def_field->maybe_null() ? newptr : 0, 1);
5001+
}
5002+
else
5003+
def_field->move_field_offset((my_ptrdiff_t)
5004+
(def_field->table->s->default_values -
5005+
def_field->table->record[0]));
5006+
return def_field;
5007+
}
5008+
5009+
49725010
/****************************************************************************
49735011
Item_copy_string
49745012
****************************************************************************/
@@ -9446,69 +9484,10 @@ bool Item_default_value::update_func_default_processor(void *)
94469484

94479485
bool Item_default_value::fix_fields(THD *thd, Item **items)
94489486
{
9449-
Item *real_arg;
9450-
Item_field *field_arg;
9451-
Field *def_field;
94529487
DBUG_ASSERT(fixed == 0);
94539488
DBUG_ASSERT(arg);
94549489

9455-
/*
9456-
DEFAULT() do not need table field so should not ask handler to bring
9457-
field value (mark column for read)
9458-
*/
9459-
enum_column_usage save_column_usage= thd->column_usage;
9460-
/*
9461-
Fields which has defult value could be read, so it is better hide system
9462-
invisible columns.
9463-
*/
9464-
thd->column_usage= COLUMNS_WRITE;
9465-
if (arg->fix_fields_if_needed(thd, &arg))
9466-
{
9467-
thd->column_usage= save_column_usage;
9468-
goto error;
9469-
}
9470-
thd->column_usage= save_column_usage;
9471-
9472-
real_arg= arg->real_item();
9473-
if (real_arg->type() != FIELD_ITEM)
9474-
{
9475-
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
9476-
goto error;
9477-
}
9478-
9479-
field_arg= (Item_field *)real_arg;
9480-
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
9481-
{
9482-
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
9483-
field_arg->field->field_name.str);
9484-
goto error;
9485-
}
9486-
if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
9487-
goto error;
9488-
memcpy((void *)def_field, (void *)field_arg->field,
9489-
field_arg->field->size_of());
9490-
def_field->reset_fields();
9491-
// If non-constant default value expression or a blob
9492-
if (def_field->default_value &&
9493-
(def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
9494-
{
9495-
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
9496-
if (!newptr)
9497-
goto error;
9498-
if (should_mark_column(thd->column_usage))
9499-
def_field->default_value->expr->update_used_tables();
9500-
def_field->move_field(newptr+1, def_field->maybe_null() ? newptr : 0, 1);
9501-
}
9502-
else
9503-
def_field->move_field_offset((my_ptrdiff_t)
9504-
(def_field->table->s->default_values -
9505-
def_field->table->record[0]));
9506-
set_field(def_field);
9507-
return FALSE;
9508-
9509-
error:
9510-
context->process_error(thd);
9511-
return TRUE;
9490+
return tie_field(thd);
95129491
}
95139492

95149493
void Item_default_value::cleanup()
@@ -9696,6 +9675,66 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer,
96969675
}
96979676

96989677

9678+
/**
9679+
Call fix_fields for an item representing the default value, create
9680+
an instance of Field for representing the default value and assign it
9681+
to the Item_field::field.
9682+
9683+
@param thd thread handler
9684+
9685+
@return false on success, true on error
9686+
*/
9687+
9688+
bool Item_default_value::tie_field(THD *thd)
9689+
{
9690+
Item *real_arg;
9691+
Item_field *field_arg;
9692+
Field *def_field;
9693+
9694+
/*
9695+
DEFAULT() do not need table field so should not ask handler to bring
9696+
field value (mark column for read)
9697+
*/
9698+
enum_column_usage save_column_usage= thd->column_usage;
9699+
/*
9700+
Fields which has defult value could be read, so it is better hide system
9701+
invisible columns.
9702+
*/
9703+
thd->column_usage= COLUMNS_WRITE;
9704+
if (arg->fix_fields_if_needed(thd, &arg))
9705+
{
9706+
thd->column_usage= save_column_usage;
9707+
goto error;
9708+
}
9709+
thd->column_usage= save_column_usage;
9710+
9711+
real_arg= arg->real_item();
9712+
if (real_arg->type() != FIELD_ITEM)
9713+
{
9714+
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
9715+
goto error;
9716+
}
9717+
9718+
field_arg= (Item_field *)real_arg;
9719+
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
9720+
{
9721+
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
9722+
field_arg->field->field_name.str);
9723+
goto error;
9724+
}
9725+
def_field= make_default_field(thd, field_arg->field);
9726+
if (!def_field)
9727+
goto error;
9728+
9729+
set_field(def_field);
9730+
return false;
9731+
9732+
error:
9733+
context->process_error(thd);
9734+
return true;
9735+
9736+
}
9737+
96999738
bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
97009739
{
97019740
return item->type() == INSERT_VALUE_ITEM &&

sql/item.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6580,6 +6580,9 @@ class Item_default_value : public Item_field
65806580
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
65816581
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
65826582
const Tmp_field_param *param);
6583+
6584+
private:
6585+
bool tie_field(THD *thd);
65836586
};
65846587

65856588

0 commit comments

Comments
 (0)