fix(plugins): guard type-expression helper recursion in py/cs/ts — DoS hardening (v0.4.1) #3

Merged
buildagent merged 1 commit from fix/parser-typehelper-recursion-guard into master 2026-06-04 15:41:00 +02:00
Member

Closes the residual security item noted in the v0.4.0 ultradeep review.

Problem

v0.4.0 capped every plugin's walk recursion, but the self-recursive TYPE-ref helpers in the Python, C#, and TypeScript plugins (emit_type_ref / emit_receiver_type_refs) were still unbounded. A crafted file with a deeply nested type expression — List[List[...]], List<List<...>>, Array<Array<...>> — is reached via a shallow walk but then recurses thousands of levels inside the helper, overflowing the worker stack and SIGABRT-ing the daemon. catch_unwind can't intercept stack exhaustion.

Fix

Each helper now routes through a depth-aware _d core guarded by common::MAX_PARSE_DEPTH; the public method is a thin wrapper, so all call sites and extraction behavior are unchanged. PHP's type helper is structurally flat (union/qualified shapes can't nest) and needs no guard.

Verification

  • Deep-nested-type regression test per plugin (2 MiB stack = daemon worker stack, 20 000-deep type). Negative control: with the cap disabled all four SIGABRT; with it they pass.
  • 123 plugin tests green; clippy clean; daemon lang_e2e (55), gap_fill (20), correctness (6) unaffected — the type-ref parity behavior is identical.

Patch bump → v0.4.1.

🤖 Generated with Claude Code

Closes the residual security item noted in the v0.4.0 ultradeep review. ## Problem v0.4.0 capped every plugin's `walk` recursion, but the self-recursive **TYPE-ref helpers** in the Python, C#, and TypeScript plugins (`emit_type_ref` / `emit_receiver_type_refs`) were still unbounded. A crafted file with a deeply nested type expression — `List[List[...]]`, `List<List<...>>`, `Array<Array<...>>` — is reached via a *shallow* walk but then recurses thousands of levels inside the helper, overflowing the worker stack and SIGABRT-ing the daemon. `catch_unwind` can't intercept stack exhaustion. ## Fix Each helper now routes through a depth-aware `_d` core guarded by `common::MAX_PARSE_DEPTH`; the public method is a thin wrapper, so **all call sites and extraction behavior are unchanged**. PHP's type helper is structurally flat (union/qualified shapes can't nest) and needs no guard. ## Verification - Deep-nested-type regression test per plugin (2 MiB stack = daemon worker stack, 20 000-deep type). **Negative control:** with the cap disabled all four SIGABRT; with it they pass. - 123 plugin tests green; clippy clean; daemon `lang_e2e` (55), `gap_fill` (20), `correctness` (6) unaffected — the type-ref parity behavior is identical. Patch bump → **v0.4.1**. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(plugins): guard type-expression helper recursion in py/cs/ts (DoS hardening)
Some checks failed
CI / cargo fmt (pull_request) Failing after 15s
CI / cargo clippy (pull_request) Has been skipped
CI / cargo test (pull_request) Has been skipped
CI / cargo fmt (push) Failing after 16s
CI / cargo clippy (push) Has been skipped
CI / cargo test (push) Has been skipped
Release Build / Generate Version (push) Successful in 15s
Release Build / Build linux-x86_64 (push) Successful in 3m54s
Release Build / Build linux-aarch64 (push) Successful in 4m18s
Release Build / Build windows-x86_64 (push) Successful in 4m39s
Release Build / Create Forgejo Release (push) Failing after 1m1s
5669573a04
Follow-up to the v0.4.0 parser hardening. v0.4.0 capped every plugin's
`walk` recursion, but the self-recursive TYPE-ref helpers in the
Python, C#, and TypeScript plugins were still unbounded: a crafted file
with a deeply nested type expression (`List[List[...]]`,
`List<List<...>>`, `Array<Array<...>>`) is reached via a shallow walk
but recurses thousands of levels inside emit_type_ref /
emit_receiver_type_refs, overflowing the worker stack and SIGABRT-ing
the daemon (catch_unwind cannot intercept stack exhaustion).

Route each helper through a depth-aware `_d` core guarded by
common::MAX_PARSE_DEPTH; the public method is now a thin wrapper, so all
call sites and extraction behavior are unchanged. Adds a deep-nested-
type regression test per plugin (2 MiB stack, 20000-deep type); verified
they SIGABRT with the cap disabled and pass with it. PHP's type helper
is flat (no nesting) and needs no guard.

Closes the residual noted in the v0.4.0 review. 123 plugin tests green;
daemon e2e/parity unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
buildagent deleted branch fix/parser-typehelper-recursion-guard 2026-06-04 15:41:00 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
h-dv/code-index!3
No description provided.