[Commits] 206b111: MDEV-7672: Crash creating an InnoDB table with foreign keys

Jan Lindström jan.lindstrom at mariadb.com
Fri Mar 6 11:22:45 EET 2015


revision-id: 206b111b114be9eccbecaac5f3060c2ecd6b575c
parent(s): f66fbe8ce0ff4ffcd6a6c185f9b3d25bd9f67f8d
committer: Jan Lindström
branch nick: 5.5-git
timestamp: 2015-03-06 11:19:23 +0200
message:

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.

---
 mysql-test/suite/innodb/r/innodb-fk.result | 32 ++++++++++++++++++++++++
 mysql-test/suite/innodb/t/innodb-fk.test   | 40 ++++++++++++++++++++++++++++++
 storage/innobase/dict/dict0dict.c          | 18 +++++++++-----
 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 cf883d8..3c55753 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 9839cd2..9bfd16b 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 9a99a03..49d0612 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 80f0405..bd0fdf6 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);
+				}
 			}
 		}
 	}


More information about the commits mailing list