From f61f58e7596b397a5490b3e2a87deefb81746cfb Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 8 Apr 2022 12:48:27 +0530 Subject: [PATCH 1/2] MDEV-26578 ERROR: AddressSanitizer: heap-use-after-free around dict_table_t::is_temporary_name - Purge thread is trying to access the table name when other thread does rename of the table name. It leads to heap use after free error by purge thread. purge thread should check whether the table name is temporary while holding dict_sys.mutex. --- storage/innobase/dict/dict0dict.cc | 11 +++++++++++ storage/innobase/include/dict0dict.h | 2 ++ storage/innobase/row/row0purge.cc | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 9c1750c588f..eb32b52db29 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -921,12 +921,14 @@ template dict_table_t* dict_acquire_mdl_shared(dict_table_t*,THD*,MDL_ticket**,dict_table_op_t); /** Look up a table by numeric identifier. +@tparam purge_thd Whether the function is called by purge thread @param[in] table_id table identifier @param[in] dict_locked data dictionary locked @param[in] table_op operation to perform when opening @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ +template dict_table_t* dict_table_open_on_id(table_id_t table_id, bool dict_locked, dict_table_op_t table_op, THD *thd, @@ -948,6 +950,10 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, table_op == DICT_TABLE_OP_OPEN_ONLY_IF_CACHED); if (table != NULL) { + if (purge_thd && table->name.is_temporary()) { + mutex_exit(&dict_sys.mutex); + return nullptr; + } dict_sys.acquire(table); MONITOR_INC(MONITOR_TABLE_REFERENCE); } @@ -965,6 +971,11 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, return table; } +template dict_table_t* dict_table_open_on_id +(table_id_t, bool, dict_table_op_t, THD *, MDL_ticket **); +template dict_table_t* dict_table_open_on_id +(table_id_t, bool, dict_table_op_t, THD *, MDL_ticket **); + /********************************************************************//** Looks for column n position in the clustered index. @return position in internal representation of the clustered index */ diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 5682a10c889..14227fad3b6 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -140,12 +140,14 @@ dict_acquire_mdl_shared(dict_table_t *table, dict_table_op_t table_op= DICT_TABLE_OP_NORMAL); /** Look up a table by numeric identifier. +@tparam purge_thd Whether the function is called by purge thread @param[in] table_id table identifier @param[in] dict_locked data dictionary locked @param[in] table_op operation to perform when opening @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ +template dict_table_t* dict_table_open_on_id(table_id_t table_id, bool dict_locked, dict_table_op_t table_op, THD *thd= nullptr, diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index ff19ed9830e..c00358eafa9 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -933,11 +933,11 @@ row_purge_parse_undo_rec( } try_again: - node->table = dict_table_open_on_id( + node->table = dict_table_open_on_id( table_id, false, DICT_TABLE_OP_NORMAL, node->purge_thd, &node->mdl_ticket); - if (node->table == NULL || node->table->name.is_temporary()) { + if (!node->table) { /* The table has been dropped: no need to do purge and release mdl happened as a part of open process itself */ goto err_exit; From e41500e4f2914af8142e06ca17925f6c03c7b7af Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 12 Apr 2022 13:57:16 +0400 Subject: [PATCH 2/2] MDEV-26128 type_set and type_enum are broken The problem was not with the server behavior, it was with wrong test results recorded. Enabling both type_set and type_enum. type_set.result was OK. The test did not fail. type_enum.result was incorrectly recorded in this commit: eb483c5181ab430877c135c16224284cfc517b3d Recording correct results. --- mysql-test/main/disabled.def | 2 -- mysql-test/main/type_enum.result | 12 +++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/disabled.def b/mysql-test/main/disabled.def index d3366587ee5..02104f6a680 100644 --- a/mysql-test/main/disabled.def +++ b/mysql-test/main/disabled.def @@ -18,5 +18,3 @@ file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing partition_open_files_limit : open_files_limit check broken by MDEV-18360 partition_innodb : Waiting for fix MDEV-20169 -type_enum : Waiting for fix MDEV-6978 -type_set : Waiting for fix MDEV-6978 diff --git a/mysql-test/main/type_enum.result b/mysql-test/main/type_enum.result index 9b251fb414b..d17b94bbb4f 100644 --- a/mysql-test/main/type_enum.result +++ b/mysql-test/main/type_enum.result @@ -1932,14 +1932,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 SET('a') CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1957,14 +1959,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET latin1 PRIMARY KEY); INSERT INTO t1 VALUES ('a'); @@ -1982,14 +1986,16 @@ ALTER TABLE t2 ADD PRIMARY KEY(c1); SELECT t1.* FROM t1 JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; c1 a +a # t2 should NOT be eliminated EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.c1 COLLATE latin1_swedish_ci=t2.c1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 -1 SIMPLE t2 range PRIMARY PRIMARY 1 NULL 1 Using where; Using index +1 SIMPLE t2 index PRIMARY PRIMARY 1 NULL 2 Using where; Using index DROP TABLE IF EXISTS t1,t2; # # MDEV-6991 GROUP_MIN_MAX optimization is erroneously applied in some cases