summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2015-03-06 11:19:23 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2015-03-06 11:19:23 +0200
commit206b111b114be9eccbecaac5f3060c2ecd6b575c (patch)
tree4f58bbe026a4cc9505a3f18b25e7fc256b2cd3a1
parentf66fbe8ce0ff4ffcd6a6c185f9b3d25bd9f67f8d (diff)
downloadmariadb-git-206b111b114be9eccbecaac5f3060c2ecd6b575c.tar.gz
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.
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk.result32
-rw-r--r--mysql-test/suite/innodb/t/innodb-fk.test40
-rw-r--r--storage/innobase/dict/dict0dict.c18
-rw-r--r--storage/xtradb/dict/dict0dict.c18
4 files changed, 96 insertions, 12 deletions
diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result
index cf883d83874..3c557534dbd 100644
--- a/mysql-test/suite/innodb/r/innodb-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-fk.result
@@ -33,3 +33,35 @@ select * from fk_29;
f1
29
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;
diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test
index 9839cd2d084..9bfd16b88e9 100644
--- a/mysql-test/suite/innodb/t/innodb-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-fk.test
@@ -84,3 +84,43 @@ while ($i)
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;
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 9a99a03b70e..49d06120411 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2533,10 +2533,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
- dict_foreign_t* val = *(dict_foreign_t**) node->value;
- if (val == foreign) {
- rbt_delete(rbt, foreign->id);
+ if (node) {
+ 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(
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
- dict_foreign_t* val = *(dict_foreign_t**) node->value;
+ if (node) {
- if (val == foreign) {
- rbt_delete(rbt, foreign->id);
+ dict_foreign_t* val = *(dict_foreign_t**) node->value;
+
+ if (val == foreign) {
+ rbt_delete(rbt, foreign->id);
+ }
}
}
}
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 80f040564cf..bd0fdf6e9b9 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -2666,10 +2666,13 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
- dict_foreign_t* val = *(dict_foreign_t**) node->value;
- if (val == foreign) {
- rbt_delete(rbt, foreign->id);
+ if (node) {
+ 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(
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
- dict_foreign_t* val = *(dict_foreign_t**) node->value;
- if (val == foreign) {
- rbt_delete(rbt, foreign->id);
+ if (node) {
+ dict_foreign_t* val = *(dict_foreign_t**) node->value;
+
+ if (val == foreign) {
+ rbt_delete(rbt, foreign->id);
+ }
}
}
}