diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2018-04-03 16:19:37 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2018-04-20 17:05:28 +0400 |
commit | 3dec6c48bce84a6c804f2a714aa899aef8c45f93 (patch) | |
tree | 97bcb6b0a8a6c2e2c9588fe35e5853def16e0b2c | |
parent | 43ab88f0ea4169f5b1a4681320c4fa5f5423585e (diff) | |
download | mariadb-git-3dec6c48bce84a6c804f2a714aa899aef8c45f93.tar.gz |
MDEV-15762 - VARCHAR(0) COMPRESSED crashes the server
Character set safe truncation is done when storing non-empty string in
VARCHAR(0) COMPRESSED column, so that string becomes empty. The code
didn't expect empty string after truncation.
Fixed by moving empty string check after truncation.
-rw-r--r-- | mysql-test/main/column_compression.result | 13 | ||||
-rw-r--r-- | mysql-test/main/column_compression.test | 11 | ||||
-rw-r--r-- | sql/field.cc | 11 |
3 files changed, 27 insertions, 8 deletions
diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index b3d4caad555..4362dff4942 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -1373,3 +1373,16 @@ bar foo SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1; +# +# MDEV-15762 - VARCHAR(0) COMPRESSED crashes the server +# +CREATE TABLE t1(a VARCHAR(0) COMPRESSED); +INSERT INTO t1 VALUES('a'); +ERROR 22001: Data too long for column 'a' at row 1 +INSERT INTO t1 VALUES(' '); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT LENGTH(a) FROM t1; +LENGTH(a) +0 +DROP TABLE t1; diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index 6d6ed3d3993..af1886e0a54 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -91,3 +91,14 @@ SET SESSION optimizer_switch = 'derived_merge=off'; SELECT * FROM ( SELECT * FROM t1 ) AS sq ORDER BY b; SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1; + + +--echo # +--echo # MDEV-15762 - VARCHAR(0) COMPRESSED crashes the server +--echo # +CREATE TABLE t1(a VARCHAR(0) COMPRESSED); +--error ER_DATA_TOO_LONG +INSERT INTO t1 VALUES('a'); +INSERT INTO t1 VALUES(' '); +SELECT LENGTH(a) FROM t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 5b1bea4b803..58b8105c00f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7958,12 +7958,6 @@ int Field_longstr::compress(char *to, uint *to_length, char *buf= 0; int rc= 0; - if (length == 0) - { - *to_length= 0; - return 0; - } - if (String::needs_conversion_on_storage(length, cs, field_charset) || *to_length <= length) { @@ -7981,10 +7975,11 @@ int Field_longstr::compress(char *to, uint *to_length, (*to_length - 1) / field_charset->mbmaxlen); rc= check_conversion_status(&copier, end, cs, true); from= buf; - DBUG_ASSERT(length > 0); } - if (length >= thd->variables.column_compression_threshold && + if (length == 0) + *to_length= 0; + else if (length >= thd->variables.column_compression_threshold && (*to_length= compression_method()->compress(thd, to, from, length))) status_var_increment(thd->status_var.column_compressions); else |