#At file:///home/kgeorge/mysql/bzr/B37943-5.0-bugteam/
2692 Georgi Kodinov 2008-10-01
Bug#37943: Reproducible mysqld crash/sigsegv in sel_trees_can_be_ored
When analyzing the possible index use cases the server was re-using an internal structure.
This is wrong, as this internal structure gets updated during the analysis.
Fixed by making a copy of the internal structure for every place it needs to be used.
Also stopped the generation of empty SEL_TREE structures that unnecessary
complicate the analysis.
modified:
mysql-test/r/index_merge.result
mysql-test/t/index_merge.test
sql/opt_range.cc
per-file messages:
mysql-test/r/index_merge.result
Bug#37943: test case
mysql-test/t/index_merge.test
Bug#37943: test case
sql/opt_range.cc
Bug#37943:
- Make copy constructors for SEL_TREE and sub-structures and use them when OR-ing trees.
- don't generate empty SEL_TREEs. Return NULL instead.
=== modified file 'mysql-test/r/index_merge.result'
--- a/mysql-test/r/index_merge.result 2007-11-30 05:32:04 +0000
+++ b/mysql-test/r/index_merge.result 2008-10-01 15:50:55 +0000
@@ -518,3 +518,13 @@ a filler b
4 zz 4
5 qq 4
drop table t1, t2;
+CREATE TABLE t1 (a varchar(8), b set('a','b','c','d','e','f','g','h'),
+KEY b(b), KEY a(a));
+INSERT INTO t1 VALUES ('y',''), ('z','');
+SELECT b,a from t1 WHERE (b!='c' AND b!='f' && b!='h') OR
+(a='pure-S') OR (a='DE80337a') OR (a='DE80799');
+b a
+ y
+ z
+DROP TABLE t1;
+End of 5.0 tests
=== modified file 'mysql-test/t/index_merge.test'
--- a/mysql-test/t/index_merge.test 2007-07-14 18:02:10 +0000
+++ b/mysql-test/t/index_merge.test 2008-10-01 15:50:55 +0000
@@ -463,3 +463,18 @@ select * from t2 where a=4 or b=4;
drop table t1, t2;
+#
+# Bug #37943: Reproducible mysqld crash/sigsegv in sel_trees_can_be_ored
+#
+
+CREATE TABLE t1 (a varchar(8), b set('a','b','c','d','e','f','g','h'),
+ KEY b(b), KEY a(a));
+INSERT INTO t1 VALUES ('y',''), ('z','');
+
+#should not crash
+SELECT b,a from t1 WHERE (b!='c' AND b!='f' && b!='h') OR
+ (a='pure-S') OR (a='DE80337a') OR (a='DE80799');
+
+DROP TABLE t1;
+
+--echo End of 5.0 tests
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2008-08-25 17:02:54 +0000
+++ b/sql/opt_range.cc 2008-10-01 15:50:55 +0000
@@ -492,6 +492,7 @@ public:
keys_map.clear_all();
bzero((char*) keys,sizeof(keys));
}
+ SEL_TREE(SEL_TREE *arg, struct st_qsel_param *param);
SEL_ARG *keys[MAX_KEY];
key_map keys_map; /* bitmask of non-NULL elements in keys */
@@ -648,6 +649,7 @@ public:
trees_next(trees),
trees_end(trees + PREALLOCED_TREES)
{}
+ SEL_IMERGE (SEL_IMERGE *arg, PARAM *param);
int or_sel_tree(PARAM *param, SEL_TREE *tree);
int or_sel_tree_with_checks(PARAM *param, SEL_TREE *new_tree);
int or_sel_imerge_with_checks(PARAM *param, SEL_IMERGE* imerge);
@@ -764,6 +766,61 @@ int SEL_IMERGE::or_sel_imerge_with_check
}
+SEL_TREE::SEL_TREE(SEL_TREE *arg, PARAM *param): Sql_alloc()
+{
+ keys_map= arg->keys_map;
+ type= arg->type;
+ for (int idx= 0; idx < MAX_KEY; idx++)
+ {
+ if ((keys[idx]= arg->keys[idx]))
+ keys[idx]->increment_use_count(1);
+ }
+
+ List_iterator<SEL_IMERGE> it(arg->merges);
+ for (SEL_IMERGE *el= it++; el; el= it++)
+ {
+ SEL_IMERGE *merge= new SEL_IMERGE(el, param);
+ if (!merge || merge->trees == merge->trees_next)
+ {
+ merges.empty();
+ return;
+ }
+ merges.push_back (merge);
+ }
+}
+
+
+SEL_IMERGE::SEL_IMERGE (SEL_IMERGE *arg, PARAM *param) : Sql_alloc()
+{
+ uint elements= (arg->trees_end - arg->trees);
+ if (elements > PREALLOCED_TREES)
+ {
+ uint size= elements * sizeof (SEL_TREE **);
+ if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size)))
+ goto mem_err;
+ }
+ else
+ trees= &trees_prealloced[0];
+
+ trees_next= trees;
+ trees_end= trees + elements;
+
+ for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_end;
+ tree++, arg_tree++)
+ {
+ if (!(*tree= new SEL_TREE(*arg_tree, param)))
+ goto mem_err;
+ }
+
+ return;
+
+mem_err:
+ trees= &trees_prealloced[0];
+ trees_next= trees;
+ trees_end= trees;
+}
+
+
/*
Perform AND operation on two index_merge lists and store result in *im1.
*/
@@ -823,10 +880,23 @@ int imerge_list_or_tree(PARAM *param,
{
SEL_IMERGE *imerge;
List_iterator<SEL_IMERGE> it(*im1);
+ bool tree_used= FALSE;
while ((imerge= it++))
{
- if (imerge->or_sel_tree_with_checks(param, tree))
+ SEL_TREE *or_tree;
+ if (tree_used)
+ {
+ or_tree= new SEL_TREE (tree, param);
+ if (!or_tree ||
+ (or_tree->keys_map.is_clear_all() && or_tree->merges.is_empty()))
+ return FALSE;
+ }
+ else
+ or_tree= tree;
+
+ if (imerge->or_sel_tree_with_checks(param, or_tree))
it.remove();
+ tree_used= TRUE;
}
return im1->is_empty();
}
@@ -4238,6 +4308,8 @@ get_mm_parts(PARAM *param, COND *cond_fu
}
}
+ if (tree && tree->merges.is_empty() && tree->keys_map.is_clear_all())
+ tree= NULL;
DBUG_RETURN(tree);
}
| Thread |
|---|
| • bzr commit into mysql-5.0-bugteam branch (kgeorge:2692) Bug#37943 | Georgi Kodinov | 1 Oct |