CVE Patch Review

GHSA-5R97-79VW-QVM4: Root-Cause Fix for 32-bit DirectXTK12 SpriteFont ReadArray Overflow

GHSA-5R97-79VW-QVM4 · Updated 2026-05-18 Root-cause

Summary

The patch addresses the core arithmetic flaw in DirectXTK12's BinaryReader::ReadArray by widening the multiplication used to compute the byte span and rejecting values that exceed 32-bit addressable limits. This directly blocks the integer overflow path described in the advisory for 32-bit builds, where crafted .spritefont input could shrink the computed allocation/read size and enable memory corruption or out-of-bounds reads.

Analysis

Vulnerability

GHSA-5R97-79VW-QVM4 describes an integer overflow in DirectXTK12's SpriteFont parsing path on 32-bit builds. The vulnerable operation in BinaryReader::ReadArray computed the end pointer using sizeof(T) * elementCount in a context where the multiplication could wrap before bounds validation completed. For attacker-controlled .spritefont input, this can cause the parser to accept a truncated byte count, bypass internal range checks, and subsequently trigger memory corruption or out-of-bounds reads. The code reference in the fixing commit shows the original arithmetic as a direct pointer advance based on the unchecked product of element size and element count, which is the root of the overflow condition on 32-bit targets: commit c037a024a7ed3b2162fa2bbbe209b84ba2904494.

uint8_t const* newPos = mPos + sizeof(T) * elementCount;

Because the parser consumes untrusted serialized font data, arithmetic overflow in the byte-count calculation is security-relevant rather than merely a correctness bug. The advisory and external report both characterize the impact as memory corruption and out-of-bounds reads in 32-bit builds: GitHub Security Advisory, CVE Reports entry.

Patch

The patch changes the byte-count computation from an unchecked native-width multiplication to an explicit 64-bit calculation, followed by a guard that rejects values larger than UINT32_MAX. Only after that check does the code advance the pointer using the validated byte count. This is visible in the upstream fix: microsoft/directxtk12 commit c037a024a7ed3b2162fa2bbbe209b84ba2904494.

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

Technically, this patch does two important things. First, it prevents intermediate multiplication overflow by promoting both operands to 64-bit before multiplication. Second, it enforces an upper bound consistent with the vulnerable deployment context identified by the advisory, namely 32-bit builds. The resulting size_t conversion is therefore performed only after the value has been proven representable within the intended range.

Review

Pros

  • The fix directly targets the root arithmetic bug in ReadArray rather than attempting to harden only a specific SpriteFont call site.
  • Using 64-bit multiplication eliminates wraparound in the intermediate product, which is the key precondition for the bounds-check bypass.
  • The explicit byteCount > UINT32_MAX rejection is aligned with the advisory's 32-bit impact statement and prevents unsafe pointer advancement on affected builds.
  • Throwing std::overflow_error provides a deterministic failure mode for malformed or malicious inputs instead of allowing silent truncation.
  • Because BinaryReader is a shared primitive, fixing it centrally likely protects all array reads that rely on this helper, not just the known SpriteFont parsing path.

Cons

  • The visible patch snippet only shows the multiplication fix; it does not by itself demonstrate whether all downstream allocation and copy sites also use the validated byteCount consistently.
  • The guard is framed around UINT32_MAX, which is appropriate for the disclosed 32-bit issue, but the snippet does not show whether there are additional invariants tying the check to remaining buffer length or object-count sanity.
  • The commit also includes unrelated repository metadata changes, so the security-relevant delta is small and should be reviewed carefully to ensure no other parser arithmetic paths remain unchecked.

Verdict

Root-cause.

This patch fixes the underlying integer overflow mechanism by widening the multiplication and rejecting oversized results before pointer arithmetic occurs. Based on the provided diff and the advisory description, that is the correct remediation for the disclosed vulnerability in BinaryReader::ReadArray. The change is narrowly scoped, technically sound, and source-consistent with the reported exploit condition on 32-bit builds. While a full audit of adjacent parser logic would still be prudent, the patch itself addresses the core flaw rather than masking symptoms.

Sources