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.
This commit is contained in:
Marko Mäkelä 2021-03-09 18:03:31 +02:00
parent a6cd4612a9
commit 549a70d7f0
2 changed files with 7 additions and 5 deletions

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 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. 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 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 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 enc_hdr encoded fixed-size header bits
@param hdr_c number of common record header bytes with prev @param hdr_c number of common record header bytes with prev
@param data_c number of common data bytes with prev @param data_c number of common data bytes with prev

View File

@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. 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 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 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. 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 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 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 enc_hdr encoded fixed-size header bits
@param hdr_c number of common record header bytes with prev @param hdr_c number of common record header bytes with prev
@param data_c number of common data 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]); if (prev_rec == &block.frame[PAGE_OLD_INFIMUM]);
else if (UNIV_UNLIKELY(prev_rec - pextra_size < heap_bot)) else if (UNIV_UNLIKELY(prev_rec - pextra_size < heap_bot))
goto corrupted; 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); const ulint pdata_size= rec_get_data_size_old(prev_rec);
if (UNIV_UNLIKELY(prev_rec + pdata_size > heap_top)) if (UNIV_UNLIKELY(prev_rec + pdata_size > heap_top))
goto corrupted; goto corrupted;
@ -2365,7 +2367,7 @@ corrupted:
const ulint extra_size= REC_N_OLD_EXTRA_BYTES + const ulint extra_size= REC_N_OLD_EXTRA_BYTES +
(is_short ? n_fields : n_fields * 2); (is_short ? n_fields : n_fields * 2);
hdr_c+= REC_N_OLD_EXTRA_BYTES; 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; goto corrupted;
if (UNIV_UNLIKELY(extra_size - hdr_c > data_len)) if (UNIV_UNLIKELY(extra_size - hdr_c > data_len))
goto corrupted; goto corrupted;