diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-03-06 11:19:23 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-03-06 11:19:23 +0200 |
commit | 206b111b114be9eccbecaac5f3060c2ecd6b575c (patch) | |
tree | 4f58bbe026a4cc9505a3f18b25e7fc256b2cd3a1 | |
parent | f66fbe8ce0ff4ffcd6a6c185f9b3d25bd9f67f8d (diff) | |
download | mariadb-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.result | 32 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb-fk.test | 40 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.c | 18 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0dict.c | 18 |
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); + } } } } |