CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-5R97-79VW-QVM4
5.3

GHSA-5r97-79vw-qvm4: Integer Overflow and Memory Corruption in Microsoft DirectXTK12 SpriteFont Parser

Amit Schendel
Amit Schendel
Senior Security Researcher

May 18, 2026·6 min read·3 visits

No Known Exploit

Executive Summary (TL;DR)

32-bit DirectXTK12 builds suffer from an integer overflow in BinaryReader::ReadArray. Malicious .spritefont files can bypass internal bounds checks, causing memory corruption and out-of-bounds reads.

An integer overflow vulnerability exists in the 32-bit builds of the Microsoft DirectX Tool Kit for DirectX 12 (DirectXTK12). By supplying a crafted .spritefont file, an attacker can trigger out-of-bounds memory operations, potentially leading to memory corruption and remote code execution.

Vulnerability Overview

The Microsoft DirectX Tool Kit for DirectX 12 (DirectXTK12) provides helper classes for writing Direct3D 12 C++ code. One of its components is the SpriteFont class, which parses .spritefont binary files to render text. This parsing mechanism relies on a binary reader utility that processes untrusted data structures defined within the font file.

A vulnerability exists in how the binary reader calculates buffer offsets on 32-bit architectures (x86 and ARM). The flaw is classified as CWE-190 (Integer Overflow or Wraparound). 64-bit builds (x64 and ARM64) natively utilize 64-bit integer sizing for memory operations and are immune to this specific defect.

Applications parsing attacker-controlled .spritefont files on affected architectures will perform incorrect memory offset calculations. This failure desynchronizes the parser's internal state from the actual file structure, causing subsequent operations to read uninitialized memory or out-of-bounds heap data.

Root Cause Analysis

The defect is located in the BinaryReader::ReadArray template method within Src/BinaryReader.h. This function is responsible for validating that a requested array of elements fits within the remaining bounds of the binary stream before advancing the internal position pointer (mPos).

The vulnerability stems from the exact mathematical operation used to calculate the required byte size: mPos + sizeof(T) * elementCount. On 32-bit architectures, the size_t type is a 32-bit unsigned integer. The multiplication sizeof(T) * elementCount occurs entirely within 32-bit integer space.

An attacker controls the elementCount variable via the binary input stream. If sizeof(T) is 16 bytes and the attacker supplies an elementCount of 0x10000001, the multiplication yields 0x100000010. Because this result exceeds the 32-bit maximum, it truncates down to 0x10 (16 bytes).

The binary reader code included a sanity check to verify that newPos (the calculated endpoint) did not wrap past the beginning of the address space (if (newPos < mPos)). This check fails to detect the vulnerability because the addition of the truncated 16-byte value to mPos is entirely valid in pointer arithmetic, bypassing the bounds enforcement while leaving the stream pointer vastly out of synchronization with the expected data size.

Code Analysis

The vulnerable implementation calculates the new position pointer using unchecked 32-bit arithmetic. The resulting pointer is then checked for a standard wrap-around, but the size calculation itself has already silently overflowed.

// Vulnerable Code snippet in Src/BinaryReader.h
uint8_t const* newPos = mPos + sizeof(T) * elementCount;
if (newPos < mPos)
    throw std::overflow_error("ReadArray");

The patch implemented in commit c037a024a7ed3b2162fa2bbbe209b84ba2904494 mitigates the flaw by explicitly forcing the multiplication into 64-bit space, regardless of the underlying architecture. It then performs an explicit upper-bound check against UINT32_MAX.

// Patched Code snippet in Src/BinaryReader.h
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);

By casting both operands to uint64_t, the arithmetic guarantees that no truncation occurs during the multiplication phase. The subsequent check against UINT32_MAX ensures that the resulting byteCount safely fits within a 32-bit size_t variable. This patch thoroughly resolves the integer overflow path for 32-bit builds.

Exploitation

Exploitation requires the target application to process a maliciously crafted .spritefont file. The attacker must deliver this file through an established application input vector, such as a user-generated content upload, an automatic asset download from a remote server, or an imported project file.

The attacker crafts the file structure to supply an anomalous elementCount at the exact offset where BinaryReader::ReadArray is invoked. When the parser hits this value, the integer overflow occurs, and the function incorrectly reports that the large data structure has been successfully validated and "read" from the buffer.

Because the internal position pointer (mPos) only advances by the truncated amount (e.g., 16 bytes) rather than the millions of bytes expected, subsequent read operations process the wrong sections of the file. The parser reads structural headers as raw data and raw data as structural headers.

If the application utilizes the attacker-controlled elementCount to allocate memory and copy data, the system will read beyond the bounds of the validated buffer. This results in processing arbitrary garbage memory or uninitialized heap data as valid font metrics, crashing the application or laying the groundwork for execution flow hijacking.

Impact Assessment

The primary manifestation of this vulnerability is an application crash. Processing the malformed file reliably triggers out-of-bounds read operations, which cause access violations when the parser reaches unmapped memory pages. This guarantees a localized Denial of Service (DoS) for the parsing thread or application.

The official advisory indicates a risk of Remote Code Execution (RCE). Achieving code execution requires the out-of-bounds read to corrupt internal application state or memory structures in a predictable manner. The attacker must precisely control the desynchronization to manipulate subsequent heap allocations and memory copies.

The vulnerability carries a CVSS 4.0 base score of 5.3 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N). The medium severity reflects the low immediate impact on system confidentiality and integrity, combined with the difficulty of weaponizing out-of-bounds reads into reliable code execution without additional information leaks.

Risk exposure is strictly limited to applications compiled for 32-bit architectures (x86 or ARM32). Furthermore, applications that exclusively load bundled, static .spritefont files are not practically exploitable, as there is no mechanism for an attacker to introduce the malicious payload.

Remediation

Developers utilizing DirectXTK12 must update the NuGet packages directxtk12_desktop_win10 and directxtk12_uwp to version 2026.5.8.1 or later. Recompiling the application with the updated library ensures the robust 64-bit arithmetic checks are compiled into the binary reader routines.

Organizations can permanently neutralize this class of vulnerability by migrating applications to 64-bit architectures (x64 or ARM64). On 64-bit systems, the native size_t variable is wide enough to handle the array multiplication without overflowing, rendering the underlying mathematical defect inert.

If patching or architecture migration is currently unfeasible, developers must implement strict supply chain controls on asset files. Applications must only load .spritefont binaries from local, trusted directories and strictly prohibit loading font files supplied by end users or untrusted remote endpoints.

Security engineers should conduct an inventory scan of source code repositories and CI/CD pipelines to identify any legacy 32-bit builds relying on outdated versions of the DirectX Tool Kit. These builds should be flagged for immediate update or retirement.

Official Patches

MicrosoftFix commit implementing 64-bit arithmetic for array reading.
MicrosoftOfficial May 2026 release containing the security patch.

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N

Affected Systems

Microsoft DirectX Tool Kit for DirectX 12 (DirectXTK12)directxtk12_desktop_win10 NuGet Packagedirectxtk12_uwp NuGet Package32-bit (x86/ARM) Windows Environments

Affected Versions Detail

Product
Affected Versions
Fixed Version
directxtk12_desktop_win10
Microsoft
< 2026.5.8.12026.5.8.1
directxtk12_uwp
Microsoft
< 2026.5.8.12026.5.8.1
AttributeDetail
CWE IDCWE-190: Integer Overflow or Wraparound
Attack VectorNetwork / Local File (AV:N)
CVSS 4.0 Score5.3 (Medium)
ImpactMemory Corruption, Out-of-bounds Read, Potential RCE
Exploit StatusNo known public exploits (None)
Architectural ScopeAffects 32-bit only (x86/ARM)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1203Exploitation for Client Execution
Execution
CWE-190
Integer Overflow or Wraparound

The software performs a calculation that can produce an integer overflow or wraparound, when the logic assumes that the resulting value will always be larger than the original value. This can introduce weaknesses when the calculation is used for resource management or execution control.

Vulnerability Timeline

Fix commit pushed to repository.
2026-04-20
Official v2026.5.8.1 release tagged.
2026-05-07
Security advisory published on GitHub.
2026-05-18

References & Sources

  • [1]GitHub Security Advisory: GHSA-5r97-79vw-qvm4
  • [2]DirectXTK12 Fix Commit
  • [3]DirectXTK12 May 2026 Release

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.