From aa2d545de2bc47b7a09d677b9240376ef7dc453b Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Fri, 28 Sep 2007 16:46:05 +0300 Subject: [PATCH] Bug #30587: mysql crashes when trying to group by TIME div NUMBER When calculating the result length of an integer DIV function the number of decimals was used without checking the result type first. Thus an uninitialized number of decimals was used for some types. This caused an excessive amount of memory to be allocated for the field's buffer and crashed the server. Fixed by using the number of decimals only for data types that can have decimals and thus have valid decimals number. --- mysql-test/r/func_math.result | 46 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_math.test | 27 ++++++++++++++++++++ sql/item_func.cc | 6 ++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index ace94217fdc..5ef528812e5 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -322,4 +322,50 @@ mod(5, cast(-2 as unsigned)) mod(5, 18446744073709551614) mod(5, -2) select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5); pow(cast(-2 as unsigned), 5) pow(18446744073709551614, 5) pow(-2, 5) 2.1359870359209e+96 2.1359870359209e+96 -32 +CREATE TABLE t1 (a timestamp, b varchar(20), c bit(1)); +INSERT INTO t1 VALUES('1998-09-23', 'str1', 1), ('2003-03-25', 'str2', 0); +SELECT a DIV 900 y FROM t1 GROUP BY y; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def y y 8 19 11 Y 32800 0 63 +y +22201025555 +22255916666 +SELECT DISTINCT a DIV 900 y FROM t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def y y 8 19 11 Y 32800 0 63 +y +22201025555 +22255916666 +SELECT b DIV 900 y FROM t1 GROUP BY y; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def y y 8 20 1 Y 32768 0 63 +y +0 +SELECT c DIV 900 y FROM t1 GROUP BY y; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def y y 3 1 1 Y 32800 0 63 +y +0 +DROP TABLE t1; +CREATE TABLE t1(a LONGBLOB); +INSERT INTO t1 VALUES('1'),('2'),('3'); +SELECT DISTINCT (a DIV 254576881) FROM t1; +(a DIV 254576881) +0 +SELECT (a DIV 254576881) FROM t1 UNION ALL +SELECT (a DIV 254576881) FROM t1; +(a DIV 254576881) +0 +0 +0 +0 +0 +0 +DROP TABLE t1; +CREATE TABLE t1(a SET('a','b','c')); +INSERT INTO t1 VALUES ('a'); +SELECT a DIV 2 FROM t1 UNION SELECT a DIV 2 FROM t1; +a DIV 2 +0 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 2ba07dfc581..1f46415741f 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -205,4 +205,31 @@ select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3); select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2); select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5); +# +# Bug #30587: mysql crashes when trying to group by TIME div NUMBER +# + +CREATE TABLE t1 (a timestamp, b varchar(20), c bit(1)); +INSERT INTO t1 VALUES('1998-09-23', 'str1', 1), ('2003-03-25', 'str2', 0); +--enable_metadata +SELECT a DIV 900 y FROM t1 GROUP BY y; +SELECT DISTINCT a DIV 900 y FROM t1; +SELECT b DIV 900 y FROM t1 GROUP BY y; +SELECT c DIV 900 y FROM t1 GROUP BY y; +--disable_metadata +DROP TABLE t1; + +CREATE TABLE t1(a LONGBLOB); +INSERT INTO t1 VALUES('1'),('2'),('3'); +SELECT DISTINCT (a DIV 254576881) FROM t1; +SELECT (a DIV 254576881) FROM t1 UNION ALL + SELECT (a DIV 254576881) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1(a SET('a','b','c')); +INSERT INTO t1 VALUES ('a'); +SELECT a DIV 2 FROM t1 UNION SELECT a DIV 2 FROM t1; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index d03d497dfd0..a90cc721ca9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1380,7 +1380,11 @@ longlong Item_func_int_div::val_int() void Item_func_int_div::fix_length_and_dec() { - max_length=args[0]->max_length - args[0]->decimals; + Item_result argtype= args[0]->result_type(); + /* use precision ony for the data type it is applicable for and valid */ + max_length=args[0]->max_length - + (argtype == DECIMAL_RESULT || argtype == INT_RESULT ? + args[0]->decimals : 0); maybe_null=1; unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag; }