From 561b5ce3647a63c343f70ce183e408423b3fa65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Mar 2020 10:23:04 +0200 Subject: [PATCH] MDEV-21748 ASAN use-after-poison in PageBulk::insertPage() PageBulk::insertPage(): Check the array bounds before comparing. We used to read one byte beyond the end of the 'rec' payload. The incorrect logic was originally introduced in commit 7ae21b18a6b73bbc3bf1ff448faf60c29ac1d386. --- mysql-test/suite/innodb/r/alter_table.result | 10 ++++++++++ mysql-test/suite/innodb/t/alter_table.test | 11 +++++++++++ storage/innobase/btr/btr0bulk.cc | 4 +++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index 0cfd3096f3f..1e7e55494d4 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -68,3 +68,13 @@ t2 CREATE TABLE `t2` ( alter table t1 engine=innodb; alter table t1 add column b int; drop table t1,t2; +# +# MDEV-21748 ASAN use-after-poison in PageBulk::insertPage() +# +CREATE TABLE t1 (pk TIMESTAMP PRIMARY KEY, a TIMESTAMP NULL UNIQUE) +ENGINE=InnoDB; +INSERT INTO t1 VALUES +('2020-03-10 10:21:00', NULL), +('0000-00-00 00:00:00', '0000-00-00 00:00:00'); +ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index a8b52732c91..4827e3440e1 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -71,3 +71,14 @@ show create table t2; alter table t1 engine=innodb; alter table t1 add column b int; drop table t1,t2; + +--echo # +--echo # MDEV-21748 ASAN use-after-poison in PageBulk::insertPage() +--echo # +CREATE TABLE t1 (pk TIMESTAMP PRIMARY KEY, a TIMESTAMP NULL UNIQUE) +ENGINE=InnoDB; +INSERT INTO t1 VALUES + ('2020-03-10 10:21:00', NULL), + ('0000-00-00 00:00:00', '0000-00-00 00:00:00'); +ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; +DROP TABLE t1; diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index aeeb5850713..1171de544a7 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -270,9 +270,11 @@ no_data: byte *bd= insert_rec; const byte *rd= rec; /* Skip any unchanged prefix of the record. */ - for (; *bd == *rd; cd++, bd++, rd++) + for (;; cd++, bd++, rd++) if (bd == insert_rec_end) goto no_data; + else if (*bd != *rd) + break; /* Try to copy any data bytes of the preceding record. */ if (c_end - cd > 2)