diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-03-09 18:03:31 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-03-11 14:21:28 +0200 |
commit | 549a70d7f01ce723b1b06fd7be569211a8270bcd (patch) | |
tree | 6de21246514db36bed74fe4adf3f31d892ab5c1b | |
parent | a6cd4612a9e802a365f8fc37e0da6a24e2541133 (diff) | |
download | mariadb-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.h | 4 | ||||
-rw-r--r-- | storage/innobase/page/page0cur.cc | 8 |
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; |