diff --git a/mysql-test/main/strings.result b/mysql-test/main/strings.result index 2d0eb5e740009..6573e7344227f 100644 --- a/mysql-test/main/strings.result +++ b/mysql-test/main/strings.result @@ -18,3 +18,13 @@ LENGTH(CONCAT_WS(d, ' ')) 1 1 DROP TABLE t1; +# +# MDEV-28315 ASAN stack-buffer-overflow in String::copy_aligned +# +CREATE TABLE t1 (a VARBINARY(128)) CHARACTER SET utf32; +INSERT INTO t1 VALUES ('South Carolina, Vermont, New Jersey, New Mexico, Wisconsin, Missouri, Delaware'); +CREATE TABLE t2 (b SET('South Carolina', 'Vermont', 'Texas', 'New Mexico', 'Wisconsin', 'Missouri', 'Delaware', 'Wyoming', 'New Jersey', 'Maryland', 'Illinois', 'New York')) CHARACTER SET utf32; +INSERT INTO t2 SELECT * FROM t1; +ERROR 01000: Data truncated for column 'b' at row 1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/main/strings.test b/mysql-test/main/strings.test index 083ab7b07a416..3f3f4b572af84 100644 --- a/mysql-test/main/strings.test +++ b/mysql-test/main/strings.test @@ -24,3 +24,15 @@ CREATE TABLE t1 (d DATE); INSERT INTO t1 VALUES ('1920-03-02'),('2020-12-01'); SELECT LENGTH(CONCAT_WS(d, ' ')) FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-28315 ASAN stack-buffer-overflow in String::copy_aligned +--echo # + +CREATE TABLE t1 (a VARBINARY(128)) CHARACTER SET utf32; +INSERT INTO t1 VALUES ('South Carolina, Vermont, New Jersey, New Mexico, Wisconsin, Missouri, Delaware'); +CREATE TABLE t2 (b SET('South Carolina', 'Vermont', 'Texas', 'New Mexico', 'Wisconsin', 'Missouri', 'Delaware', 'Wyoming', 'New Jersey', 'Maryland', 'Illinois', 'New York')) CHARACTER SET utf32; +--error WARN_DATA_TRUNCATED +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1; +DROP TABLE t2; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 991b65ef4b298..90693f407fbc2 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -398,7 +398,7 @@ bool String::copy_aligned(const char *str, size_t arg_length, size_t offset, DBUG_ASSERT(offset && offset != cs->mbminlen); size_t aligned_length= arg_length + offset; - if (alloc(aligned_length)) + if (alloc(aligned_length+1)) return TRUE; /* diff --git a/sql/sql_string.h b/sql/sql_string.h index fe57c8153bb7b..b398d4437ee61 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -690,7 +690,7 @@ class Binary_string: public Sql_alloc Note that if arg_length == Alloced_length then we don't allocate. This ensures we don't do any extra allocations in protocol and String:int, - but the string will not be atomically null terminated if c_ptr() is not + but the string will not be automatically null terminated if c_ptr() is not called. */ if (arg_length <= Alloced_length && Alloced_length)