Commit 206b111b authored by Jan Lindström's avatar Jan Lindström

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.
parent f66fbe8c
...@@ -33,3 +33,35 @@ select * from fk_29; ...@@ -33,3 +33,35 @@ select * from fk_29;
f1 f1
29 29
drop table t1; drop table t1;
CREATE TABLE t1 (
id int(11) NOT NULL AUTO_INCREMENT,
f1 int(11) DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
f3 int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Error 1005 Can't create table 'test.t2' (errno: 150)
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
f3 int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t2;
drop table t1;
...@@ -84,3 +84,43 @@ while ($i) ...@@ -84,3 +84,43 @@ while ($i)
drop table t1; drop table t1;
#
# MDEV-7672: Crash creating an InnoDB table with foreign keys
#
CREATE TABLE t1 (
id int(11) NOT NULL AUTO_INCREMENT,
f1 int(11) DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
--error 1005
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
f3 int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
show warnings;
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
f2 int(11) NOT NULL,
f3 int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
--error 1005
ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
show warnings;
drop table t2;
drop table t1;
...@@ -2533,10 +2533,13 @@ dict_foreign_remove_from_cache( ...@@ -2533,10 +2533,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) { if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id); = rbt_lookup(rbt, foreign->id);
dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) { if (node) {
rbt_delete(rbt, foreign->id); dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
}
} }
} }
} }
...@@ -2552,10 +2555,13 @@ dict_foreign_remove_from_cache( ...@@ -2552,10 +2555,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) { if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id); = rbt_lookup(rbt, foreign->id);
dict_foreign_t* val = *(dict_foreign_t**) node->value; if (node) {
if (val == foreign) { dict_foreign_t* val = *(dict_foreign_t**) node->value;
rbt_delete(rbt, foreign->id);
if (val == foreign) {
rbt_delete(rbt, foreign->id);
}
} }
} }
} }
......
...@@ -2666,10 +2666,13 @@ dict_foreign_remove_from_cache( ...@@ -2666,10 +2666,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) { if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id); = rbt_lookup(rbt, foreign->id);
dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) { if (node) {
rbt_delete(rbt, foreign->id); dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
}
} }
} }
} }
...@@ -2685,10 +2688,13 @@ dict_foreign_remove_from_cache( ...@@ -2685,10 +2688,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) { if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id); = rbt_lookup(rbt, foreign->id);
dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) { if (node) {
rbt_delete(rbt, foreign->id); dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
}
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment