diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index 7f176290637e9..5b35d70a24d92 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -3035,3 +3035,19 @@ select * from (select * from t) as t natural join (select * from t) as t1; a b drop tables t, t4; # End of 10.5 tests +# +# MDEV-39450: Memory corruption: overlapping memory ranges in `Field_longstr::compress` on UPDATE of compressed column +# +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=RIGHT(c,10); +DROP TABLE t; +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=SUBSTRING(c,3); +DROP TABLE t; +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=MID(c,2,4); +DROP TABLE t; +# End of 10.6 tests diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index 874f3c3580bf2..2aba8862c6679 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -573,3 +573,24 @@ select * from (select * from t) as t natural join (select * from t) as t1; drop tables t, t4; --echo # End of 10.5 tests + +--echo # +--echo # MDEV-39450: Memory corruption: overlapping memory ranges in `Field_longstr::compress` on UPDATE of compressed column +--echo # + +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=RIGHT(c,10); +DROP TABLE t; + +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=SUBSTRING(c,3); +DROP TABLE t; + +CREATE TABLE t (c VARCHAR(255) COMPRESSED); +REPLACE INTO t VALUES ('abcdefghijklm'); +UPDATE t SET c=MID(c,2,4); +DROP TABLE t; + +--echo # End of 10.6 tests diff --git a/sql/field.cc b/sql/field.cc index 7fed7cdfc760d..4c43bb017b416 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8543,7 +8543,7 @@ int Field_longstr::compress(char *to, uint to_length, /* Store uncompressed */ to[0]= 0; if (buf_length < to_length) - memcpy(to + 1, buf, buf_length); + memmove(to + 1, buf, buf_length); else { /* Storing string at blob capacity, e.g. 255 bytes string to TINYBLOB. */