Skip to content

Commit 6ba938a

Browse files
committed
MDEV-25905: Assertion table2==NULL in dict_sys_t::add()
In commit 49e2c8f (MDEV-25743) we made dict_sys_t::find() incompatible with the rest of the table name hash table operations in case the table name contains non-ASCII octets (using a compatibility mode that facilitates the upgrade into the MySQL 5.0 filename-safe encoding) and the target platform implements signed char. ut_fold_string(): Remove; replace with my_crc32c(). This also makes table name hash value calculations independent on whether char is unsigned or signed.
1 parent 28e362e commit 6ba938a

File tree

8 files changed

+50
-69
lines changed

8 files changed

+50
-69
lines changed

extra/mariabackup/xtrabackup.cc

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,7 +2414,8 @@ find_filter_in_hashtable(
24142414
)
24152415
{
24162416
xb_filter_entry_t* found = NULL;
2417-
HASH_SEARCH(name_hash, table, ut_fold_string(name),
2417+
const ulint fold = my_crc32c(0, name, strlen(name));
2418+
HASH_SEARCH(name_hash, table, fold,
24182419
xb_filter_entry_t*,
24192420
found, (void) 0,
24202421
!strcmp(found->name, name));
@@ -3874,22 +3875,16 @@ new hash table */
38743875
static
38753876
xb_filter_entry_t*
38763877
xb_add_filter(
3877-
/*========================*/
38783878
const char* name, /*!< in: name of table/database */
38793879
hash_table_t* hash) /*!< in/out: hash to insert into */
38803880
{
3881-
xb_filter_entry_t* entry;
3882-
3883-
entry = xb_new_filter_entry(name);
3881+
xb_filter_entry_t* entry = xb_new_filter_entry(name);
38843882

38853883
if (UNIV_UNLIKELY(!hash->array)) {
38863884
hash->create(1000);
38873885
}
3888-
HASH_INSERT(xb_filter_entry_t,
3889-
name_hash, hash,
3890-
ut_fold_string(entry->name),
3891-
entry);
3892-
3886+
const ulint fold = my_crc32c(0, entry->name, strlen(entry->name));
3887+
HASH_INSERT(xb_filter_entry_t, name_hash, hash, fold, entry);
38933888
return entry;
38943889
}
38953890

@@ -3943,8 +3938,9 @@ xb_register_filter_entry(
39433938
dbname[p - name] = 0;
39443939

39453940
if (databases_hash && databases_hash->array) {
3941+
const ulint fold = my_crc32c(0, dbname, p - name);
39463942
HASH_SEARCH(name_hash, databases_hash,
3947-
ut_fold_string(dbname),
3943+
fold,
39483944
xb_filter_entry_t*,
39493945
db_entry, (void) 0,
39503946
!strcmp(db_entry->name, dbname));
@@ -4153,9 +4149,10 @@ xb_filter_hash_free(hash_table_t* hash)
41534149

41544150
table = static_cast<xb_filter_entry_t *>
41554151
(HASH_GET_NEXT(name_hash, prev_table));
4156-
4152+
const ulint fold = my_crc32c(0, prev_table->name,
4153+
strlen(prev_table->name));
41574154
HASH_DELETE(xb_filter_entry_t, name_hash, hash,
4158-
ut_fold_string(prev_table->name), prev_table);
4155+
fold, prev_table);
41594156
free(prev_table);
41604157
}
41614158
}
@@ -5049,15 +5046,17 @@ xb_delta_open_matching_space(
50495046
return file;
50505047
}
50515048

5049+
const size_t len = strlen(dest_space_name);
50525050
/* remember space name for further reference */
50535051
table = static_cast<xb_filter_entry_t *>
50545052
(malloc(sizeof(xb_filter_entry_t) +
5055-
strlen(dest_space_name) + 1));
5053+
len + 1));
50565054

50575055
table->name = ((char*)table) + sizeof(xb_filter_entry_t);
5058-
strcpy(table->name, dest_space_name);
5056+
memcpy(table->name, dest_space_name, len + 1);
5057+
const ulint fold = my_crc32c(0, dest_space_name, len);
50595058
HASH_INSERT(xb_filter_entry_t, name_hash, &inc_dir_tables_hash,
5060-
ut_fold_string(table->name), table);
5059+
fold, table);
50615060

50625061
mysql_mutex_lock(&fil_system.mutex);
50635062
fil_space = fil_space_get_by_name(dest_space_name);
@@ -5458,8 +5457,10 @@ static ibool prepare_handle_new_files(const char *data_home_dir,
54585457
(malloc(sizeof(xb_filter_entry_t) + table_name.size() + 1));
54595458
table->name = ((char*)table) + sizeof(xb_filter_entry_t);
54605459
strcpy(table->name, table_name.c_str());
5460+
const ulint fold = my_crc32c(0, table->name,
5461+
table_name.size());
54615462
HASH_INSERT(xb_filter_entry_t, name_hash, &inc_dir_tables_hash,
5462-
ut_fold_string(table->name), table);
5463+
fold, table);
54635464
}
54645465

54655466
return TRUE;
@@ -5482,9 +5483,11 @@ rm_if_not_found(
54825483

54835484
snprintf(name, FN_REFLEN, "%s/%s", db_name, file_name);
54845485
/* Truncate ".ibd" */
5485-
name[strlen(name) - 4] = '\0';
5486+
const size_t len = strlen(name) - 4;
5487+
name[len] = '\0';
5488+
const ulint fold = my_crc32c(0, name, len);
54865489

5487-
HASH_SEARCH(name_hash, &inc_dir_tables_hash, ut_fold_string(name),
5490+
HASH_SEARCH(name_hash, &inc_dir_tables_hash, fold,
54885491
xb_filter_entry_t*,
54895492
table, (void) 0,
54905493
!strcmp(table->name, name));

mysql-test/suite/innodb/r/dropdb.result

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
SET NAMES utf8;
2+
call mtr.add_suppression("Invalid .old.. table or database name");
13
#
24
# Bug #19929435 DROP DATABASE HANGS WITH MALFORMED TABLE
35
#
@@ -6,4 +8,5 @@ create database `b`;
68
use `b`;
79
create table `#mysql50#q.q` select 1;
810
ERROR 42000: Incorrect table name '#mysql50#q.q'
11+
create table `#mysql50#q·q` select 1;
912
drop database `b`;

mysql-test/suite/innodb/t/dropdb.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
--source include/have_innodb.inc
22

3+
SET NAMES utf8;
4+
call mtr.add_suppression("Invalid .old.. table or database name");
5+
36
--echo #
47
--echo # Bug #19929435 DROP DATABASE HANGS WITH MALFORMED TABLE
58
--echo #
@@ -9,4 +12,5 @@ create database `b`;
912
use `b`;
1013
--error ER_WRONG_TABLE_NAME
1114
create table `#mysql50#q.q` select 1;
15+
create table `#mysql50#q·q` select 1;
1216
drop database `b`;

storage/innobase/dict/dict0dict.cc

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,8 @@ inline void dict_sys_t::add(dict_table_t* table)
12011201
{
12021202
ut_ad(!find(table));
12031203

1204-
ulint fold = ut_fold_string(table->name.m_name);
1204+
ulint fold = my_crc32c(0, table->name.m_name,
1205+
strlen(table->name.m_name));
12051206

12061207
table->autoinc_mutex.init();
12071208
table->lock_mutex_init();
@@ -1545,10 +1546,11 @@ dict_table_rename_in_cache(
15451546
dict_sys.assert_locked();
15461547

15471548
/* store the old/current name to an automatic variable */
1548-
ut_a(strlen(table->name.m_name) < sizeof old_name);
1549+
const size_t old_name_len = strlen(table->name.m_name);
1550+
ut_a(old_name_len < sizeof old_name);
15491551
strcpy(old_name, table->name.m_name);
15501552

1551-
fold = ut_fold_string(new_name);
1553+
fold = my_crc32c(0, new_name, strlen(new_name));
15521554

15531555
/* Look for a table with the same name: error if such exists */
15541556
dict_table_t* table2;
@@ -1560,7 +1562,7 @@ dict_table_rename_in_cache(
15601562
table2 = (dict_table_t*) -1;
15611563
} );
15621564
if (table2) {
1563-
ib::error() << "Cannot rename table '" << old_name
1565+
ib::error() << "Cannot rename table '" << table->name
15641566
<< "' to '" << new_name << "' since the"
15651567
" dictionary cache already contains '" << new_name << "'.";
15661568
return(DB_ERROR);
@@ -1574,7 +1576,7 @@ dict_table_rename_in_cache(
15741576

15751577
/* Remove table from the hash tables of tables */
15761578
HASH_DELETE(dict_table_t, name_hash, &dict_sys.table_hash,
1577-
ut_fold_string(old_name), table);
1579+
my_crc32c(0, table->name.m_name, old_name_len), table);
15781580

15791581
const bool keep_mdl_name = dict_table_t::is_temporary_name(new_name)
15801582
&& !table->name.is_temporary();
@@ -1922,7 +1924,9 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep)
19221924
/* Remove table from the hash tables of tables */
19231925

19241926
HASH_DELETE(dict_table_t, name_hash, &table_hash,
1925-
ut_fold_string(table->name.m_name), table);
1927+
my_crc32c(0, table->name.m_name,
1928+
strlen(table->name.m_name)),
1929+
table);
19261930

19271931
hash_table_t* id_hash = table->is_temporary()
19281932
? &temp_id_hash : &table_id_hash;
@@ -4663,7 +4667,7 @@ void dict_sys_t::resize()
46634667
table= UT_LIST_GET_NEXT(table_LRU, table))
46644668
{
46654669
ut_ad(!table->is_temporary());
4666-
ulint fold= ut_fold_string(table->name.m_name);
4670+
ulint fold= my_crc32c(0, table->name.m_name, strlen(table->name.m_name));
46674671
ulint id_fold= ut_fold_ull(table->id);
46684672

46694673
HASH_INSERT(dict_table_t, name_hash, &table_hash, fold, table);
@@ -4673,7 +4677,7 @@ void dict_sys_t::resize()
46734677
for (dict_table_t *table = UT_LIST_GET_FIRST(table_non_LRU); table;
46744678
table= UT_LIST_GET_NEXT(table_LRU, table))
46754679
{
4676-
ulint fold= ut_fold_string(table->name.m_name);
4680+
ulint fold= my_crc32c(0, table->name.m_name, strlen(table->name.m_name));
46774681
ulint id_fold= ut_fold_ull(table->id);
46784682

46794683
HASH_INSERT(dict_table_t, name_hash, &table_hash, fold, table);

storage/innobase/include/dict0dict.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Created 1/8/1996 Heikki Tuuri
3232
#include "dict0mem.h"
3333
#include "fsp0fsp.h"
3434
#include "srw_lock.h"
35+
#include <my_sys.h>
3536
#include <deque>
3637

3738
class MDL_ticket;
@@ -1478,7 +1479,7 @@ class dict_sys_t
14781479
{
14791480
mysql_mutex_assert_owner(&mutex);
14801481
dict_table_t *table;
1481-
ulint fold = ut_fold_ull(id);
1482+
ulint fold= ut_fold_ull(id);
14821483
HASH_SEARCH(id_hash, &table_id_hash, fold, dict_table_t*, table,
14831484
ut_ad(table->cached), table->id == id);
14841485
DBUG_ASSERT(!table || !table->is_temporary());
@@ -1617,8 +1618,7 @@ class dict_sys_t
16171618
assert_locked();
16181619
for (dict_table_t *table= static_cast<dict_table_t*>
16191620
(HASH_GET_FIRST(&table_hash, table_hash.calc_hash
1620-
(ut_fold_binary(reinterpret_cast<const byte*>
1621-
(name.data()), name.size()))));
1621+
(my_crc32c(0, name.data(), name.size()))));
16221622
table; table= table->name_hash)
16231623
if (strlen(table->name.m_name) == name.size() &&
16241624
!memcmp(table->name.m_name, name.data(), name.size()))

storage/innobase/include/ut0rnd.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2019, 2020, MariaDB Corporation.
4+
Copyright (c) 2019, 2021, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -90,15 +90,6 @@ ut_fold_ull(
9090
/*========*/
9191
ib_uint64_t d) /*!< in: 64-bit integer */
9292
MY_ATTRIBUTE((const));
93-
/*************************************************************//**
94-
Folds a character string ending in the null character.
95-
@return folded value */
96-
UNIV_INLINE
97-
ulint
98-
ut_fold_string(
99-
/*===========*/
100-
const char* str) /*!< in: null-terminated string */
101-
MY_ATTRIBUTE((warn_unused_result));
10293
/***********************************************************//**
10394
Looks for a prime number slightly greater than the given argument.
10495
The prime is chosen so that it is not near any power of 2.

storage/innobase/include/ut0rnd.ic

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22

33
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2017, 2019, MariaDB Corporation.
4+
Copyright (c) 2017, 2021, MariaDB Corporation.
55

66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -59,28 +59,6 @@ ut_fold_ull(
5959
return(ut_fold_ulint_pair((ulint) d & ULINT32_MASK,
6060
(ulint) (d >> 32)));
6161
}
62-
63-
/*************************************************************//**
64-
Folds a character string ending in the null character.
65-
@return folded value */
66-
UNIV_INLINE
67-
ulint
68-
ut_fold_string(
69-
/*===========*/
70-
const char* str) /*!< in: null-terminated string */
71-
{
72-
ulint fold = 0;
73-
74-
ut_ad(str);
75-
76-
while (*str != '\0') {
77-
fold = ut_fold_ulint_pair(fold, (ulint)(*str));
78-
str++;
79-
}
80-
81-
return(fold);
82-
}
83-
8462
#endif /* !UNIV_INNOCHECKSUM */
8563

8664
/*************************************************************//**

tpool/aio_liburing.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,10 @@ class aio_uring final : public tpool::aio
162162

163163
io_uring_cqe_seen(&aio->uring_, cqe);
164164

165-
if (res == -EAGAIN) {
166-
// If we need to resubmit the IO operation, but the ring is full,
167-
// then just go the same path as for any other error codes.
168-
if (!aio->submit_io(iocb))
169-
continue;
170-
}
165+
// If we need to resubmit the IO operation, but the ring is full,
166+
// we will follow the same path as for any other error codes.
167+
if (res == -EAGAIN && !aio->submit_io(iocb))
168+
continue;
171169

172170
iocb->m_internal_task.m_func= iocb->m_callback;
173171
iocb->m_internal_task.m_arg= iocb;

0 commit comments

Comments
 (0)