summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2023-03-26 17:50:37 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2023-05-05 16:12:01 +0300
commit667d0eaffa1f3cc459ce7ad412b65e2bffbddf5a (patch)
tree8106100b54dcc5287331eaa064dbbb9fa9a2bee5
parent20c104e00c007f3ef6896872237574976483141d (diff)
downloadmariadb-git-667d0eaffa1f3cc459ce7ad412b65e2bffbddf5a.tar.gz
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.
-rw-r--r--mysql-test/main/alter_table_online_debug.result22
-rw-r--r--mysql-test/main/alter_table_online_debug.test28
-rw-r--r--sql/log.cc3
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 c4c1cf67504..40a1bad7f68 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 10.10 tests
#
diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test
index 9e118d73996..424a69d1a47 100644
--- a/mysql-test/main/alter_table_online_debug.test
+++ b/mysql-test/main/alter_table_online_debug.test
@@ -1371,5 +1371,33 @@ set debug_sync= 'now signal goon';
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 10.10 tests
--echo #
diff --git a/sql/log.cc b/sql/log.cc
index 5fda1563ec6..f30ce3bcbd1 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -6422,8 +6422,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);