tags 599937 patch thanks On Tue, Oct 12, 2010 at 05:56:38PM +0200, Moritz Muehlenhoff wrote: > Package: mysql-5.1 > Severity: grave > Tags: security > Justification: user security hole > > 5.1.51 fixes eight security issues. It has already been uploaded > to experimental, so depending on the amount and quality of > changes it needs to be checked whether this version shold be > uploaded to Squeeze or fixes need to be cherry-picked:
Patch against 5.1.49 attached. Cheers, Moritz
diff -Naur mysql-5.1-5.1.49.orig//mysql-test/r/func_gconcat.result mysql-5.1-5.1.49/mysql-test/r/func_gconcat.result --- mysql-5.1-5.1.49.orig//mysql-test/r/func_gconcat.result 2010-07-09 15:02:55.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/r/func_gconcat.result 2010-10-29 21:52:45.000000000 +0200 @@ -995,6 +995,7 @@ 1 1 DROP TABLE t1; +End of 5.0 tests # # Bug #52397: another crash with explain extended and group_concat # @@ -1010,4 +1011,22 @@ Warnings: Note 1003 select 1 AS `1` from (select group_concat(`test`.`t1`.`a` order by `test`.`t1`.`a` ASC separator ',') AS `GROUP_CONCAT(t1.a ORDER BY t1.a ASC)` from `test`.`t1` `t2` join `test`.`t1` group by `test`.`t1`.`a`) `d` DROP TABLE t1; -End of 5.0 tests +# +# Bug #54476: crash when group_concat and 'with rollup' in prepared statements +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/r/func_misc.result mysql-5.1-5.1.49/mysql-test/r/func_misc.result --- mysql-5.1-5.1.49.orig//mysql-test/r/func_misc.result 2010-07-09 15:02:55.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/r/func_misc.result 2010-10-29 21:52:47.000000000 +0200 @@ -336,4 +336,19 @@ select connection_id() > 0; connection_id() > 0 1 +# +# Bug #54461: crash with longblob and union or update with subquery +# +CREATE TABLE t1 (a INT, b LONGBLOB); +INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2'); +SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +LEAST(a, (SELECT b FROM t1 LIMIT 1)) +1 +2 +SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +GREATEST(a, (SELECT b FROM t1 LIMIT 1)) +2 +3 +1 +DROP TABLE t1; End of tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/r/join.result mysql-5.1-5.1.49/mysql-test/r/join.result --- mysql-5.1-5.1.49.orig//mysql-test/r/join.result 2010-07-09 15:03:00.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/r/join.result 2010-10-29 21:52:39.000000000 +0200 @@ -1184,4 +1184,55 @@ NULL 1 DROP TABLE t1, t2, mm1; +# +# 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.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/r/user_var.result mysql-5.1-5.1.49/mysql-test/r/user_var.result --- mysql-5.1-5.1.49.orig//mysql-test/r/user_var.result 2010-07-09 15:03:13.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/r/user_var.result 2010-10-29 21:52:42.000000000 +0200 @@ -430,4 +430,21 @@ INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1); DROP TABLE t1; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (0),(0); +# BUG#55615 : should not crash +SELECT (@a:=(SELECT @a:=1 FROM t1 LIMIT 1)) AND COUNT(1) FROM t1 GROUP BY @a; +(@a:=(SELECT @a:=1 FROM t1 LIMIT 1)) AND COUNT(1) +1 +1 +# BUG#55564 : should not crash +SELECT IF( +...@v:=LEAST((SELECT 1 FROM t1 t2 LEFT JOIN t1 ON (@v) GROUP BY t1.a), a), +count(*), 1) +FROM t1 GROUP BY a LIMIT 1; +IF( +...@v:=LEAST((SELECT 1 FROM t1 t2 LEFT JOIN t1 ON (@v) GROUP BY t1.a), a), +count(*), 1) +1 +DROP TABLE t1; End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/suite/innodb/r/innodb_mysql.result mysql-5.1-5.1.49/mysql-test/suite/innodb/r/innodb_mysql.result --- mysql-5.1-5.1.49.orig//mysql-test/suite/innodb/r/innodb_mysql.result 2010-07-09 15:05:40.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/suite/innodb/r/innodb_mysql.result 2010-10-29 21:52:36.000000000 +0200 @@ -2499,4 +2499,17 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where DROP TABLE t1; +# +# Bug#55826: create table .. select crashes with when KILL_BAD_DATA +# is returned +# +CREATE TABLE t1(a INT) ENGINE=innodb; +INSERT INTO t1 VALUES (0); +SET SQL_MODE='STRICT_ALL_TABLES'; +CREATE TABLE t2 +SELECT LEAST((SELECT '' FROM t1),NOW()) FROM `t1`; +ERROR 22007: Incorrect datetime value: '' for column 'NOW()' at row 1 +DROP TABLE t1,t2; +ERROR 42S02: Unknown table 't2' +SET SQL_MODE=DEFAULT; End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/suite/innodb/t/innodb_mysql.test mysql-5.1-5.1.49/mysql-test/suite/innodb/t/innodb_mysql.test --- mysql-5.1-5.1.49.orig//mysql-test/suite/innodb/t/innodb_mysql.test 2010-07-09 15:05:37.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/suite/innodb/t/innodb_mysql.test 2010-10-29 21:52:36.000000000 +0200 @@ -737,4 +737,19 @@ DROP TABLE t1; +--echo # +--echo # Bug#55826: create table .. select crashes with when KILL_BAD_DATA +--echo # is returned +--echo # + +CREATE TABLE t1(a INT) ENGINE=innodb; +INSERT INTO t1 VALUES (0); +SET SQL_MODE='STRICT_ALL_TABLES'; +--error ER_TRUNCATED_WRONG_VALUE +CREATE TABLE t2 + SELECT LEAST((SELECT '' FROM t1),NOW()) FROM `t1`; +DROP TABLE t1,t2; +SET SQL_MODE=DEFAULT; + + --echo End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/t/func_gconcat.test mysql-5.1-5.1.49/mysql-test/t/func_gconcat.test --- mysql-5.1-5.1.49.orig//mysql-test/t/func_gconcat.test 2010-07-09 15:02:26.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/t/func_gconcat.test 2010-10-29 21:52:45.000000000 +0200 @@ -708,6 +708,7 @@ DROP TABLE t1; +--echo End of 5.0 tests --echo # --echo # Bug #52397: another crash with explain extended and group_concat @@ -719,5 +720,18 @@ t1 t2, t1 GROUP BY t1.a) AS d; DROP TABLE t1; +--echo # +--echo # Bug #54476: crash when group_concat and 'with rollup' in prepared statements +--echo # ---echo End of 5.0 tests +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/t/func_misc.test mysql-5.1-5.1.49/mysql-test/t/func_misc.test --- mysql-5.1-5.1.49.orig//mysql-test/t/func_misc.test 2010-07-09 15:02:27.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/t/func_misc.test 2010-10-29 21:52:47.000000000 +0200 @@ -467,4 +467,16 @@ select connection_id() > 0; +--echo # +--echo # Bug #54461: crash with longblob and union or update with subquery +--echo # + +CREATE TABLE t1 (a INT, b LONGBLOB); +INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2'); + +SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; +SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1; + +DROP TABLE t1; + --echo End of tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/t/join.test mysql-5.1-5.1.49/mysql-test/t/join.test --- mysql-5.1-5.1.49.orig//mysql-test/t/join.test 2010-07-09 15:02:30.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/t/join.test 2010-10-29 21:52:50.000000000 +0200 @@ -851,4 +851,70 @@ SELECT t1.a FROM mm1,t1; DROP TABLE t1, t2, mm1; +--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 # +--echo # Bug #53544: Server hangs during JOIN query in stored procedure called +--echo # twice in a row +--echo # + +CREATE TABLE t1(c INT); + +INSERT INTO t1 VALUES (1), (2); + +PREPARE stmt FROM "SELECT t2.c AS f1 FROM t1 LEFT JOIN + t1 t2 ON t1.c=t2.c RIGHT JOIN + t1 t3 ON t1.c=t3.c + GROUP BY f1;"; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + --echo End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//mysql-test/t/user_var.test mysql-5.1-5.1.49/mysql-test/t/user_var.test --- mysql-5.1-5.1.49.orig//mysql-test/t/user_var.test 2010-07-09 15:02:46.000000000 +0200 +++ mysql-5.1-5.1.49/mysql-test/t/user_var.test 2010-10-29 21:52:42.000000000 +0200 @@ -328,4 +328,22 @@ INSERT INTO t1 VALUES (1); DROP TABLE t1; +# +# Bug #55615: debug assertion after using variable in assignment and +# referred to +# Bug #55564: crash with user variables, assignments, joins... +# + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (0),(0); +--echo # BUG#55615 : should not crash +SELECT (@a:=(SELECT @a:=1 FROM t1 LIMIT 1)) AND COUNT(1) FROM t1 GROUP BY @a; +--echo # BUG#55564 : should not crash +SELECT IF( + @v:=LEAST((SELECT 1 FROM t1 t2 LEFT JOIN t1 ON (@v) GROUP BY t1.a), a), + count(*), 1) +FROM t1 GROUP BY a LIMIT 1; + +DROP TABLE t1; + --echo End of 5.1 tests diff -Naur mysql-5.1-5.1.49.orig//sql/field.cc mysql-5.1-5.1.49/sql/field.cc --- mysql-5.1-5.1.49.orig//sql/field.cc 2010-07-09 14:34:53.000000000 +0200 +++ mysql-5.1-5.1.49/sql/field.cc 2010-10-29 21:52:40.000000000 +0200 @@ -1535,7 +1535,7 @@ } 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 -Naur mysql-5.1-5.1.49.orig//sql/item_cmpfunc.cc mysql-5.1-5.1.49/sql/item_cmpfunc.cc --- mysql-5.1-5.1.49.orig//sql/item_cmpfunc.cc 2010-07-09 14:34:57.000000000 +0200 +++ mysql-5.1-5.1.49/sql/item_cmpfunc.cc 2010-10-29 21:50:27.000000000 +0200 @@ -4662,7 +4662,8 @@ recompute the tables for each row it's not worth it. */ if (args[1]->const_item() && !use_strnxfrm(collation.collation) && - !(specialflag & SPECIAL_NO_NEW_FUNC)) + !(specialflag & SPECIAL_NO_NEW_FUNC) && + !thd->lex->view_prepare_mode) { String* res2 = args[1]->val_str(&cmp.value2); if (!res2) diff -Naur mysql-5.1-5.1.49.orig//sql/item_func.cc mysql-5.1-5.1.49/sql/item_func.cc --- mysql-5.1-5.1.49.orig//sql/item_func.cc 2010-07-09 14:34:56.000000000 +0200 +++ mysql-5.1-5.1.49/sql/item_func.cc 2010-10-29 21:52:47.000000000 +0200 @@ -2243,6 +2243,8 @@ max_length= my_decimal_precision_to_length_no_truncation(max_int_part + decimals, decimals, unsigned_flag); + else if (cmp_type == REAL_RESULT) + max_length= float_length(decimals); cached_field_type= agg_field_type(args, arg_count); } @@ -2261,7 +2263,7 @@ stored to the value pointer, if latter is provided. RETURN - 0 If one of arguments is NULL + 0 If one of arguments is NULL or there was a execution error # index of the least/greatest argument */ @@ -2275,6 +2277,14 @@ Item **arg= args + i; bool is_null; longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); + + /* Check if we need to stop (because of error or KILL) and stop the loop */ + if (thd->is_error()) + { + null_value= 1; + return 0; + } + if ((null_value= args[i]->null_value)) return 0; if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0) @@ -2303,6 +2313,12 @@ if (null_value) return 0; str_res= args[min_max_idx]->val_str(str); + if (args[min_max_idx]->null_value) + { + // check if the call to val_str() above returns a NULL value + null_value= 1; + return NULL; + } str_res->set_charset(collation.collation); return str_res; } @@ -4261,6 +4277,14 @@ return entry->val_int(&null_value); } +bool Item_func_set_user_var::val_bool_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return entry->val_int(&null_value) != 0; +} + String *Item_func_set_user_var::str_result(String *str) { DBUG_ASSERT(fixed == 1); diff -Naur mysql-5.1-5.1.49.orig//sql/item_func.h mysql-5.1-5.1.49/sql/item_func.h --- mysql-5.1-5.1.49.orig//sql/item_func.h 2010-07-09 14:35:10.000000000 +0200 +++ mysql-5.1-5.1.49/sql/item_func.h 2010-10-29 21:52:42.000000000 +0200 @@ -1353,6 +1353,7 @@ my_decimal *val_decimal(my_decimal *); double val_result(); longlong val_int_result(); + bool val_bool_result(); String *str_result(String *str); my_decimal *val_decimal_result(my_decimal *); bool is_null_result(); diff -Naur mysql-5.1-5.1.49.orig//sql/item_sum.cc mysql-5.1-5.1.49/sql/item_sum.cc --- mysql-5.1-5.1.49.orig//sql/item_sum.cc 2010-07-09 14:34:53.000000000 +0200 +++ mysql-5.1-5.1.49/sql/item_sum.cc 2010-10-29 21:52:45.000000000 +0200 @@ -3034,7 +3034,6 @@ tree(item->tree), unique_filter(item->unique_filter), table(item->table), - order(item->order), context(item->context), arg_count_order(item->arg_count_order), arg_count_field(item->arg_count_field), @@ -3047,6 +3046,24 @@ { quick_group= item->quick_group; result.set_charset(collation.collation); + + /* + Since the ORDER structures pointed to by the elements of the 'order' array + may be modified in find_order_in_list() called from + Item_func_group_concat::setup(), create a copy of those structures so that + such modifications done in this object would not have any effect on the + object being copied. + */ + ORDER *tmp; + if (!(order= (ORDER **) thd->alloc(sizeof(ORDER *) * arg_count_order + + sizeof(ORDER) * arg_count_order))) + return; + tmp= (ORDER *)(order + arg_count_order); + for (uint i= 0; i < arg_count_order; i++, tmp++) + { + memcpy(tmp, item->order[i], sizeof(ORDER)); + order[i]= tmp; + } } diff -Naur mysql-5.1-5.1.49.orig//sql/spatial.cc mysql-5.1-5.1.49/sql/spatial.cc --- mysql-5.1-5.1.49.orig//sql/spatial.cc 2010-07-09 14:35:15.000000000 +0200 +++ mysql-5.1-5.1.49/sql/spatial.cc 2010-10-29 21:52:04.000000000 +0200 @@ -522,7 +522,7 @@ n_points= wkb_get_uint(wkb, bo); proper_length= 4 + n_points * POINT_DATA_SIZE; - if (len < proper_length || res->reserve(proper_length)) + if (!n_points || len < proper_length || res->reserve(proper_length)) return 0; res->q_append(n_points); @@ -740,7 +740,9 @@ if (len < 4) return 0; - n_linear_rings= wkb_get_uint(wkb, bo); + if (!(n_linear_rings= wkb_get_uint(wkb, bo))) + return 0; + if (res->reserve(4, 512)) return 0; wkb+= 4; diff -Naur mysql-5.1-5.1.49.orig//sql/sql_select.cc mysql-5.1-5.1.49/sql/sql_select.cc --- mysql-5.1-5.1.49.orig//sql/sql_select.cc 2010-07-09 14:34:57.000000000 +0200 +++ mysql-5.1-5.1.49/sql/sql_select.cc 2010-10-29 21:52:50.000000000 +0200 @@ -2378,13 +2378,8 @@ 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) @@ -2395,6 +2390,19 @@ 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). @@ -8875,10 +8883,10 @@ /* Flatten nested joins that can be flattened. */ TABLE_LIST *right_neighbor= NULL; - bool fix_name_res= FALSE; li.rewind(); while ((table= li++)) { + bool fix_name_res= FALSE; nested_join= table->nested_join; if (nested_join && !table->on_expr) { diff -Naur mysql-5.1-5.1.49.orig//sql/sql_select.h mysql-5.1-5.1.49/sql/sql_select.h --- mysql-5.1-5.1.49.orig//sql/sql_select.h 2010-07-09 14:34:56.000000000 +0200 +++ mysql-5.1-5.1.49/sql/sql_select.h 2010-10-29 21:52:40.000000000 +0200 @@ -577,6 +577,7 @@ */ bool implicit_grouping; bool make_simple_join(JOIN *join, TABLE *tmp_table); + void cleanup_item_list(List<Item> &items) const; }; diff -Naur mysql-5.1-5.1.49.orig//sql/table.h mysql-5.1-5.1.49/sql/table.h --- mysql-5.1-5.1.49.orig//sql/table.h 2010-07-09 14:34:54.000000000 +0200 +++ mysql-5.1-5.1.49/sql/table.h 2010-10-29 21:52:45.000000000 +0200 @@ -55,7 +55,6 @@ struct st_order *next; Item **item; /* Point at item in select fields */ Item *item_ptr; /* Storage for initial item */ - Item **item_copy; /* For SPs; the original item ptr */ int counter; /* position in SELECT list, correct only if counter_used is true*/ bool asc; /* true if ascending */