Skip to content

Commit 083cd3e

Browse files
committed
MDEV-37720 use-after-free on CREATE OR REPLACE GTT under pseudo_slave_mode
... and LOCK TABLES. Global temporary tables data is not replicated, and pseudo_slave_mode is used internally for partial replication testing. Hence forbid opening GTT (i.e. create child GTT handles) under pseudo_slave_mode, and forbid setting pseudo_slave_mode=1 whenever child GTT handles are open.
1 parent 7d67ea8 commit 083cd3e

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed

mysql-test/main/global_temporary_table.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,4 +1109,18 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
11091109
select * from gtt;
11101110
c
11111111
drop table gtt;
1112+
# MDEV-37720 use-after-free on CREATE OR REPLACE GTT under LOCK TABLES and pseudo_slave_mode
1113+
create global temporary table t (c int) engine=innodb on commit preserve rows;
1114+
set pseudo_slave_mode=1;
1115+
select * from t;
1116+
ERROR HY000: Failed to open t.test
1117+
set pseudo_slave_mode=0;
1118+
Warnings:
1119+
Warning 1231 Slave applier execution mode not active, statement ineffective.
1120+
select * from t;
1121+
c
1122+
set pseudo_slave_mode=1;
1123+
ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of '1'
1124+
truncate t;
1125+
drop table t;
11121126
disconnect con1;

mysql-test/main/global_temporary_table.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,5 +973,16 @@ rollback to sp1;
973973
select * from gtt;
974974
drop table gtt;
975975

976+
--echo # MDEV-37720 use-after-free on CREATE OR REPLACE GTT under LOCK TABLES and pseudo_slave_mode
977+
create global temporary table t (c int) engine=innodb on commit preserve rows;
978+
set pseudo_slave_mode=1;
979+
--error ER_GTID_OPEN_TABLE_FAILED
980+
select * from t;
981+
set pseudo_slave_mode=0;
982+
select * from t;
983+
--error ER_WRONG_VALUE_FOR_VAR
984+
set pseudo_slave_mode=1;
985+
truncate t;
986+
drop table t;
976987

977988
--disconnect con1

mysql-test/suite/binlog/r/global_temporary_table.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,20 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
11121112
select * from gtt;
11131113
c
11141114
drop table gtt;
1115+
# MDEV-37720 use-after-free on CREATE OR REPLACE GTT under LOCK TABLES and pseudo_slave_mode
1116+
create global temporary table t (c int) engine=innodb on commit preserve rows;
1117+
set pseudo_slave_mode=1;
1118+
select * from t;
1119+
ERROR HY000: Failed to open t.test
1120+
set pseudo_slave_mode=0;
1121+
Warnings:
1122+
Warning 1231 Slave applier execution mode not active, statement ineffective.
1123+
select * from t;
1124+
c
1125+
set pseudo_slave_mode=1;
1126+
ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of '1'
1127+
truncate t;
1128+
drop table t;
11151129
disconnect con1;
11161130
include/show_binlog_events.inc
11171131
Log_name Pos Event_type Server_id End_log_pos Info
@@ -1688,4 +1702,8 @@ master-bin.000001 # Gtid # # GTID #-#-#
16881702
master-bin.000001 # Query # # use `test`; create global temporary table gtt (c int)
16891703
master-bin.000001 # Gtid # # GTID #-#-#
16901704
master-bin.000001 # Query # # use `test`; DROP TABLE `gtt` /* generated by server */
1705+
master-bin.000001 # Gtid # # GTID #-#-#
1706+
master-bin.000001 # Query # # use `test`; create global temporary table t (c int) engine=innodb on commit preserve rows
1707+
master-bin.000001 # Gtid # # GTID #-#-#
1708+
master-bin.000001 # Query # # use `test`; DROP TABLE `t` /* generated by server */
16911709
set global binlog_annotate_row_events= @old_binlog_annotate_row_events;

mysql-test/suite/rpl/r/global_temporary_table.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,20 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
11121112
select * from gtt;
11131113
c
11141114
drop table gtt;
1115+
# MDEV-37720 use-after-free on CREATE OR REPLACE GTT under LOCK TABLES and pseudo_slave_mode
1116+
create global temporary table t (c int) engine=innodb on commit preserve rows;
1117+
set pseudo_slave_mode=1;
1118+
select * from t;
1119+
ERROR HY000: Failed to open t.test
1120+
set pseudo_slave_mode=0;
1121+
Warnings:
1122+
Warning 1231 Slave applier execution mode not active, statement ineffective.
1123+
select * from t;
1124+
c
1125+
set pseudo_slave_mode=1;
1126+
ERROR 42000: Variable 'pseudo_slave_mode' can't be set to the value of '1'
1127+
truncate t;
1128+
drop table t;
11151129
disconnect con1;
11161130
connection slave;
11171131
connection master;

sql/sql_table.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6222,6 +6222,16 @@ my_bool open_global_temporary_table(THD *thd, TABLE_SHARE *source,
62226222
MDL_ticket *mdl_ticket)
62236223
{
62246224
DBUG_ASSERT(!thd->rgi_slave); // slave won't use global temporary tables
6225+
if (thd->variables.pseudo_slave_mode)
6226+
{
6227+
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
6228+
ER_GTID_OPEN_TABLE_FAILED,
6229+
"Can't open global temporary table upder "
6230+
"slave applier execution mode");
6231+
my_error(ER_GTID_OPEN_TABLE_FAILED, MYF(0),
6232+
source->table_name.str, source->db.str);
6233+
return TRUE;
6234+
}
62256235

62266236
/*
62276237
First, lookup in tmp tables list for cases like "t join t"

sql/sys_vars.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7233,6 +7233,16 @@ static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var)
72337233
}
72347234
else
72357235
{
7236+
if (!thd->rgi_slave && thd->temporary_tables &&
7237+
thd->temporary_tables->global_temporary_tables_count)
7238+
{
7239+
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
7240+
ER_WRONG_VALUE_FOR_VAR,
7241+
"Slave applier execution mode can't be enabled "
7242+
"when some global temporary tables are open.");
7243+
return TRUE;
7244+
}
7245+
72367246
if (!previous_val && !val)
72377247
goto ineffective;
72387248
else if (previous_val && !val)

0 commit comments

Comments
 (0)