GHSA-C55G-RP4X-FX84: Root-cause fix for SpriteFont parser integer overflow
Summary
The patch addresses the core arithmetic flaw in DirectX Tool Kit's SpriteFont parsing path by widening the multiplication used in BinaryReader::ReadArray and rejecting byte counts that exceed 32-bit bounds. This directly prevents crafted element counts from wrapping the computed buffer advance on 32-bit targets, which was the condition enabling out-of-bounds access.
Analysis
Vulnerability
GHSA-C55G-RP4X-FX84 describes a 32-bit integer overflow in the DirectX Tool Kit SpriteFont parser. The vulnerable operation is in BinaryReader::ReadArray, where the parser computed the end pointer using a multiplication performed in a width that could wrap on 32-bit architectures. A crafted .spritefont file could supply an attacker-controlled elementCount such that sizeof(T) * elementCount overflowed, causing size validation to be bypassed and enabling heap buffer overflow or out-of-bounds read conditions during parsing.
The relevant vulnerable code from the referenced commit shows the unchecked pointer advance:
uint8_t const* newPos = mPos + sizeof(T) * elementCount;Because the byte-count calculation was not performed in a sufficiently wide integer type before pointer arithmetic, the parser could derive an incorrect newPos and accept malformed input as if it were in bounds. This matches the advisory's description of integer overflow leading to out-of-bounds access on 32-bit systems.
Sources: commit ef1bd5d7f492c39dd0cd87493ba8ea38725c9791, GitHub Security Advisory, CVE Reports summary.
Patch
The patch changes the byte-count computation to use 64-bit arithmetic and explicitly rejects values that exceed UINT32_MAX before performing pointer advancement. The patched snippet in Src/BinaryReader.h is:
uint64_t byteCount = uint64_t(sizeof(T)) * uint64_t(elementCount);
if (byteCount > UINT32_MAX)
throw std::overflow_error("ReadArray");
uint8_t const* newPos = mPos + static_cast<size_t>(byteCount);This is a targeted arithmetic hardening change. It removes the overflow primitive by ensuring the multiplication cannot wrap in 32-bit intermediate arithmetic, then fails closed when the requested array size exceeds the supported range. Only after validation does the code convert to size_t for pointer arithmetic.
Review
Pros
- The patch directly addresses the root arithmetic bug identified in the advisory rather than relying on downstream bounds checks.
- Using
uint64_tfor the multiplication prevents wraparound in the intermediate byte-count calculation. - The explicit
byteCount > UINT32_MAXguard makes the failure mode deterministic and converts malformed input into an exception instead of memory corruption. - The change is minimal and localized to the generic array-reading helper, which is likely to protect all parser call sites that depend on
ReadArray.
Cons
- The visible patch snippet only shows overflow prevention for the byte-count computation; it does not by itself demonstrate any broader parser hardening such as format-level sanity limits.
- The guard is framed around a 32-bit maximum. That aligns with the reported issue, but the snippet alone does not show whether all subsequent comparisons and remaining-size calculations are consistently widened as well.
- The commit also contains unrelated documentation changes in
.github/copilot-instructions.md, which add noise around the security-relevant delta.
Verdict
Root-cause.
The patch fixes the actual vulnerability mechanism documented in the advisory: integer overflow in BinaryReader::ReadArray during byte-count calculation. By widening the multiplication and rejecting oversized results before pointer advancement, it closes the bypass that allowed malformed .spritefont files to evade size validation on 32-bit architectures. Based on the provided diff, this is an appropriate and technically sound remediation for the reported issue.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Integer Overflow II.cpp
Best fit for this DirectX Tool Kit issue because it is a hands-on C++ lab focused on integer overflow conditions that can cascade into unsafe allocation sizing and memory access problems. That closely matches the advisory’s parser bug pattern: arithmetic overflow during size calculation leading to out-of-bounds behavior.
- Integer Overflow.c
Useful supporting lab for understanding low-level defensive coding around overflow-safe size validation, bounds checks, and allocation logic in native code. Even though it is in C rather than C++, the memory-safety lessons transfer directly to file parser hardening on 32-bit targets.
- Integer Overflow II.c
A strong defensive follow-up lab for practicing more advanced overflow scenarios in native code. It is relevant for reviewing parser patch quality, especially where multiplication, element counts, and buffer sizing must be validated before reads or heap operations occur.