diff options
-rw-r--r-- | mysql-test/main/column_compression.result | 8 | ||||
-rw-r--r-- | mysql-test/main/column_compression.test | 10 | ||||
-rw-r--r-- | sql/field_comp.cc | 22 |
3 files changed, 39 insertions, 1 deletions
diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index 4362dff4942..8b7f0f7f611 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -1386,3 +1386,11 @@ SELECT LENGTH(a) FROM t1; LENGTH(a) 0 DROP TABLE t1; +# +# MDEV-15763 - VARCHAR(1) COMPRESSED crashes the server +# +CREATE TABLE t1(a VARCHAR(1) COMPRESSED); +SET column_compression_threshold=0; +INSERT INTO t1 VALUES('a'); +SET column_compression_threshold=DEFAULT; +DROP TABLE t1; diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index af1886e0a54..84f17076494 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -102,3 +102,13 @@ INSERT INTO t1 VALUES('a'); INSERT INTO t1 VALUES(' '); SELECT LENGTH(a) FROM t1; DROP TABLE t1; + + +--echo # +--echo # MDEV-15763 - VARCHAR(1) COMPRESSED crashes the server +--echo # +CREATE TABLE t1(a VARCHAR(1) COMPRESSED); +SET column_compression_threshold=0; +INSERT INTO t1 VALUES('a'); +SET column_compression_threshold=DEFAULT; +DROP TABLE t1; diff --git a/sql/field_comp.cc b/sql/field_comp.cc index 9a7b3a7c7e0..cbd8215485e 100644 --- a/sql/field_comp.cc +++ b/sql/field_comp.cc @@ -21,11 +21,30 @@ #include <zlib.h> +/** + Compresses string using zlib + + @param[out] to destination buffer for compressed data + @param[in] from data to compress + @param[in] length from length + + Requirement is such that string stored at `to' must not exceed `from' length. + Otherwise 0 is returned and caller stores string uncompressed. + + `to' must be large enough to hold `length' bytes. + + length == 1 is an edge case that may break stream.avail_out calculation: at + least 2 bytes required to store metadata. +*/ + static uint compress_zlib(THD *thd, char *to, const char *from, uint length) { uint level= thd->variables.column_compression_zlib_level; - if (level > 0) + /* Caller takes care of empty strings. */ + DBUG_ASSERT(length); + + if (level > 0 && length > 1) { z_stream stream; int wbits= thd->variables.column_compression_zlib_wrap ? MAX_WBITS : @@ -40,6 +59,7 @@ static uint compress_zlib(THD *thd, char *to, const char *from, uint length) stream.avail_in= length; stream.next_in= (Bytef*) from; + DBUG_ASSERT(length >= original_pack_length + 1); stream.avail_out= length - original_pack_length - 1; stream.next_out= (Bytef*) to + original_pack_length + 1; |