| 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 |
| 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 |