From: Date: March 31 2007 9:23am Subject: bk commit into 5.0 tree (igor:1.2427) BUG#27154 List-Archive: http://lists.mysql.com/commits/23452 X-Bug: 27154 Message-Id: <20070331072309.3E1A323256E@olga.mysql.com> Below is the list of changes that have just been committed into a local 5.0 repository of igor. When igor does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-03-31 00:23:03-07:00, igor@stripped +3 -0 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@stripped, 2007-03-31 00:23:00-07:00, igor@stripped +13 -0 Added a test case for bug #27154. mysql-test/t/row.test@stripped, 2007-03-31 00:23:00-07:00, igor@stripped +17 -0 Added a test case for bug #27154. sql/sql_select.cc@stripped, 2007-03-31 00:23:00-07:00, igor@stripped +30 -15 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. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: igor # Host: olga.mysql.com # Root: /home/igor/dev-opt/mysql-5.0-opt-bug27154 --- 1.505/sql/sql_select.cc 2007-03-31 00:23:09 -07:00 +++ 1.506/sql/sql_select.cc 2007-03-31 00:23:09 -07:00 @@ -6947,6 +6947,7 @@ 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 @@ 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* eq_list) { uint n= left_row->cols(); @@ -6978,13 +6979,21 @@ 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 @@ 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 @@ 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 *eq_list) { if (item->type() == Item::FUNC_ITEM && @@ -7038,9 +7048,13 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) --- 1.24/mysql-test/r/row.result 2007-03-31 00:23:09 -07:00 +++ 1.25/mysql-test/r/row.result 2007-03-31 00:23:09 -07:00 @@ -306,3 +306,16 @@ 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; --- 1.21/mysql-test/t/row.test 2007-03-31 00:23:09 -07:00 +++ 1.22/mysql-test/t/row.test 2007-03-31 00:23:09 -07:00 @@ -139,3 +139,20 @@ 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;