Why a clean compile is not enough: backporting CVE-2026-58470 on 32-bit ARM.
A single upstream security commit can compile without warnings and pass on a 64-bit build host while silently breaking large-file HTTP transfers on a 32-bit ARM device. Here is how target-ABI verification caught a strtol width regression before release review.
- Advisory & symbol
- CVE-2026-58470 ·
parse_content_range() - Maintained package
- GNU Wget 1.21.4 on pinned Yocto LTS
- Target ABI
- 32-bit ARM Cortex-A5 (
ILP32, 64-bitoff_t) - Regression prevented
- >2 GiB HTTP
Content-Rangetruncation
1. Confirming source applicability before touching the recipe
Pinned Yocto LTS branches commonly ship wget 1.21.4 alongside existing recipe patches for reproducibility and prior advisories (CVE-2024-38428, CVE-2024-10524). Before preparing any change, we reconstruct the exact patched source tree against SDK debug sources to verify whether the reported code path is compiled and reachable.
parse_content_range() in src/http.c
Accumulated HTTP Content-Range byte offsets via unchecked signed math (10 * num + digit). Called directly by Wget's HTTP response handler during ranged transfers.
Disabled features stop at VEX
Findings in uncompiled options (excluded via PACKAGECONFIG or uncalled APIs) receive an auditable CVE_STATUS or VEX record rather than an unnecessary binary rebuild.
2. Why cherry-picking only the initial commit breaks 32-bit ARM
Upstream GNU Wget fixed the unchecked loop in commit 43d3ba9336bc using strtol() and errno == ERANGE. That single commit passes on 64-bit build servers yet breaks large-file offsets on 32-bit ARM targets:
Masks the truncation
sizeof(long)- 64-bit
sizeof(wgint)- 64-bit
strtol()max- 9.22 EiB (INT64_MAX)
- Host unit tests
- Pass (>2 GiB OK)
Fails on >2 GiB ranges
sizeof(long)- 32-bit
sizeof(wgint)- 64-bit (LFS off_t)
strtol()max- 2,147,483,647 B (~2 GiB)
- ARM unit tests
- Fail (ERANGE on >2 GiB)
Upstream subsequently published follow-up commit 01ff771caac1 switching strtol() to strtoll(), and OpenEmbedded-Core paired both commits. Our candidate series preserved both upstream-attributed backports, added boundary guards preventing caller last_byte + 1 overflow at INT64_MAX even when total length is unknown (*), and added 19 boundary unit cases:
/* Enforced 64-bit range invariant on 32-bit ARM (ILP32): * 0 <= first_byte <= last_byte < INT64_MAX * entity_length == -1 || last_byte < entity_length <= INT64_MAX * Uses strtoll() and prevents caller (last_byte + 1) overflow. */
3. Baseline-vs-candidate validation record
Both baseline and candidate builds were verified across native UndefinedBehaviorSanitizer runs and cross-compiled 32-bit ARM execution under QEMU user mode with the target SDK sysroot:
| Verification check | Outcome | Observed evidence |
|---|---|---|
| Unpatched baseline + UBSan | Reproduced | Signed integer overflow in parse_content_range at http.c:936 (exit 1) |
Commit 43d3ba9336bc alone on ARM |
ABI regression | Clean ARM compile, but failed target-ABI range unit group on >2 GiB offsets (exit 1) |
| Candidate + UBSan native suite | Passed 15/15 | All 15 unit groups and 29 Content-Range boundary cases passed; zero UBSan faults |
| Candidate on 32-bit ARM + QEMU | Passed 15/15 | All 15 unit groups passed with GnuTLS, IPv6, and 64-bit large-file parity intact |
| HTTP resume integration on ARM | Passed 4/4 | Passed Test-c.px, Test-c-partial.px, Test-c-full.px, and Test-c-shorter.px |
Recipe patch series (--fuzz=0) |
Clean apply | Zero-fuzz patch application on pinned tarball alongside existing recipe patches |
Explicit engineering boundary: component validation vs. board sign-off
QEMU user-mode execution proves target-ABI instruction and 32/64-bit type behavior in userspace, catching regressions that host-only builds miss. Full BitBake image assembly, hardware boot, peripheral interfaces, configuration migration, and cryptographic image signing remain distinct release gates under the manufacturer's control. See our responsibility matrix.
Primary technical references
-
GNU Wget commit 43d3ba9336bc: Fix integer overflow in parse_content_range (CVE-2026-58470)
Initial conversion from manual decimal accumulation to
strtol(). -
GNU Wget commit 01ff771caac1: Use strtoll instead of strtol in parse_content_range
Follow-up commit restoring 64-bit range parsing on targets with 32-bit
long. - Linux kernel documentation: Backporting and conflict resolution Guidance on prerequisite commits, follow-up regression fixes, and runtime validation beyond compilation.
- Yocto Project: Checking for Vulnerabilities Guidance on stable-branch backporting, ABI preservation, and CVE status tracking.