mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-03 05:06:50 +02:00
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, likebae868ca
. 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
This commit is contained in:
parent
d1c76fdec3
commit
45d1fe8b53
@ -380,6 +380,15 @@ restart:
|
|||||||
}
|
}
|
||||||
else
|
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. */
|
/* We'll validate the header once we have the next page. */
|
||||||
gotheader = false;
|
gotheader = false;
|
||||||
}
|
}
|
||||||
@ -795,6 +804,8 @@ ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
|
|||||||
{
|
{
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
|
|
||||||
|
Assert(record->xl_tot_len >= SizeOfXLogRecord);
|
||||||
|
|
||||||
/* Calculate the CRC */
|
/* Calculate the CRC */
|
||||||
INIT_CRC32C(crc);
|
INIT_CRC32C(crc);
|
||||||
COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
|
COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
|
||||||
|
@ -287,6 +287,19 @@ ok( $node->log_contains(
|
|||||||
$log_size),
|
$log_size),
|
||||||
"xl_tot_len short");
|
"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.
|
# Need more pages, but xl_prev check fails first.
|
||||||
emit_message($node, 0);
|
emit_message($node, 0);
|
||||||
$end_lsn = advance_out_of_record_splitting_zone($node);
|
$end_lsn = advance_out_of_record_splitting_zone($node);
|
||||||
|
Loading…
Reference in New Issue
Block a user