Skip to content

Commit 6c19f51

Browse files
Jan LindströmNirbhay Choubey
authored andcommitted
MDEV-7672: Crash creating an InnoDB table with foreign keys
Analysis: after a red-black-tree lookup we use node withouth checking did lookup succeed or not. This lead to situation where NULL-pointer was used. Fix: Add additional check that found node from red-back-tree is valid.
1 parent e52a58a commit 6c19f51

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,35 @@ select * from fk_29;
3333
f1
3434
29
3535
drop table t1;
36+
CREATE TABLE t1 (
37+
id int(11) NOT NULL AUTO_INCREMENT,
38+
f1 int(11) DEFAULT NULL,
39+
PRIMARY KEY (id),
40+
CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
41+
) ENGINE=InnoDB;
42+
CREATE TABLE t2 (
43+
id int(11) NOT NULL AUTO_INCREMENT,
44+
f2 int(11) NOT NULL,
45+
f3 int(11) NOT NULL,
46+
PRIMARY KEY (`id`),
47+
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
48+
CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
49+
) ENGINE=InnoDB;
50+
ERROR HY000: Can't create table 'test.t2' (errno: 150)
51+
show warnings;
52+
Level Code Message
53+
Error 1005 Can't create table 'test.t2' (errno: 150)
54+
CREATE TABLE t2 (
55+
id int(11) NOT NULL AUTO_INCREMENT,
56+
f2 int(11) NOT NULL,
57+
f3 int(11) NOT NULL,
58+
PRIMARY KEY (`id`),
59+
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
60+
) ENGINE=InnoDB;
61+
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
62+
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
63+
show warnings;
64+
Level Code Message
65+
Error 1005 Can't create table '#sql-temporary' (errno: 150)
66+
drop table t2;
67+
drop table t1;

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,43 @@ while ($i)
8484

8585
drop table t1;
8686

87+
#
88+
# MDEV-7672: Crash creating an InnoDB table with foreign keys
89+
#
90+
91+
CREATE TABLE t1 (
92+
id int(11) NOT NULL AUTO_INCREMENT,
93+
f1 int(11) DEFAULT NULL,
94+
PRIMARY KEY (id),
95+
CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
96+
) ENGINE=InnoDB;
97+
98+
--error 1005
99+
CREATE TABLE t2 (
100+
id int(11) NOT NULL AUTO_INCREMENT,
101+
f2 int(11) NOT NULL,
102+
f3 int(11) NOT NULL,
103+
PRIMARY KEY (`id`),
104+
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
105+
CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
106+
) ENGINE=InnoDB;
107+
108+
show warnings;
109+
110+
CREATE TABLE t2 (
111+
id int(11) NOT NULL AUTO_INCREMENT,
112+
f2 int(11) NOT NULL,
113+
f3 int(11) NOT NULL,
114+
PRIMARY KEY (`id`),
115+
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
116+
) ENGINE=InnoDB;
117+
118+
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
119+
--error 1005
120+
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
121+
122+
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
123+
show warnings;
124+
125+
drop table t2;
126+
drop table t1;

storage/innobase/dict/dict0dict.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,10 +2533,13 @@ dict_foreign_remove_from_cache(
25332533
if (rbt != NULL && foreign->id != NULL) {
25342534
const ib_rbt_node_t* node
25352535
= rbt_lookup(rbt, foreign->id);
2536-
dict_foreign_t* val = *(dict_foreign_t**) node->value;
25372536

2538-
if (val == foreign) {
2539-
rbt_delete(rbt, foreign->id);
2537+
if (node) {
2538+
dict_foreign_t* val = *(dict_foreign_t**) node->value;
2539+
2540+
if (val == foreign) {
2541+
rbt_delete(rbt, foreign->id);
2542+
}
25402543
}
25412544
}
25422545
}
@@ -2552,10 +2555,13 @@ dict_foreign_remove_from_cache(
25522555
if (rbt != NULL && foreign->id != NULL) {
25532556
const ib_rbt_node_t* node
25542557
= rbt_lookup(rbt, foreign->id);
2555-
dict_foreign_t* val = *(dict_foreign_t**) node->value;
2558+
if (node) {
25562559

2557-
if (val == foreign) {
2558-
rbt_delete(rbt, foreign->id);
2560+
dict_foreign_t* val = *(dict_foreign_t**) node->value;
2561+
2562+
if (val == foreign) {
2563+
rbt_delete(rbt, foreign->id);
2564+
}
25592565
}
25602566
}
25612567
}

storage/xtradb/dict/dict0dict.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,10 +2666,13 @@ dict_foreign_remove_from_cache(
26662666
if (rbt != NULL && foreign->id != NULL) {
26672667
const ib_rbt_node_t* node
26682668
= rbt_lookup(rbt, foreign->id);
2669-
dict_foreign_t* val = *(dict_foreign_t**) node->value;
26702669

2671-
if (val == foreign) {
2672-
rbt_delete(rbt, foreign->id);
2670+
if (node) {
2671+
dict_foreign_t* val = *(dict_foreign_t**) node->value;
2672+
2673+
if (val == foreign) {
2674+
rbt_delete(rbt, foreign->id);
2675+
}
26732676
}
26742677
}
26752678
}
@@ -2685,10 +2688,13 @@ dict_foreign_remove_from_cache(
26852688
if (rbt != NULL && foreign->id != NULL) {
26862689
const ib_rbt_node_t* node
26872690
= rbt_lookup(rbt, foreign->id);
2688-
dict_foreign_t* val = *(dict_foreign_t**) node->value;
26892691

2690-
if (val == foreign) {
2691-
rbt_delete(rbt, foreign->id);
2692+
if (node) {
2693+
dict_foreign_t* val = *(dict_foreign_t**) node->value;
2694+
2695+
if (val == foreign) {
2696+
rbt_delete(rbt, foreign->id);
2697+
}
26922698
}
26932699
}
26942700
}

0 commit comments

Comments
 (0)