Skip to content

fix(json): parse deep nesting with a heap-backed stack - #7832

Merged
proggeramlug merged 2 commits into
mainfrom
fix/7817-iterative-json-parser
Aug 11, 2026
Merged

fix(json): parse deep nesting with a heap-backed stack#7832
proggeramlug merged 2 commits into
mainfrom
fix/7817-iterative-json-parser

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #7817. JSON.parse now switches from the recursive fast path to the existing flat tape representation once nesting passes the worker-stack threshold, then materializes that tape with an explicit heap-backed work stack. The reported 300,000-level document parses on a 2 MiB worker stack.

A separate 500,000-level iterative nesting budget keeps resource use finite and reports a catchable RangeError.

Changes

  • make tape validation strict enough to own the deep-input path without the recursive serde validation pass
  • add iterative tape materialization for arrays, objects, duplicate keys, strings, numbers, booleans, and null
  • route all three parse entries through the same recursive/iterative decision
  • retain the optimized recursive and typed-shape paths for ordinary payloads

Related issue

Closes #7817. Follows the crash guard in #7816.

Test plan

  • baseline reproduction: the old 1,001-level test passes on main by asserting that parsing returns an error
  • cargo test -p perry-runtime json::tests::nesting_depth -- --nocapture
  • cargo test -p perry-runtime json::tests -- --nocapture
  • cargo test -p perry-runtime json_tape::tests -- --nocapture
  • full perry-runtime suite: 2,108 passed; one unrelated promise keyed-table timing assertion failed under concurrent local load and passed immediately when rerun alone
  • cargo fmt --all -- --check
  • git diff --check
  • scripts/check_file_size.sh still reports only the two pre-existing main offenders fixed by fix(lint): unbreak the 2000-line file-size gate on main #7830

The quiet-mini benchmark is pending because its required lock is held by strcat-agent; no performance numbers are claimed here yet.

Screenshots / output

N/A (runtime parser change).

Checklist

  • Added regression tests
  • Added changelog.d/7832-iterative-json-parse.md
  • Kept ordinary JSON on the existing optimized path
  • No version bump or CHANGELOG.md edit
  • Run ordinary-payload timing on the quiet mini when its lock is free

Summary by CodeRabbit

  • New Features

    • JSON parsing now supports deeply nested documents, including inputs with up to 500,000 levels of nesting.
    • Deep JSON structures can be parsed reliably even with limited stack space.
  • Bug Fixes

    • Improved validation rejects malformed numbers, invalid escapes, control characters, trailing content, and incomplete structures.
    • Excessively deep input now returns a clear RangeError instead of risking parser failure.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

json: make JSON.parse iterative so nesting depth is not bounded by thread stack size

1 participant