Hi,

pg_waldump segfaults on a 58-byte record with a valid CRC. The attached
script puts it in place of the first record of a fresh cluster's WAL.
Reproduced on 15 to master (e75fcc9867f).

DecodeXLogRecord sums the block data, image and main data lengths into
datatotal and checks it against the bytes left after the headers.
datatotal is a uint32 and main_data_len alone can be UINT32_MAX, so the
sum wraps to the remaining length and passes the check. The memcpy of
the main data then reads ~4 GB past the record.

18992dc9d98 capped xl_tot_len, but the lengths inside the record are
still summed in a uint32.

The patch makes datatotal a uint64, and the record is rejected with
"record with invalid length".

There is no test, because the record needs a valid CRC, which
039_end_of_wal.pl can't build. I can add one if wanted.

Best Regards,
Iliia
#!/bin/sh
# usage: make-segment.sh <bindir> <workdir>
# initdb a fresh cluster and overwrite its first WAL record with record.bin
# (58 bytes, CRC already valid, xl_prev = 0), then run pg_waldump on it.
set -e
B=$1; W=$2; HERE=$(cd "$(dirname "$0")" && pwd)
"$B/initdb" -D "$W/data" >/dev/null
mkdir -p "$W/wal"
cp "$W/data/pg_wal/000000010000000000000001" "$W/wal/"
dd if="$HERE/record.bin" of="$W/wal/000000010000000000000001" bs=1 seek=40 conv=notrunc 2>/dev/null
cd "$W/wal" && "$B/pg_waldump" 000000010000000000000001

Attachment: 0001-Prevent-overflow-of-datatotal-in-DecodeXLogRecord.patch
Description: Binary data

Attachment: record.bin
Description: application/macbinary

Reply via email to