Skip to content

Commit

Permalink
MDEV-35510 ASAN build crashes during bootstrap
Browse files Browse the repository at this point in the history
Decouple a DML result's cleanup from the destructor semantics, allowing
cleanup to occur without simultaneously deallocating memory.

The MYSQL_DML_DONE function would access the select_result_interceptor
implementation (in either the cases of UPDATE or DELETE) after that
interceptor instance's destructor had been called.  Most of the time
this works because the instance was allocated on the statement memroot
which continues to live on and no other allocations are made at this point.
The interceptor instance's destructor would be called during either
Sql_cmd_update::execute_inner or Sql_cmd_delete::execute_inner by an
explicit call to delete.  Since the result instance lives on the
memroot associated with the current command, we can avoid calling the
destructor via delete and instead invoke a cleanup method, deferring
the memory deallocation to free_root when the command's processing has
completed.
  • Loading branch information
DaveGosselin-MariaDB committed Jan 8, 2025
1 parent e021770 commit c284c93
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
2 changes: 2 additions & 0 deletions sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -7586,6 +7586,7 @@ class multi_delete :public select_result_interceptor
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
void cleanup();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override;
int send_data(List<Item> &items) override;
bool initialize_tables (JOIN *join) override;
Expand Down Expand Up @@ -7640,6 +7641,7 @@ class multi_update :public select_result_interceptor
List<Item> *fields, List<Item> *values,
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
void cleanup();
bool init(THD *thd);
bool init_for_single_table(THD *thd);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override;
Expand Down
8 changes: 7 additions & 1 deletion sql/sql_delete.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,12 @@ multi_delete::initialize_tables(JOIN *join)


multi_delete::~multi_delete()
{
cleanup();
}


void multi_delete::cleanup()
{
for (table_being_deleted= delete_tables;
table_being_deleted;
Expand Down Expand Up @@ -1913,7 +1919,7 @@ bool Sql_cmd_delete::execute_inner(THD *thd)
if (result)
{
res= false;
delete result;
result->cleanup();
}

status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count());
Expand Down
16 changes: 12 additions & 4 deletions sql/sql_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,12 @@ int multi_update::prepare2(JOIN *join)


multi_update::~multi_update()
{
cleanup();
}


void multi_update::cleanup()
{
TABLE_LIST *table;
for (table= update_tables ; table; table= table->next_local)
Expand All @@ -2319,10 +2325,12 @@ multi_update::~multi_update()
}
}
}
if (copy_field)
delete [] copy_field;
if (copy_field) {
delete[] copy_field;
copy_field= nullptr;
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
DBUG_ASSERT(trans_safe || !updated ||
DBUG_ASSERT(trans_safe || !updated ||
thd->transaction->all.modified_non_trans_table);
}

Expand Down Expand Up @@ -3176,7 +3184,7 @@ bool Sql_cmd_update::execute_inner(THD *thd)
if (result)
{
res= false;
delete result;
result->cleanup();
}

status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count());
Expand Down

0 comments on commit c284c93

Please sign in to comment.