Re: Fix detection of truncated zstd-compressed backups

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Cc: Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>
Subject: Re: Fix detection of truncated zstd-compressed backups
Date: 2026-08-10 08:11:38
Message-ID: 2E9971CA-062B-4EC0-8858-9979C73A3888@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Aug 10, 2026, at 14:45, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> wrote:
>
>
> See attached 0002 for the fix of gzip streamer. I will check the lz4 streamer next.
>
> Best regards,
> --
> Chao Li (Evan)
> HighGo Software Co., Ltd.
> https://www.highgo.com/
>
>
>
>
> <v2-0001-Fix-detection-of-truncated-zstd-compressed-backup.patch><v2-0002-Fix-detection-of-truncated-gzip-compressed-backup.patch>

Confirmed that lz4 also has the same problem. See the similar repro script:
```
workdir=$(mktemp -d /tmp/lz4-trunc.XXXXXX)
mkdir "$workdir/truncated"
dd if=/dev/zero of="$workdir/base.tar" bs=1024 count=2
lz4 -q -f "$workdir/base.tar" "$workdir/base.tar.lz4"
size=$(stat -f %z "$workdir/base.tar.lz4")
dd if="$workdir/base.tar.lz4" of="$workdir/truncated/base.tar.lz4" bs=1 count=$((size - 1))

manifest_prefix=$'{"PostgreSQL-Backup-Manifest-Version": 1,\n "Files": [],\n "WAL-Ranges": [],\n'
printf '%s' "$manifest_prefix" > "$workdir/manifest-prefix"
manifest_checksum=$(shasum -a 256 "$workdir/manifest-prefix" | awk '{print $1}')
printf '%s"Manifest-Checksum": "%s"}\n' "$manifest_prefix" "$manifest_checksum" > "$workdir/truncated/backup_manifest"

lz4 -t "$workdir/truncated/base.tar.lz4"
pg_verifybackup -F t -s "$workdir/truncated"
```

lz4 fails to decompress the truncated tar file, but pg_verifybackup succeeds.

The doc for LZ4F_decompress() [4] says that a return value >0 is a hint about how many source bytes are needed next, 0 means that the frame is complete, and an error return is identified with LZ4F_isError().

So, as in 0001, we can record the return value of LZ4F_decompress() in astreamer_lz4_frame and check it in astreamer_lz4_decompressor_finalize(). Unlike zstd, we don't need to call LZ4F_decompress() again because it has no documented case where a positive return value with a full output buffer requires an empty-input call to flush internally buffered output.

[4] https://github.com/lz4/lz4/blob/dev/lib/lz4frame.h#L470-L500

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

Attachment Content-Type Size
v3-0001-Fix-detection-of-truncated-zstd-compressed-backup.patch application/octet-stream 3.2 KB
v3-0002-Fix-detection-of-truncated-gzip-compressed-backup.patch application/octet-stream 1.8 KB
v3-0003-Fix-detection-of-truncated-LZ4-compressed-backups.patch application/octet-stream 2.1 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Daniel Gustafsson 2026-08-10 08:13:16 Re: pg_control_checkpoint(): add "data_checksum_version" (Pg19)?
Previous Message Fujii Masao 2026-08-10 08:10:03 Re: Avoid calling SetMatViewPopulatedState if possible