[Commits] 6c19f51: MDEV-7672: Crash creating an InnoDB table with foreign keys

Nirbhay Choubey nirbhay at mariadb.com
Sun Mar 8 05:56:33 EET 2015


revision-id: 6c19f51a5fe6bd0dbecf3cb8fd4f88e4f8da477e
parent(s): e52a58a5cc338a82a9de446785f81c8f45064fa5
committer: Nirbhay Choubey
branch nick: 5.5-galera
timestamp: 2015-03-07 22:56:33 -0500
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 15426b1..cf0d4c1 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2533,10 +2533,13 @@ be called right after dtuple_create(). */
 		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 @@ be called right after dtuple_create(). */
 		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 0addc41..a67ca85 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -2666,10 +2666,13 @@ be called right after dtuple_create(). */
 		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 @@ be called right after dtuple_create(). */
 		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