From ecf902895d9f85d989532058492bc68326a9439f Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 30 Jul 2026 08:23:25 +0000 Subject: [PATCH v1 2/5] Fix integer parsing in manifest parser for portability strtoul() can set two different values for errno: EINVAL and ERANGE. Quoting the man page for EINVAL: > The value of base is not supported or no conversion could be performed > (the last feature is not portable across all platforms). Emphasis on the portion in parentheses. Take the following example: strtoul("", &endptr, 10); On glibc, the output value is 0, errno *is not* set, and endptr points to the empty string. On Apple libc, the output value is 0, errno *is* set to EINVAL, and endptr points to the empty string. In this case, when we try to parse an empty string, glibc treats that as a 0, and Apple libc correctly treats it as an error. Signed-off-by: Tristan Partin --- src/bin/pg_verifybackup/t/005_bad_manifest.pl | 16 ++++++++++++++++ src/common/parse_manifest.c | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/bin/pg_verifybackup/t/005_bad_manifest.pl b/src/bin/pg_verifybackup/t/005_bad_manifest.pl index 0413fea02c3..bc9fe4a79d7 100644 --- a/src/bin/pg_verifybackup/t/005_bad_manifest.pl +++ b/src/bin/pg_verifybackup/t/005_bad_manifest.pl @@ -39,6 +39,10 @@ {"PostgreSQL-Backup-Manifest-Version": 9876599} EOM +test_parse_error('system identifier in manifest not an integer', <manifest_system_identifier, &ep, 10); - if (*ep) + if (ep == parse->manifest_system_identifier || *ep) json_manifest_parse_failure(parse->context, "system identifier in manifest not an integer"); @@ -688,7 +688,7 @@ json_manifest_finalize_file(JsonManifestParseState *parse) /* Parse size. */ size = strtou64(parse->size, &ep, 10); - if (*ep) + if (ep == parse->size || *ep) json_manifest_parse_failure(parse->context, "file size is not an integer"); @@ -766,7 +766,7 @@ json_manifest_finalize_wal_range(JsonManifestParseState *parse) /* Parse timeline. */ tli = strtoul(parse->timeline, &ep, 10); - if (*ep) + if (ep == parse->timeline || *ep) json_manifest_parse_failure(parse->context, "timeline is not an integer"); if (!parse_xlogrecptr(&start_lsn, parse->start_lsn)) -- Tristan Partin https://tristan.partin.io