CVE-2026-16554 Overview
CVE-2026-16554 is an integer overflow vulnerability in the print_string_ptr() function of the cJSON library (cJSON.c) on 32-bit platforms. The escape_characters counter, a 32-bit size_t, wraps around when the function processes strings containing approximately 858,993,460 or more control characters. This wrap causes the output buffer to be allocated based on an underestimated length. When cJSON_PrintBuffered() is used with a pre-allocated buffer, the subsequent write loop overflows the heap allocation. The flaw is confirmed in cJSON version 1.7.19 and may affect earlier releases. The weakness is classified under CWE-190 (Integer Overflow or Wraparound).
Critical Impact
An attacker who supplies a crafted JSON string to an application using cJSON on a 32-bit platform can trigger a heap buffer overflow, potentially leading to remote code execution, information disclosure, or denial of service.
Affected Products
- cJSON library version 1.7.19 (confirmed)
- Potentially earlier cJSON releases on 32-bit platforms (unconfirmed)
- Applications embedding cJSON that call cJSON_PrintBuffered() with attacker-influenced input
Discovery Timeline
- 2026-07-27 - CVE-2026-16554 published to NVD
- 2026-07-30 - Coordinated disclosure via the OpenWall oss-security mailing list and CERT Polska advisory
- 2026-07-30 - Last updated in NVD database
Technical Details for CVE-2026-16554
Vulnerability Analysis
The defect resides in the print_string_ptr() routine used by cJSON to serialize string values into JSON output. During serialization, cJSON scans the input string and increments an escape_characters counter for each control character requiring escaping. The counter is declared as size_t, which is 32 bits wide on 32-bit platforms. Each control character contributes a fixed number of extra bytes to the required output size. When the input contains roughly 858,993,460 or more control characters, the multiplication used to size the output buffer overflows the 32-bit range and wraps to a small value.
The allocator then returns a buffer smaller than the data cJSON is about to write. The subsequent write loop copies escape sequences past the end of the heap allocation, corrupting adjacent heap metadata and memory. Because the primitive is a linear heap overflow with attacker-controlled contents, it can be leveraged for arbitrary code execution, memory disclosure, or process termination depending on the target allocator and surrounding heap layout.
Root Cause
The root cause is arithmetic on a 32-bit size_t without a saturating check or 64-bit intermediate. cJSON trusts the computed length when calling the underlying allocator or when writing into a buffer supplied through cJSON_PrintBuffered(). There is no bounds validation that rejects input strings large enough to overflow the length calculation.
Attack Vector
Exploitation requires supplying a crafted JSON string that contains an unusually large number of control characters to any application that serializes attacker-controlled data via cJSON_PrintBuffered() on a 32-bit build. The CVSS 4.0 vector lists an attack vector of Local, reflecting scenarios where the attacker delivers the payload through a locally accessible interface, file, or IPC channel that ultimately reaches the vulnerable serialization path.
No verified public exploit code is currently available. Refer to the CERT Polska advisory and the OpenWall oss-security thread for additional technical detail.
Detection Methods for CVE-2026-16554
Indicators of Compromise
- Process crashes, heap corruption reports, or allocator aborts in applications that link against cJSON on 32-bit targets
- JSON inputs whose string fields contain hundreds of millions of control characters (bytes in the ranges 0x00–0x1F and 0x7F)
- Sudden growth in memory allocation followed by segmentation faults in services parsing untrusted JSON
Detection Strategies
- Perform a software bill of materials (SBOM) sweep to identify binaries statically or dynamically linking cJSON 1.7.19 or earlier
- Instrument 32-bit builds with AddressSanitizer or heap-hardening allocators to catch the overflow at write time
- Add input filters or logging that flag JSON payloads with abnormally high control-character density before they reach cJSON
Monitoring Recommendations
- Monitor for repeated crashes and core dumps from services that parse external JSON on 32-bit systems
- Alert on ingress traffic containing JSON documents exceeding realistic size or control-character thresholds
- Correlate application crashes with upstream JSON sources to detect targeted probing
How to Mitigate CVE-2026-16554
Immediate Actions Required
- Inventory all applications and firmware images that embed cJSON, prioritizing 32-bit builds and embedded devices
- Restrict untrusted input reaching cJSON_PrintBuffered() by enforcing maximum JSON size and control-character limits at the network or application boundary
- Rebuild affected 32-bit components on a 64-bit toolchain where feasible, since the overflow does not trigger with a 64-bit size_t
Patch Information
At the time of NVD publication, no fixed release from the upstream cJSON GitHub repository is referenced in the advisory. Because project maintainer contact attempts were reported as unsuccessful, downstream vendors should evaluate applying a local patch that validates input length and uses 64-bit arithmetic for buffer sizing in print_string_ptr(). Track the CERT Polska advisory for updates.
Workarounds
- Reject JSON inputs larger than the maximum size expected by the application before invoking cJSON
- Prefer cJSON_Print() with dynamic allocation over cJSON_PrintBuffered() where the pre-allocated buffer path is not required, and validate output length after serialization
- Migrate to 64-bit builds so that the size_t counter cannot wrap at the documented control-character threshold
- Sandbox JSON parsing components with reduced privileges and resource limits to contain heap corruption impact
# Configuration example: reject oversized or control-character-heavy JSON at ingress
# (nginx example using the njs module or a WAF rule)
client_max_body_size 1m;
# Drop requests whose bodies contain excessive control characters before proxying to the app
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

