summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <igor@olga.mysql.com>2007-03-31 00:23:03 -0700
committerunknown <igor@olga.mysql.com>2007-03-31 00:23:03 -0700
commit7887a74491051d67fe0d780e19a62b5f055d07f9 (patch)
tree30965172fb391f49ca43b269726d625266437a20
parent8aa507edb99a6f24553b9a8f773411327307aa0b (diff)
downloadmariadb-git-7887a74491051d67fe0d780e19a62b5f055d07f9.tar.gz
Fixed bug #27154: memory corruption when using row equalities in where
conditions. When allocating memory for KEY_FIELD/SARGABLE_PARAM structures the function update_ref_and_keys did not take into account the fact that a single row equality could be replaced by several simple equalities. Fixed by adjusting the counter cond_count accordingly for each subquery when performing substitution of a row equality for simple equalities. mysql-test/r/row.result: Added a test case for bug #27154. mysql-test/t/row.test: Added a test case for bug #27154.
-rw-r--r--mysql-test/r/row.result13
-rw-r--r--mysql-test/t/row.test17
-rw-r--r--sql/sql_select.cc45
3 files changed, 60 insertions, 15 deletions
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
index 5b5f8b7b954..faf9b11d7c9 100644
--- a/mysql-test/r/row.result
+++ b/mysql-test/r/row.result
@@ -306,3 +306,16 @@ a b a b c
1 1 1 2 1
1 2 1 2 1
DROP TABLE t1,t2;
+CREATE TABLE t1(
+a int, b int, c int, d int, e int, f int, g int, h int,
+PRIMARY KEY (a,b,c,d,e,f,g)
+);
+INSERT INTO t1 VALUES (1,2,3,4,5,6,7,99);
+SELECT h FROM t1 WHERE (a,b,c,d,e,f,g)=(1,2,3,4,5,6,7);
+h
+99
+SET @x:= (SELECT h FROM t1 WHERE (a,b,c,d,e,f,g)=(1,2,3,4,5,6,7));
+SELECT @x;
+@x
+99
+DROP TABLE t1;
diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test
index 63c611e6be6..1d5c7a543ea 100644
--- a/mysql-test/t/row.test
+++ b/mysql-test/t/row.test
@@ -139,3 +139,20 @@ EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
DROP TABLE t1,t2;
+
+#
+# Bug #27154: crash (memory corruption) when using row equalities
+#
+
+CREATE TABLE t1(
+ a int, b int, c int, d int, e int, f int, g int, h int,
+ PRIMARY KEY (a,b,c,d,e,f,g)
+);
+INSERT INTO t1 VALUES (1,2,3,4,5,6,7,99);
+
+SELECT h FROM t1 WHERE (a,b,c,d,e,f,g)=(1,2,3,4,5,6,7);
+
+SET @x:= (SELECT h FROM t1 WHERE (a,b,c,d,e,f,g)=(1,2,3,4,5,6,7));
+SELECT @x;
+
+DROP TABLE t1;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 08780efbedb..27e19657935 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -6947,6 +6947,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
SYNOPSIS
check_row_equality()
+ thd thread handle
left_row left term of the row equality to be processed
right_row right term of the row equality to be processed
cond_equal multiple equalities that must hold together with the predicate
@@ -6967,7 +6968,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
FALSE otherwise
*/
-static bool check_row_equality(Item *left_row, Item_row *right_row,
+static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
COND_EQUAL *cond_equal, List<Item>* eq_list)
{
uint n= left_row->cols();
@@ -6978,13 +6979,21 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
Item *right_item= right_row->element_index(i);
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
- is_converted= check_row_equality((Item_row *) left_item,
- (Item_row *) right_item,
- cond_equal, eq_list);
- else
+ {
+ is_converted= check_row_equality(thd,
+ (Item_row *) left_item,
+ (Item_row *) right_item,
+ cond_equal, eq_list);
+ if (!is_converted)
+ thd->lex->current_select->cond_count++;
+ }
+ else
+ {
is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);
-
- if (!is_converted)
+ thd->lex->current_select->cond_count++;
+ }
+
+ if (!is_converted)
{
Item_func_eq *eq_item;
if (!(eq_item= new Item_func_eq(left_item, right_item)))
@@ -7003,6 +7012,7 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
SYNOPSIS
check_equality()
+ thd thread handle
item predicate to process
cond_equal multiple equalities that must hold together with the predicate
eq_list results of conversions of row equalities that are not simple
@@ -7027,7 +7037,7 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
or, if the procedure fails by a fatal error.
*/
-static bool check_equality(Item *item, COND_EQUAL *cond_equal,
+static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
List<Item> *eq_list)
{
if (item->type() == Item::FUNC_ITEM &&
@@ -7038,9 +7048,13 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
- return check_row_equality((Item_row *) left_item,
+ {
+ thd->lex->current_select->cond_count--;
+ return check_row_equality(thd,
+ (Item_row *) left_item,
(Item_row *) right_item,
cond_equal, eq_list);
+ }
else
return check_simple_equality(left_item, right_item, item, cond_equal);
}
@@ -7053,6 +7067,7 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
SYNOPSIS
build_equal_items_for_cond()
+ thd thread handle
cond condition(expression) where to make replacement
inherited path to all inherited multiple equality items
@@ -7115,7 +7130,7 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
pointer to the transformed condition
*/
-static COND *build_equal_items_for_cond(COND *cond,
+static COND *build_equal_items_for_cond(THD *thd, COND *cond,
COND_EQUAL *inherited)
{
Item_equal *item_equal;
@@ -7148,7 +7163,7 @@ static COND *build_equal_items_for_cond(COND *cond,
structure here because it's restored before each
re-execution of any prepared statement/stored procedure.
*/
- if (check_equality(item, &cond_equal, &eq_list))
+ if (check_equality(thd, item, &cond_equal, &eq_list))
li.remove();
}
@@ -7183,7 +7198,7 @@ static COND *build_equal_items_for_cond(COND *cond,
while ((item= li++))
{
Item *new_item;
- if ((new_item = build_equal_items_for_cond(item, inherited))!= item)
+ if ((new_item= build_equal_items_for_cond(thd, item, inherited)) != item)
{
/* This replacement happens only for standalone equalities */
/*
@@ -7213,7 +7228,7 @@ static COND *build_equal_items_for_cond(COND *cond,
for WHERE a=b AND c=d AND (b=c OR d=5)
b=c is replaced by =(a,b,c,d).
*/
- if (check_equality(cond, &cond_equal, &eq_list))
+ if (check_equality(thd, cond, &cond_equal, &eq_list))
{
int n= cond_equal.current_level.elements + eq_list.elements;
if (n == 0)
@@ -7276,7 +7291,7 @@ static COND *build_equal_items_for_cond(COND *cond,
SYNOPSIS
build_equal_items()
- thd Thread handler
+ thd thread handle
cond condition to build the multiple equalities for
inherited path to all inherited multiple equality items
join_list list of join tables to which the condition refers to
@@ -7337,7 +7352,7 @@ static COND *build_equal_items(THD *thd, COND *cond,
if (cond)
{
- cond= build_equal_items_for_cond(cond, inherited);
+ cond= build_equal_items_for_cond(thd, cond, inherited);
cond->update_used_tables();
if (cond->type() == Item::COND_ITEM &&
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)