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 ...@@ -306,3 +306,16 @@ a b a b c
1 1 1 2 1 1 1 1 2 1
1 2 1 2 1 1 2 1 2 1
DROP TABLE t1,t2; 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); ...@@ -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); SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
DROP TABLE t1,t2; 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, ...@@ -6947,6 +6947,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
SYNOPSIS SYNOPSIS
check_row_equality() check_row_equality()
thd thread handle
left_row left term of the row equality to be processed left_row left term of the row equality to be processed
right_row right 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 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, ...@@ -6967,7 +6968,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
FALSE otherwise 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) COND_EQUAL *cond_equal, List<Item>* eq_list)
{ {
uint n= left_row->cols(); uint n= left_row->cols();
...@@ -6978,13 +6979,21 @@ static bool check_row_equality(Item *left_row, Item_row *right_row, ...@@ -6978,13 +6979,21 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
Item *right_item= right_row->element_index(i); Item *right_item= right_row->element_index(i);
if (left_item->type() == Item::ROW_ITEM && if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM) right_item->type() == Item::ROW_ITEM)
is_converted= check_row_equality((Item_row *) left_item, {
(Item_row *) right_item, is_converted= check_row_equality(thd,
cond_equal, eq_list); (Item_row *) left_item,
else (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); is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);
thd->lex->current_select->cond_count++;
if (!is_converted) }
if (!is_converted)
{ {
Item_func_eq *eq_item; Item_func_eq *eq_item;
if (!(eq_item= new Item_func_eq(left_item, right_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, ...@@ -7003,6 +7012,7 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
SYNOPSIS SYNOPSIS
check_equality() check_equality()
thd thread handle
item predicate to process item predicate to process
cond_equal multiple equalities that must hold together with the predicate cond_equal multiple equalities that must hold together with the predicate
eq_list results of conversions of row equalities that are not simple 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, ...@@ -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. 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) List<Item> *eq_list)
{ {
if (item->type() == Item::FUNC_ITEM && if (item->type() == Item::FUNC_ITEM &&
...@@ -7038,9 +7048,13 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal, ...@@ -7038,9 +7048,13 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
if (left_item->type() == Item::ROW_ITEM && if (left_item->type() == Item::ROW_ITEM &&
right_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, (Item_row *) right_item,
cond_equal, eq_list); cond_equal, eq_list);
}
else else
return check_simple_equality(left_item, right_item, item, cond_equal); 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, ...@@ -7053,6 +7067,7 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
SYNOPSIS SYNOPSIS
build_equal_items_for_cond() build_equal_items_for_cond()
thd thread handle
cond condition(expression) where to make replacement cond condition(expression) where to make replacement
inherited path to all inherited multiple equality items inherited path to all inherited multiple equality items
...@@ -7115,7 +7130,7 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal, ...@@ -7115,7 +7130,7 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal,
pointer to the transformed condition 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) COND_EQUAL *inherited)
{ {
Item_equal *item_equal; Item_equal *item_equal;
...@@ -7148,7 +7163,7 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -7148,7 +7163,7 @@ static COND *build_equal_items_for_cond(COND *cond,
structure here because it's restored before each structure here because it's restored before each
re-execution of any prepared statement/stored procedure. 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(); li.remove();
} }
...@@ -7183,7 +7198,7 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -7183,7 +7198,7 @@ static COND *build_equal_items_for_cond(COND *cond,
while ((item= li++)) while ((item= li++))
{ {
Item *new_item; 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 */ /* This replacement happens only for standalone equalities */
/* /*
...@@ -7213,7 +7228,7 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -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) for WHERE a=b AND c=d AND (b=c OR d=5)
b=c is replaced by =(a,b,c,d). 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; int n= cond_equal.current_level.elements + eq_list.elements;
if (n == 0) if (n == 0)
...@@ -7276,7 +7291,7 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -7276,7 +7291,7 @@ static COND *build_equal_items_for_cond(COND *cond,
SYNOPSIS SYNOPSIS
build_equal_items() build_equal_items()
thd Thread handler thd thread handle
cond condition to build the multiple equalities for cond condition to build the multiple equalities for
inherited path to all inherited multiple equality items inherited path to all inherited multiple equality items
join_list list of join tables to which the condition refers to 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, ...@@ -7337,7 +7352,7 @@ static COND *build_equal_items(THD *thd, COND *cond,
if (cond) if (cond)
{ {
cond= build_equal_items_for_cond(cond, inherited); cond= build_equal_items_for_cond(thd, cond, inherited);
cond->update_used_tables(); cond->update_used_tables();
if (cond->type() == Item::COND_ITEM && if (cond->type() == Item::COND_ITEM &&
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) ((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