Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Stack-overflow via deep JSON array nesting under ASan+-O0, below CJSON_NESTING_LIMIT

Open Beginner friendly
#1,093 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Documentation
Clarity
Mostly clear
Activity status
Active
Tech stack
c
Domain
documentation

Research direction

Start in cJSON.c by locating CJSON_NESTING_LIMIT and its existing documentation or comments. Review the reported sanitizer reproducer and build details, then document that effective safe nesting depth depends on build configuration, especially under -O0 and ASan; the work is done when the limit documentation clearly sets this expectation for fuzzing and sanitizer users.

Written by the indexing model from the issue text.

Description

Summary

Under an ASan + -O0 build (the standard configuration for fuzzing/CI sanitizer runs), a deeply nested JSON array triggers a native stack overflow before CJSON_NESTING_LIMIT (1000) is ever reached, because the limit bounds the number of recursive parser calls but not the size of each call's stack frame, and ASan instrumentation plus disabled optimization inflate that frame size substantially.

This is not an exploitable issue in a normal optimized release build (verified below) — filing this as a robustness/documentation note, not a security report.

Repro

Minimized input: a JSON value consisting of 755 consecutive [ bytes, no closing brackets, no other content.

$ ./cjson_asan_o0 < deepnest_755.json
==PID==ERROR: AddressSanitizer: stack-overflow on address 0x...
    <empty stack>
SUMMARY: AddressSanitizer: stack-overflow

(No symbolized backtrace — ASan's own crash-reporting code cannot run once the stack is this exhausted, which is typical for pure stack-overflow crashes as opposed to heap-buffer-overflow.)

Build used to reproduce: cJSON.c compiled with -O0 -fsanitize=address -g, default thread/process stack size (8 MiB on the Linux machine used here). Binary search found the exact boundary on that machine: 754 levels of [ is parsed/rejected cleanly (cJSON_ParseWithLength returns NULL), 755 crashes.

Why the existing limit does not catch it here

CJSON_NESTING_LIMIT counts recursive calls, not stack bytes consumed. Under -O0, every local gets its own stack slot (no register allocation), and ASan adds redzone padding around each stack allocation. The combined per-call frame size under this build is large enough that the process stack is exhausted well before the 1000-call counter would reject the input.

Confirms it is release-build-safe

The same inputs (780, 1000, 1500, 5000, 50000 levels of [) were tested against an identical harness built -O2, no sanitizers: all are rejected cleanly, exit code 0, no crash, in every case. The nesting limit does its job as documented in a normal build; the gap only appears under sanitizer instrumentation.

Suggested fix

Options, roughly in order of effort:

  • Note in the CJSON_NESTING_LIMIT documentation that the effective safe depth is build-configuration-dependent (much lower under -O0/ASan/MSan than in an optimized release build), so people fuzzing or testing cJSON with sanitizers know a stack-overflow at a shallower depth than 1000 is expected, not a new bug.
  • Optionally lower the default limit, or make it configurable relative to a measured/available stack size, if protecting sanitizer/debug builds against this specific crash is a goal.

Happy to share the exact harness and inputs if useful. Reported by an independent fuzzing exercise, no CVE requested given the release-build behavior is correct.

Dominant language
C
Stars
13k
Forks
3.5k
PR merge metrics
No merged PRs in 30d

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from DaveGamble/cJSON

All issues in DaveGamble/cJSON

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.