Skip to content

Commit 2c1aab1

Browse files
committed
Bug#21466850: Derived I_S based tables + MAX_INDEXES=128 causes crash
When MAX_INDEXES is > 64, Key_map uses a special template implementation. However, the fields keys_in_use_for_group_by and keys_in_use_for_order_by were not initialized when used by a temporary table. This was OK when using a Bitmap<64> template, but causes failure when using the special template. The solution is to explicitly initialize the two fields. In addition, it was detected that argument key_to_save to is_set() in TABLE::use_index() could be negative, this was corrected. To prevent further problems like this, more asserts on valid arguments were added in sql_bitmap.h. No test case was added to this bugfix: A special configuration is needed to trigger the problem, and several queries in the test suite are vulnerable (all queries with materialized derived tables with equality test on non-indexed columns). However, the problem is not met in any standard test suite, since none of them use the option MAX_INDEXES=128.
1 parent cfe8461 commit 2c1aab1

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

sql/sql_bitmap.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -130,8 +130,8 @@ template <> class Bitmap<64>
130130
void init() { clear_all(); }
131131
void init(uint prefix_to_set) { set_prefix(prefix_to_set); }
132132
uint length() const { return 64; }
133-
void set_bit(uint n) { map|= ((ulonglong)1) << n; }
134-
void clear_bit(uint n) { map&= ~(((ulonglong)1) << n); }
133+
void set_bit(uint n) { DBUG_ASSERT(n < 64); map|= ((ulonglong)1) << n; }
134+
void clear_bit(uint n) { DBUG_ASSERT(n < 64); map&= ~(((ulonglong)1) << n); }
135135
void set_prefix(uint n)
136136
{
137137
if (n >= length())
@@ -146,12 +146,21 @@ template <> class Bitmap<64>
146146
void intersect_extended(ulonglong map2) { map&= map2; }
147147
void subtract(const Bitmap<64>& map2) { map&= ~map2.map; }
148148
void merge(const Bitmap<64>& map2) { map|= map2.map; }
149-
my_bool is_set(uint n) const { return MY_TEST(map & (((ulonglong)1) << n)); }
150-
my_bool is_prefix(uint n) const { return map == (((ulonglong)1) << n)-1; }
149+
my_bool is_set(uint n) const
150+
{ DBUG_ASSERT(n < 64); return MY_TEST(map & (((ulonglong)1) << n)); }
151+
my_bool is_prefix(uint n) const
152+
{
153+
DBUG_ASSERT(n <= 64);
154+
if (n < 64)
155+
return map == (((ulonglong)1) << n)-1;
156+
else
157+
return map == ~(ulonglong)1;
158+
}
151159
my_bool is_clear_all() const { return map == (ulonglong)0; }
152160
my_bool is_set_all() const { return map == ~(ulonglong)0; }
153161
my_bool is_subset(const Bitmap<64>& map2) const { return !(map & ~map2.map); }
154-
my_bool is_overlapping(const Bitmap<64>& map2) const { return (map & map2.map)!= 0; }
162+
my_bool is_overlapping(const Bitmap<64>& map2) const
163+
{ return (map & map2.map)!= 0; }
155164
my_bool operator==(const Bitmap<64>& map2) const { return map == map2.map; }
156165
my_bool operator!=(const Bitmap<64>& map2) const { return !(*this == map2); }
157166
char *print(char *buf) const { longlong2str(map,buf,16); return buf; }

sql/sql_tmp_table.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,8 @@ create_tmp_table(THD *thd, Temp_table_param *param, List<Item> &fields,
818818
table->covering_keys.init();
819819
table->merge_keys.init();
820820
table->keys_in_use_for_query.init();
821+
table->keys_in_use_for_group_by.init();
822+
table->keys_in_use_for_order_by.init();
821823

822824
table->s= share;
823825
init_tmp_table_share(thd, share, "", 0, tmpname, tmpname);

sql/table.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6522,7 +6522,7 @@ void TABLE::use_index(int key_to_save)
65226522
*/
65236523
for (reg_field=field ; *reg_field; reg_field++)
65246524
{
6525-
if(!(*reg_field)->part_of_key.is_set(key_to_save))
6525+
if (key_to_save < 0 || !(*reg_field)->part_of_key.is_set(key_to_save))
65266526
(*reg_field)->key_start.clear_all();
65276527
(*reg_field)->part_of_key.clear_all();
65286528
(*reg_field)->part_of_sortkey.clear_all();

0 commit comments

Comments
 (0)