Skip to content

Commit 8aa37c2

Browse files
committed
MDEV-28980 InnoDB: Failing assertion: len <= MAX_TABLE_NAME_LEN
dict_load_foreigns(): Use a correctly sized buffer for the maximum-length SYS_FOREIGN.ID. In case of overflow, do not crash the server but instead return DB_CORRUPTION.
1 parent e55c3dc commit 8aa37c2

File tree

5 files changed

+114
-9
lines changed

5 files changed

+114
-9
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,3 +858,17 @@ Error 1296 Got error 193 '`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`)
858858
DROP TABLE t1;
859859
FOUND 1 /InnoDB: Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 15.*/ in mysqld.1.err
860860
# End of 10.2 tests
861+
#
862+
# MDEV-28980 InnoDB: Failing assertion: len <= MAX_TABLE_NAME_LEN
863+
#
864+
SET NAMES utf8;
865+
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=InnoDB;
866+
CREATE DATABASE `db`;
867+
CREATE TABLE `db`.u (
868+
a INT PRIMARY KEY,
869+
CONSTRAINT `††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††`
870+
FOREIGN KEY (a) REFERENCES test.t (a)) ENGINE=InnoDB;
871+
DROP TABLE `db`.u;
872+
DROP DATABASE `db`;
873+
DROP TABLE t;
874+
# End of 10.3 tests
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# MDEV-28980 InnoDB: Failing assertion: len <= MAX_TABLE_NAME_LEN
3+
#
4+
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=InnoDB;
5+
CREATE DATABASE `d255`;
6+
CREATE TABLE `d255`.`d255`
7+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
8+
ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@
9+
CREATE TABLE `d255`.`_##################################################`
10+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
11+
ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/_@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023
12+
CREATE TABLE `d255`.`##################################################`
13+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
14+
DROP DATABASE `d255`;
15+
DROP TABLE t;
16+
# End of 10.3 tests

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,4 +881,33 @@ let SEARCH_PATTERN= InnoDB: Cannot delete/update rows with cascading foreign key
881881

882882
--echo # End of 10.2 tests
883883

884+
--echo #
885+
--echo # MDEV-28980 InnoDB: Failing assertion: len <= MAX_TABLE_NAME_LEN
886+
--echo #
887+
888+
SET NAMES utf8;
889+
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=InnoDB;
890+
# The maximum identifier length is 64 characters.
891+
# my_charset_filename will expand some characters to 5 characters,
892+
# e.g., # to @0023.
893+
# Many operating systems (such as Linux) or file systems
894+
# limit the path component length to 255 bytes, such as 51*5 characters.
895+
# The bug was repeated with a shorter length, which we will use here,
896+
# to avoid exceeding MAX_PATH on Microsoft Windows.
897+
let $db=##########################;
898+
--replace_result $db db
899+
eval CREATE DATABASE `$db`;
900+
--replace_result $db db
901+
eval CREATE TABLE `$db`.u (
902+
a INT PRIMARY KEY,
903+
CONSTRAINT `††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††††`
904+
FOREIGN KEY (a) REFERENCES test.t (a)) ENGINE=InnoDB;
905+
--replace_result $db db
906+
eval DROP TABLE `$db`.u;
907+
--replace_result $db db
908+
eval DROP DATABASE `$db`;
909+
DROP TABLE t;
910+
911+
--echo # End of 10.3 tests
912+
884913
--source include/wait_until_count_sessions.inc
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--source include/have_innodb.inc
2+
--source include/not_windows.inc
3+
4+
--echo #
5+
--echo # MDEV-28980 InnoDB: Failing assertion: len <= MAX_TABLE_NAME_LEN
6+
--echo #
7+
8+
# The main test is innodb.foreign_key. This is an additional test that
9+
# the maximum length cannot be exceeded for implicitly created
10+
# constraint names. On Microsoft Windows, MAX_PATH is a much stricter
11+
# limit than the 255-byte maximum path component length on many other systems,
12+
# including Linux and IBM AIX.
13+
14+
CREATE TABLE t (a INT PRIMARY KEY) ENGINE=InnoDB;
15+
16+
# The maximum identifier length is 64 characters.
17+
# my_charset_filename will expand some characters to 5 characters,
18+
# e.g., # to @0023.
19+
# Many operating systems (such as Linux) or file systems
20+
# limit the path component length to 255 bytes,
21+
# corresponding to the 51 characters below: 5*51=255.
22+
let $d255=###################################################;
23+
let $d250=##################################################;
24+
--replace_result $d255 d255
25+
eval CREATE DATABASE `$d255`;
26+
--replace_result $d255 d255
27+
--error ER_IDENT_CAUSES_TOO_LONG_PATH
28+
eval CREATE TABLE `$d255`.`$d255`
29+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
30+
--replace_result $d255 d255
31+
--error ER_IDENT_CAUSES_TOO_LONG_PATH
32+
eval CREATE TABLE `$d255`.`_$d250`
33+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
34+
--replace_result $d255 d255
35+
eval CREATE TABLE `$d255`.`$d250`
36+
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
37+
--replace_result $d255 d255
38+
eval DROP DATABASE `$d255`;
39+
DROP TABLE t;
40+
41+
--echo # End of 10.3 tests

storage/innobase/dict/dict0load.cc

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2016, 2020, MariaDB Corporation.
4+
Copyright (c) 2016, 2022, 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
@@ -3651,21 +3651,26 @@ dict_load_foreigns(
36513651

36523652
/* Copy the string because the page may be modified or evicted
36533653
after mtr_commit() below. */
3654-
char fk_id[MAX_TABLE_NAME_LEN + 1];
3655-
3656-
ut_a(len <= MAX_TABLE_NAME_LEN);
3657-
memcpy(fk_id, field, len);
3658-
fk_id[len] = '\0';
3654+
char fk_id[MAX_TABLE_NAME_LEN + NAME_LEN + 1];
3655+
err = DB_SUCCESS;
3656+
if (UNIV_LIKELY(len < sizeof fk_id)) {
3657+
memcpy(fk_id, field, len);
3658+
fk_id[len] = '\0';
3659+
} else {
3660+
err = DB_CORRUPTION;
3661+
}
36593662

36603663
btr_pcur_store_position(&pcur, &mtr);
36613664

36623665
mtr_commit(&mtr);
36633666

36643667
/* Load the foreign constraint definition to the dictionary cache */
36653668

3666-
err = dict_load_foreign(fk_id, col_names,
3667-
check_recursive, check_charsets, ignore_err,
3668-
fk_tables);
3669+
if (err == DB_SUCCESS) {
3670+
err = dict_load_foreign(fk_id, col_names,
3671+
check_recursive, check_charsets,
3672+
ignore_err, fk_tables);
3673+
}
36693674

36703675
if (err != DB_SUCCESS) {
36713676
btr_pcur_close(&pcur);

0 commit comments

Comments
 (0)