diff options
author | Gleb Shchepa <gleb.shchepa@oracle.com> | 2010-11-23 00:29:47 +0300 |
---|---|---|
committer | Gleb Shchepa <gleb.shchepa@oracle.com> | 2010-11-23 00:29:47 +0300 |
commit | 3586f7727f43275aa7e696d62f0e3bd444de2d24 (patch) | |
tree | cb79999eeac8931541a7d309a485b4657ffb4cd8 | |
parent | b31888294997ea450552127e6440ea970892f81e (diff) | |
download | mariadb-git-3586f7727f43275aa7e696d62f0e3bd444de2d24.tar.gz |
backport: Bug #55568 from 5.1-security to 5.0-security
> revision-id: alexey.kopytov@sun.com-20100824103548-ikm79qlfrvggyj9h
> parent: sunny.bains@oracle.com-20100816001222-xqc447tr6jwh8c53
> committer: Alexey Kopytov <Alexey.Kopytov@Sun.com>
> branch nick: 5.1-security
> timestamp: Tue 2010-08-24 14:35:48 +0400
> message:
> Bug #55568: user variable assignments crash server when used
> within query
>
> The server could crash after materializing a derived table
> which requires a temporary table for grouping.
>
> When destroying the temporary table used to execute a query for
> a derived table, JOIN::destroy() did not clean up Item_fields
> pointing to fields in the temporary table. This led to
> dereferencing a dangling pointer when printing out the items
> tree later in the outer SELECT.
>
> The solution is an addendum to the patch for bug37362: in
> addition to cleaning up items in tmp_all_fields3, do the same
> for items in tmp_all_fields1, since now we have an example
> where this is necessary.
-rw-r--r-- | mysql-test/r/join.result | 51 | ||||
-rw-r--r-- | mysql-test/t/join.test | 46 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 22 | ||||
-rw-r--r-- | sql/sql_select.h | 1 |
5 files changed, 114 insertions, 8 deletions
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index beba47cd39b..131efc7aaad 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -952,4 +952,55 @@ a b a b 0 0 0 0 1 1 1 1 DROP TABLE t1; +# +# Bug #55568: user variable assignments crash server when used within +# query +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0), (1); +SELECT MULTIPOINT( +1, +( +SELECT MULTIPOINT( +MULTIPOINT( +1, +(SELECT COUNT(*) FROM (SELECT 1 FROM t1 GROUP BY a,a) d) +) +) FROM t1 +) +) != COUNT(*) q FROM t1 GROUP BY a; +q +NULL +NULL +SELECT MULTIPOINT( +1, +( +SELECT MULTIPOINT( +MULTIPOINT( +1, +(SELECT COUNT(*) FROM (SELECT 1 FROM t1 GROUP BY a,a) d) +) +) FROM t1 +) +) != COUNT(*) q FROM t1 GROUP BY a; +q +NULL +NULL +DROP TABLE t1; +# +# Bug #54468: crash after item's print() function when ordering/grouping +# by subquery +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (), (); +SELECT 1 FROM t1 +GROUP BY +GREATEST(t1.a, +(SELECT 1 FROM +(SELECT t1.b FROM t1,t1 t2 +ORDER BY t1.a, t1.a LIMIT 1) AS d) +); +1 +1 +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index d51740bb380..17f2a64b24a 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -747,4 +747,50 @@ SELECT * FROM t1 STRAIGHT_JOIN t1 t2 ON t1.a=t2.a AND t1.a=t2.b ORDER BY t2.a, t DROP TABLE t1; +--echo # +--echo # Bug #55568: user variable assignments crash server when used within +--echo # query +--echo # + +CREATE TABLE t1 (a INT); + +INSERT INTO t1 VALUES (0), (1); + +let $i=2; +while ($i) +{ + SELECT MULTIPOINT( + 1, + ( + SELECT MULTIPOINT( + MULTIPOINT( + 1, + (SELECT COUNT(*) FROM (SELECT 1 FROM t1 GROUP BY a,a) d) + ) + ) FROM t1 + ) + ) != COUNT(*) q FROM t1 GROUP BY a; + dec $i; +} + +DROP TABLE t1; + +--echo # +--echo # Bug #54468: crash after item's print() function when ordering/grouping +--echo # by subquery +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (), (); + +SELECT 1 FROM t1 +GROUP BY +GREATEST(t1.a, + (SELECT 1 FROM + (SELECT t1.b FROM t1,t1 t2 + ORDER BY t1.a, t1.a LIMIT 1) AS d) + ); + +DROP TABLE t1; + --echo End of 5.0 tests. diff --git a/sql/field.cc b/sql/field.cc index b61e5fd2d79..3efd6111dcb 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1365,7 +1365,7 @@ void Field::make_field(Send_field *field) } else field->org_table_name= field->db_name= ""; - if (orig_table) + if (orig_table && orig_table->alias) { field->table_name= orig_table->alias; field->org_col_name= field_name; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 929ef3c8949..ff572172afa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2226,13 +2226,8 @@ JOIN::destroy() cleanup(1); /* Cleanup items referencing temporary table columns */ - if (!tmp_all_fields3.is_empty()) - { - List_iterator_fast<Item> it(tmp_all_fields3); - Item *item; - while ((item= it++)) - item->cleanup(); - } + cleanup_item_list(tmp_all_fields1); + cleanup_item_list(tmp_all_fields3); if (exec_tmp_table1) free_tmp_table(thd, exec_tmp_table1); if (exec_tmp_table2) @@ -2243,6 +2238,19 @@ JOIN::destroy() DBUG_RETURN(error); } + +void JOIN::cleanup_item_list(List<Item> &items) const +{ + if (!items.is_empty()) + { + List_iterator_fast<Item> it(items); + Item *item; + while ((item= it++)) + item->cleanup(); + } +} + + /* An entry point to single-unit select (a select without UNION). diff --git a/sql/sql_select.h b/sql/sql_select.h index 346d98aae58..553acd25624 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -489,6 +489,7 @@ public: } private: bool make_simple_join(JOIN *join, TABLE *tmp_table); + void cleanup_item_list(List<Item> &items) const; }; |