aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlogreader.c
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2023-09-26 09:07:26 +1300
committerThomas Munro <tmunro@postgresql.org>2023-09-26 10:54:02 +1300
commit99d334a187ae5c283aca1c31b9fad0cea140a4b2 (patch)
tree0aa0ebd1ce8bbc9358bb4dc302e12b6d90368822 /src/backend/access/transam/xlogreader.c
parent9dc3c5472ed99a1046a4d7884270a35cfad29d1d (diff)
downloadpostgresql-99d334a187ae5c283aca1c31b9fad0cea140a4b2.tar.gz
postgresql-99d334a187ae5c283aca1c31b9fad0cea140a4b2.zip
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 <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
Diffstat (limited to 'src/backend/access/transam/xlogreader.c')
-rw-r--r--src/backend/access/transam/xlogreader.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 4b48abfa053..652c9a184e4 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -651,6 +651,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;
}
@@ -1188,6 +1197,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);