summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
diff options
context:
space:
mode:
authorAnnamalai Gurusami <annamalai.gurusami@oracle.com>2014-10-29 16:53:53 +0530
committerAnnamalai Gurusami <annamalai.gurusami@oracle.com>2014-10-29 16:53:53 +0530
commit427424265501c9b5e281dcfb4a0ab2654758be67 (patch)
treea4b620844a2ff3e938bd155432b8c0510bed359b /storage/innobase/dict
parent352b6bc9a84634534f40290f243ee412e07e74f1 (diff)
downloadmariadb-git-427424265501c9b5e281dcfb4a0ab2654758be67.tar.gz
Bug #19908343 SERVER CRASHES WHEN EXECUTING ALTER TABLE
Problem: In the function dict_foreign_remove_from_cache(), the rb tree was updated without actually verifying whether the given foreign key object is there in the rb tree or not. There can be an existing foreign key object with the same id in the rb tree, which must not be removed. Such a scenario comes when an attempt is made to add a foreign key object with a duplicate identifier. Solution: When the foreign key object is removed from the dictionary cache, ensure that the foreign key object removed from the rbt is the correct one. rb#7168 approved by Jimmy and Marko.
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0dict.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 63571bb26c8..c298f867ae3 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2529,8 +2529,15 @@ dict_foreign_remove_from_cache(
foreign);
rbt = foreign->referenced_table->referenced_rbt;
+
if (rbt != NULL) {
- rbt_delete(rbt, foreign->id);
+ 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);
+ }
}
}
@@ -2543,7 +2550,13 @@ dict_foreign_remove_from_cache(
rbt = foreign->foreign_table->foreign_rbt;
if (rbt != NULL) {
- rbt_delete(rbt, foreign->id);
+ 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);
+ }
}
}