From bde2f1847f51577b8e5a13a3ccc2cda9626fb214 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Tue, 26 Sep 2023 09:07:26 +1300 Subject: 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 Tested-by: Alexander Lakhin Discussion: https://postgr.es/m/CA%2BhUKGLCkTT7zYjzOxuLGahBdQ%3DMcF%3Dz5ZvrjSOnW4EDhVjT-g%40mail.gmail.com --- src/backend/access/transam/xlogreader.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/backend/access/transam/xlogreader.c') diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index 0016a3b3eff..85cec564226 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -330,6 +330,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", + (uint32) (RecPtr >> 32), (uint32) RecPtr, + (uint32) SizeOfXLogRecord, total_len); + goto err; + } /* We'll validate the header once we have the next page. */ gotheader = false; } @@ -745,6 +754,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); -- cgit v1.2.3