summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-03-09 18:03:31 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-03-11 14:21:28 +0200
commit549a70d7f01ce723b1b06fd7be569211a8270bcd (patch)
tree6de21246514db36bed74fe4adf3f31d892ab5c1b
parenta6cd4612a9e802a365f8fc37e0da6a24e2541133 (diff)
downloadmariadb-git-549a70d7f01ce723b1b06fd7be569211a8270bcd.tar.gz
MDEV-25031 Not applying INSERT_*_REDUNDANT due to corruption on page
page_apply_insert_redundant(): Replace a too strict condition hdr_c > pextra_size. It turns out that page_cur_insert_rec_low() is not even computing the extra_size of cur->rec when it is trying to reuse header bytes of the preceding record.
-rw-r--r--storage/innobase/include/page0cur.h4
-rw-r--r--storage/innobase/page/page0cur.cc8
2 files changed, 7 insertions, 5 deletions
diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h
index 57c3a8f66fc..c0f3bf6866e 100644
--- a/storage/innobase/include/page0cur.h
+++ b/storage/innobase/include/page0cur.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -205,7 +205,7 @@ page_cur_delete_rec(
written by page_cur_insert_rec_low() for a ROW_FORMAT=REDUNDANT page.
@param block B-tree or R-tree page in ROW_FORMAT=COMPACT or DYNAMIC
@param reuse false=allocate from PAGE_HEAP_TOP; true=reuse PAGE_FREE
-@param prev byte offset of the predecessor, relative to PAGE_NEW_INFIMUM
+@param prev byte offset of the predecessor, relative to PAGE_OLD_INFIMUM
@param enc_hdr encoded fixed-size header bits
@param hdr_c number of common record header bytes with prev
@param data_c number of common data bytes with prev
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index 781884842ef..cb4293f998a 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2288,7 +2288,7 @@ page_cur_delete_rec(
written by page_cur_insert_rec_low() for a ROW_FORMAT=REDUNDANT page.
@param block B-tree or R-tree page in ROW_FORMAT=COMPACT or DYNAMIC
@param reuse false=allocate from PAGE_HEAP_TOP; true=reuse PAGE_FREE
-@param prev byte offset of the predecessor, relative to PAGE_NEW_INFIMUM
+@param prev byte offset of the predecessor, relative to PAGE_OLD_INFIMUM
@param enc_hdr encoded fixed-size header bits
@param hdr_c number of common record header bytes with prev
@param data_c number of common data bytes with prev
@@ -2350,6 +2350,8 @@ corrupted:
if (prev_rec == &block.frame[PAGE_OLD_INFIMUM]);
else if (UNIV_UNLIKELY(prev_rec - pextra_size < heap_bot))
goto corrupted;
+ if (UNIV_UNLIKELY(hdr_c && prev_rec - hdr_c < heap_bot))
+ goto corrupted;
const ulint pdata_size= rec_get_data_size_old(prev_rec);
if (UNIV_UNLIKELY(prev_rec + pdata_size > heap_top))
goto corrupted;
@@ -2365,7 +2367,7 @@ corrupted:
const ulint extra_size= REC_N_OLD_EXTRA_BYTES +
(is_short ? n_fields : n_fields * 2);
hdr_c+= REC_N_OLD_EXTRA_BYTES;
- if (UNIV_UNLIKELY(hdr_c > extra_size || hdr_c > pextra_size))
+ if (UNIV_UNLIKELY(hdr_c > extra_size))
goto corrupted;
if (UNIV_UNLIKELY(extra_size - hdr_c > data_len))
goto corrupted;