mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-36181 Field pointer may be uninitialized in fill_record
Newer gcc reports: error: 'rfield' may be used uninitialized [-Werror=maybe-uninitialized] 9041 | unwind_stored_field_offsets(fields, rfield); After investigation, it turned to be an impossible case: 1. The only way it could be broken is if if (!(field= fld->field_for_view_update())) line case would succeed from the first time. 2. Consequent checks initialize rfield. fld may return NULL in field_for_view_update() only for views. 3. Before fill_record, UPDATE first calls check_fields, where field_for_view_update() result is already checked. INSERT calls check_view_insertability that checks that all view fields are updateable. It all means that field_for_view_update() cannot be NULL in fill_record, so the if can be converted to DBUG_ASSERT. This essentially shifts the responsibility on preliminary field_for_view_update() check to the caller. In this patch: 1. convert field_for_view_update() check to DBUG_ASSERT 2. harden unwind_stored_field_offsets function so that it can be used even if field_for_view_update() is NULL 3. As a consequence, `field` is passed instead of `rfield` as a terminator. 4. Initialize `field` to NULL to bypass a false-positive warning!
This commit is contained in:
committed by
Oleksandr Byelkin
parent
ba34657cd2
commit
cb7e39b75b
@@ -8485,14 +8485,15 @@ err_no_arena:
|
||||
}
|
||||
|
||||
|
||||
static void unwind_stored_field_offsets(const List<Item> &fields, Field *end)
|
||||
static void unwind_stored_field_offsets(const List<Item> &fields, Item_field *end)
|
||||
{
|
||||
for (Item &item_field: fields)
|
||||
for (Item &item: fields)
|
||||
{
|
||||
Field *f= item_field.field_for_view_update()->field;
|
||||
if (f == end)
|
||||
Item_field *item_field= item.field_for_view_update();
|
||||
if (item_field == end)
|
||||
break;
|
||||
|
||||
Field *f= item_field->field;
|
||||
if (f->stored_in_db())
|
||||
{
|
||||
TABLE *table= f->table;
|
||||
@@ -8537,7 +8538,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
|
||||
{
|
||||
List_iterator_fast<Item> f(fields),v(values);
|
||||
Item *value, *fld;
|
||||
Item_field *field;
|
||||
Item_field *field= NULL;
|
||||
Field *rfield;
|
||||
TABLE *table;
|
||||
bool only_unvers_fields= update && table_arg->versioned();
|
||||
@@ -8555,11 +8556,8 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
|
||||
|
||||
while ((fld= f++))
|
||||
{
|
||||
if (!(field= fld->field_for_view_update()))
|
||||
{
|
||||
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name.str);
|
||||
goto err_unwind_fields;
|
||||
}
|
||||
field= fld->field_for_view_update();
|
||||
DBUG_ASSERT(field); // ensured by check_fields or check_view_insertability.
|
||||
value=v++;
|
||||
DBUG_ASSERT(value);
|
||||
rfield= field->field;
|
||||
@@ -8621,7 +8619,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
|
||||
DBUG_RETURN(thd->is_error());
|
||||
err_unwind_fields:
|
||||
if (update && thd->variables.sql_mode & MODE_SIMULTANEOUS_ASSIGNMENT)
|
||||
unwind_stored_field_offsets(fields, rfield);
|
||||
unwind_stored_field_offsets(fields, field);
|
||||
err:
|
||||
DBUG_PRINT("error",("got error"));
|
||||
thd->abort_on_warning= save_abort_on_warning;
|
||||
|
Reference in New Issue
Block a user