From 986bd5b1b91abe12e1769508591d7c8983150e5e Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Wed, 5 Aug 2026 10:23:15 +0530 Subject: [PATCH] Reject out-of-range LSNs in backup manifests parse_xlogrecptr() used sscanf() with "%X" to read each half of an LSN into a uint32. A half wider than 32 bits was therefore accepted with its high-order bits silently discarded, and trailing garbage after the LSN was ignored, because sscanf() still reported two successful conversions. Genuinely unparseable values were rejected, so the difference went unnoticed. The resulting value is used to validate the WAL ranges of a backup, both by pg_verifybackup and pg_combinebackup and, via UPLOAD_MANIFEST, by the server when taking an incremental backup. Those checks were therefore performed against a location the manifest did not actually specify. Require each half to consist of one to eight hexadecimal digits and the whole string to be consumed, matching the rules of the pg_lsn input function, and add tests. Commit 355814931141 tightened the other scalar values of a manifest in the same way, but did not touch this one. --- src/bin/pg_verifybackup/t/005_bad_manifest.pl | 12 +++++++++++ src/common/parse_manifest.c | 21 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/bin/pg_verifybackup/t/005_bad_manifest.pl b/src/bin/pg_verifybackup/t/005_bad_manifest.pl index bc9fe4a79d7..6a0989ea5c3 100644 --- a/src/bin/pg_verifybackup/t/005_bad_manifest.pl +++ b/src/bin/pg_verifybackup/t/005_bad_manifest.pl @@ -168,6 +168,18 @@ test_parse_error('could not parse start LSN', < MAXPG_LSNCOMPONENT || input[len1] != '/') return false; + + len2 = strspn(input + len1 + 1, "0123456789abcdefABCDEF"); + if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || input[len1 + 1 + len2] != '\0') + return false; + + hi = (uint32) strtoul(input, NULL, 16); + lo = (uint32) strtoul(input + len1 + 1, NULL, 16); *result = ((uint64) hi) << 32 | lo; return true; } -- 2.34.1