Commit 7887a744 authored by unknown's avatar unknown

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.
parent 8aa507ed
......@@ -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;
......@@ -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;
......@@ -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,11 +6979,19 @@ 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,
{
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);
thd->lex->current_select->cond_count++;
}
if (!is_converted)
{
......@@ -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)
......
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