This is an automated email from the ASF dual-hosted git repository.

tuhaihe pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit df1ce4d4a224df037b8cbc37384f5b5f9a2dab4a
Author: Thomas Munro <[email protected]>
AuthorDate: Tue Sep 26 09:07:26 2023 +1300

    Fix edge-case for xl_tot_len broken by bae868ca.
    
    bae868ca removed a check that was still needed.  If you had an
    xl_tot_len at the end of a page that was too small for a record header,
    but not big enough to span onto the next page, we'd immediately perform
    the CRC check using a bogus large length.  Because of arbitrary coding
    differences between the CRC implementations on different platforms,
    nothing very bad happened on common modern systems.  On systems using
    the _sb8.c fallback we could segfault.
    
    Restore that check, add a new assertion and supply a test for that case.
    Back-patch to 12, like bae868ca.
    
    Tested-by: Tom Lane <[email protected]>
    Tested-by: Alexander Lakhin <[email protected]>
    Discussion: 
https://postgr.es/m/CA%2BhUKGLCkTT7zYjzOxuLGahBdQ%3DMcF%3Dz5ZvrjSOnW4EDhVjT-g%40mail.gmail.com
---
 src/backend/access/transam/xlogreader.c | 11 +++++++++++
 src/test/recovery/t/039_end_of_wal.pl   | 13 +++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/src/backend/access/transam/xlogreader.c 
b/src/backend/access/transam/xlogreader.c
index 67e6b9cf717..af5e8508bf1 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -388,6 +388,15 @@ restart:
        }
        else
        {
+               /* There may be no next page if it's too small. */
+               if (total_len < SizeOfXLogRecord)
+               {
+                       report_invalid_record(state,
+                                                                 "invalid 
record length at %X/%X: wanted %u, got %u",
+                                                                 
LSN_FORMAT_ARGS(RecPtr),
+                                                                 (uint32) 
SizeOfXLogRecord, total_len);
+                       goto err;
+               }
                /* We'll validate the header once we have the next page. */
                gotheader = false;
        }
@@ -800,6 +809,8 @@ ValidXLogRecord(XLogReaderState *state, XLogRecord *record, 
XLogRecPtr recptr)
 {
        pg_crc32c       crc;
 
+       Assert(record->xl_tot_len >= SizeOfXLogRecord);
+
        /* Calculate the CRC */
        INIT_CRC32C(crc);
        COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, 
record->xl_tot_len - SizeOfXLogRecord);
diff --git a/src/test/recovery/t/039_end_of_wal.pl 
b/src/test/recovery/t/039_end_of_wal.pl
index 1eb65c07654..1d1d883be6a 100644
--- a/src/test/recovery/t/039_end_of_wal.pl
+++ b/src/test/recovery/t/039_end_of_wal.pl
@@ -287,6 +287,19 @@ ok( $node->log_contains(
                $log_size),
        "xl_tot_len short");
 
+# xl_tot_len in final position, not big enough to span into a new page but
+# also not eligible for regular record header validation
+emit_message($node, 0);
+$end_lsn = advance_to_record_splitting_zone($node);
+$node->stop('immediate');
+write_wal($node, $TLI, $end_lsn, build_record_header(1));
+$log_size = -s $node->logfile;
+$node->start;
+ok( $node->log_contains(
+               "invalid record length at .*: wanted 24, got 1", $log_size
+       ),
+       "xl_tot_len short at end-of-page");
+
 # Need more pages, but xl_prev check fails first.
 emit_message($node, 0);
 $end_lsn = advance_out_of_record_splitting_zone($node);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to