From 3ad0e7edd15b4cdd16492a5a9138b099fa2551a1 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Sun, 26 Mar 2023 17:50:37 +0300 Subject: [PATCH] MDEV-30924 Server crashes in MYSQL_LOG::is_open upon ALTER vs FUNCTION ASAN showed use-after-free in binlog_online_alter_end_trans, during running through thd->online_alter_cache_list. In online_alter_binlog_get_cache_data, new_cache_data was allocated on thd->mem_root, in case of autocommit=1, but this mem_root could be freed in sp_head::execute, upon using stored functions. It appears that thd->transaction->mem_root exists even in single-stmt transaction mode (i.e autocommit=1), so it can be used in all cases. This mem_root will remain valid till the end of transaction, including commit phase. --- .../main/alter_table_online_debug.result | 22 +++++++++++++++ mysql-test/main/alter_table_online_debug.test | 28 +++++++++++++++++++ sql/log.cc | 3 +- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index e7c875814b8..cf72d2dede0 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1190,5 +1190,27 @@ set debug_sync= 'now signal goon'; connection default; drop table t; # +# MDEV-30924 Server crashes in MYSQL_LOG::is_open upon ALTER vs FUNCTION +# +create table t (a int); +insert into t values (1),(2); +create function f () returns int +begin +update t set a = 10; +return 0; +end $ +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for goon'; +alter table t force, algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +select f(); +f() +0 +set debug_sync= 'now signal goon'; +connection default; +drop table t; +drop function f; +disconnect con1; +# # End of 11.2 tests # diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index febdb388a75..47e0a7b23e5 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1370,6 +1370,34 @@ set debug_sync= 'now signal goon'; --reap drop table t; +--echo # +--echo # MDEV-30924 Server crashes in MYSQL_LOG::is_open upon ALTER vs FUNCTION +--echo # +create table t (a int); +insert into t values (1),(2); + +--delimiter $ +create function f () returns int +begin + update t set a = 10; + return 0; +end $ +--delimiter ; + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for goon'; +send alter table t force, algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +select f(); +set debug_sync= 'now signal goon'; + +--connection default +--reap +drop table t; +drop function f; +--disconnect con1 + --echo # --echo # End of 11.2 tests --echo # diff --git a/sql/log.cc b/sql/log.cc index f150235ee9d..8fe91050064 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6449,8 +6449,7 @@ online_alter_cache_data *online_alter_binlog_get_cache_data(THD *thd, TABLE *tab return &cache; } - MEM_ROOT *root= thd->in_multi_stmt_transaction_mode() - ? &thd->transaction->mem_root : thd->mem_root; + MEM_ROOT *root= &thd->transaction->mem_root; auto *new_cache_data= binlog_setup_cache_data(root, table->s); list.push_back(*new_cache_data);