Skip to content

Commit f61f58e

Browse files
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.
1 parent bf70532 commit f61f58e

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

storage/innobase/dict/dict0dict.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,12 +921,14 @@ template dict_table_t*
921921
dict_acquire_mdl_shared<true>(dict_table_t*,THD*,MDL_ticket**,dict_table_op_t);
922922

923923
/** Look up a table by numeric identifier.
924+
@tparam purge_thd Whether the function is called by purge thread
924925
@param[in] table_id table identifier
925926
@param[in] dict_locked data dictionary locked
926927
@param[in] table_op operation to perform when opening
927928
@param[in,out] thd background thread, or NULL to not acquire MDL
928929
@param[out] mdl mdl ticket, or NULL
929930
@return table, NULL if does not exist */
931+
template<bool purge_thd>
930932
dict_table_t*
931933
dict_table_open_on_id(table_id_t table_id, bool dict_locked,
932934
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,
948950
table_op == DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
949951

950952
if (table != NULL) {
953+
if (purge_thd && table->name.is_temporary()) {
954+
mutex_exit(&dict_sys.mutex);
955+
return nullptr;
956+
}
951957
dict_sys.acquire(table);
952958
MONITOR_INC(MONITOR_TABLE_REFERENCE);
953959
}
@@ -965,6 +971,11 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked,
965971
return table;
966972
}
967973

974+
template dict_table_t* dict_table_open_on_id<false>
975+
(table_id_t, bool, dict_table_op_t, THD *, MDL_ticket **);
976+
template dict_table_t* dict_table_open_on_id<true>
977+
(table_id_t, bool, dict_table_op_t, THD *, MDL_ticket **);
978+
968979
/********************************************************************//**
969980
Looks for column n position in the clustered index.
970981
@return position in internal representation of the clustered index */

storage/innobase/include/dict0dict.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,14 @@ dict_acquire_mdl_shared(dict_table_t *table,
140140
dict_table_op_t table_op= DICT_TABLE_OP_NORMAL);
141141

142142
/** Look up a table by numeric identifier.
143+
@tparam purge_thd Whether the function is called by purge thread
143144
@param[in] table_id table identifier
144145
@param[in] dict_locked data dictionary locked
145146
@param[in] table_op operation to perform when opening
146147
@param[in,out] thd background thread, or NULL to not acquire MDL
147148
@param[out] mdl mdl ticket, or NULL
148149
@return table, NULL if does not exist */
150+
template<bool purge_thd= false>
149151
dict_table_t*
150152
dict_table_open_on_id(table_id_t table_id, bool dict_locked,
151153
dict_table_op_t table_op, THD *thd= nullptr,

storage/innobase/row/row0purge.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,11 +933,11 @@ row_purge_parse_undo_rec(
933933
}
934934

935935
try_again:
936-
node->table = dict_table_open_on_id(
936+
node->table = dict_table_open_on_id<true>(
937937
table_id, false, DICT_TABLE_OP_NORMAL, node->purge_thd,
938938
&node->mdl_ticket);
939939

940-
if (node->table == NULL || node->table->name.is_temporary()) {
940+
if (!node->table) {
941941
/* The table has been dropped: no need to do purge and
942942
release mdl happened as a part of open process itself */
943943
goto err_exit;

0 commit comments

Comments
 (0)