diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index 4a3454cf658..a30ca7859f1 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -116,4 +116,19 @@ Warnings: Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted drop table t1; +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1), (1111), (11111); +SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; +UNCOMPRESS(c1) UNCOMPRESSED_LENGTH(c1) +NULL NULL +NULL NULL +NULL 825307441 +Warnings: +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 68f07f258bf..b1a37c16c6d 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -82,4 +82,21 @@ select *, uncompress(a) from t1; select *, uncompress(a), uncompress(a) is null from t1; drop table t1; +# +# Bug #44796: valgrind: too many my_longlong10_to_str_8bit warnings after +# uncompressed_length +# + +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1), (1111), (11111); + +SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; + +# We do not need the results, just make sure there are no valgrind errors +--disable_result_log +EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; +--enable_result_log + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index bc2dcb9c61b..4941f427731 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3108,7 +3108,21 @@ longlong Item_func_uncompressed_length::val_int() if (res->is_empty()) return 0; /* - res->ptr() using is safe because we have tested that string is not empty, + If length is <= 4 bytes, data is corrupt. This is the best we can do + to detect garbage input without decompressing it. + */ + if (res->length() <= 4) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_ZLIB_Z_DATA_ERROR, + ER(ER_ZLIB_Z_DATA_ERROR)); + null_value= 1; + return 0; + } + + /* + res->ptr() using is safe because we have tested that string is at least + 5 bytes long. res->c_ptr() is not used because: - we do not need \0 terminated string to get first 4 bytes - c_ptr() tests simbol after string end (uninitialiozed memory) which