Commit db2ed27e authored by Annamalai Gurusami's avatar Annamalai Gurusami

Bug #20762798 FK DDL: CRASH IN DICT_FOREIGN_REMOVE_FROM_CACHE

Problem:

If we add a referential integrity constraint with a duplicate
name, an error occurs.  The foreign key object would not have
been added to the dictionary cache.  In the error path, there
is an attempt to remove this foreign key object. Since this
object is not there, the search returns a NULL result.
De-referencing the null object results in this crash.

Solution:

If the search to the foreign key object failed, then don't
attempt to access it.

rb#9309 approved by Marko.
parent dbbe747e
#
# Bug #20762798 FK DDL: CRASH IN DICT_FOREIGN_REMOVE_FROM_CACHE
#
create table t1(a int, b int, key(a),key(b))engine=innodb;
create table t2(a int, b int, key(a),key(b))engine=innodb;
alter table t2 add constraint b foreign key (b) references t1(a);
alter table t1 add constraint b1 foreign key (b) references t2(a);
alter table t2 add constraint b1 foreign key (b) references t1(a);
ERROR HY000: Can't create table '#sql-temporary' (errno: 121)
alter table t2 drop foreign key b;
alter table t1 drop foreign key b1;
drop table t2;
drop table t1;
--source include/have_innodb.inc
--echo #
--echo # Bug #20762798 FK DDL: CRASH IN DICT_FOREIGN_REMOVE_FROM_CACHE
--echo #
create table t1(a int, b int, key(a),key(b))engine=innodb;
create table t2(a int, b int, key(a),key(b))engine=innodb;
alter table t2 add constraint b foreign key (b) references t1(a);
alter table t1 add constraint b1 foreign key (b) references t2(a);
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE
alter table t2 add constraint b1 foreign key (b) references t1(a);
alter table t2 drop foreign key b;
alter table t1 drop foreign key b1;
drop table t2;
drop table t1;
......@@ -2533,10 +2533,14 @@ 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 != NULL) {
dict_foreign_t* val
= *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
}
}
}
}
......@@ -2552,10 +2556,14 @@ 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 != NULL) {
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