summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2018-04-03 16:19:37 +0400
committerSergey Vojtovich <svoj@mariadb.org>2018-04-20 17:05:28 +0400
commit3dec6c48bce84a6c804f2a714aa899aef8c45f93 (patch)
tree97bcb6b0a8a6c2e2c9588fe35e5853def16e0b2c
parent43ab88f0ea4169f5b1a4681320c4fa5f5423585e (diff)
downloadmariadb-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.result13
-rw-r--r--mysql-test/main/column_compression.test11
-rw-r--r--sql/field.cc11
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