Skip to content

Commit becfbdd

Browse files
committed
Fix edge-case for xl_tot_len broken by bae868c.
bae868c 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 bae868c. Tested-by: Tom Lane <tgl@sss.pgh.pa.us> Tested-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGLCkTT7zYjzOxuLGahBdQ%3DMcF%3Dz5ZvrjSOnW4EDhVjT-g%40mail.gmail.com
1 parent 13aeaf0 commit becfbdd

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

src/backend/access/transam/xlogreader.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,15 @@ XLogDecodeNextRecord(XLogReaderState *state, bool nonblocking)
653653
}
654654
else
655655
{
656+
/* There may be no next page if it's too small. */
657+
if (total_len < SizeOfXLogRecord)
658+
{
659+
report_invalid_record(state,
660+
"invalid record length at %X/%X: expected at least %u, got %u",
661+
LSN_FORMAT_ARGS(RecPtr),
662+
(uint32) SizeOfXLogRecord, total_len);
663+
goto err;
664+
}
656665
/* We'll validate the header once we have the next page. */
657666
gotheader = false;
658667
}
@@ -1190,6 +1199,8 @@ ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
11901199
{
11911200
pg_crc32c crc;
11921201

1202+
Assert(record->xl_tot_len >= SizeOfXLogRecord);
1203+
11931204
/* Calculate the CRC */
11941205
INIT_CRC32C(crc);
11951206
COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);

src/test/recovery/t/039_end_of_wal.pl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,19 @@ sub advance_to_record_splitting_zone
281281
$log_size),
282282
"xl_tot_len short");
283283

284+
# xl_tot_len in final position, not big enough to span into a new page but
285+
# also not eligible for regular record header validation
286+
emit_message($node, 0);
287+
$end_lsn = advance_to_record_splitting_zone($node);
288+
$node->stop('immediate');
289+
write_wal($node, $TLI, $end_lsn, build_record_header(1));
290+
$log_size = -s $node->logfile;
291+
$node->start;
292+
ok( $node->log_contains(
293+
"invalid record length at .*: expected at least 24, got 1", $log_size
294+
),
295+
"xl_tot_len short at end-of-page");
296+
284297
# Need more pages, but xl_prev check fails first.
285298
emit_message($node, 0);
286299
$end_lsn = advance_out_of_record_splitting_zone($node);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy