MDEV-21850: ASAN use-after-poison in page_cur_insert_rec_low()

page_cur_insert_rec_low(): 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 7ae21b18a6
and modified in commit 138cbec5f2.
This commit is contained in:
Marko Mäkelä 2020-03-26 16:05:25 +02:00
parent b8e7579194
commit 718f18599a
3 changed files with 17 additions and 6 deletions

View file

@ -78,3 +78,10 @@ INSERT INTO t1 VALUES
('0000-00-00 00:00:00', '0000-00-00 00:00:00');
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
DROP TABLE t1;
#
# MDEV-21850 ASAN use-after-poison in page_cur_insert_rec_low()
#
CREATE TABLE t1 (id INT PRIMARY KEY, a YEAR, INDEX(id,a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,NULL),(2,NULL);
UPDATE t1 SET a=0;
DROP TABLE t1;

View file

@ -82,3 +82,10 @@ INSERT INTO t1 VALUES
('0000-00-00 00:00:00', '0000-00-00 00:00:00');
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
DROP TABLE t1;
--echo #
--echo # MDEV-21850 ASAN use-after-poison in page_cur_insert_rec_low()
--echo #
CREATE TABLE t1 (id INT PRIMARY KEY, a YEAR, INDEX(id,a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,NULL),(2,NULL);
UPDATE t1 SET a=0;
DROP TABLE t1;

View file

@ -1562,13 +1562,10 @@ inc_dir:
c_end= std::min<const byte*>(c_end, block->frame + srv_page_size -
PAGE_DIR - PAGE_DIR_SLOT_SIZE *
page_dir_get_n_slots(block->frame));
size_t data_common= 0;
size_t data_common;
/* Copy common data bytes of the preceding record. */
if (c != c_end)
{
for (; *r == *c && c++ != c_end; r++);
data_common= static_cast<size_t>(r - rec);
}
for (; c != c_end && *r == *c; c++, r++);
data_common= static_cast<size_t>(r - rec);
if (comp)
mtr->page_insert(*block, reuse,