Files
Colby McHenry cbf84855e7 fix(kernel): guard the native walkers against stack overflow and defer deep files to wasm (#1581)
A C/C++ (or any other kernel-routed) file with extremely deep nesting —
clang's 16,384-brace `parser_overflow.c`, fuzzer corpora — parsed fine
(tree-sitter is iterative) and then overflowed the native stack of the
kernel's recursive walker. A native overflow is uncatchable: the parse
worker is a thread of the `codegraph` process, so the SIGSEGV took the
whole indexer down with no message, no partial index and no per-file
fallback. Worker threads get Node's 4 MiB default stack; the 8 MiB main
thread only moved the cliff (100k levels still died), so a bigger
`resourceLimits.stackSizeMb` was never a fix.

The walkers now guard their own recursion against the CALLING THREAD's
real stack bounds (`codegraph-kernel/src/stack.rs`: glibc/musl
`pthread_getattr_np`, macOS `pthread_get_stackaddr_np`, Win32
`GetCurrentThreadStackLimits`; one thread-local load + one compare per
recursive entry, inserted by the `stack_guard!` macro at all 150
self-recursive / on-cycle walker functions). Within 256 KiB of the limit
the walk stops descending and latches a flag; `stack::run_guarded` turns
a tripped walk into the kernel's existing `defer:` routing signal, so the
file takes the wasm path — whose walker catches its own JS `RangeError`
per file — and lands as a partial result with a recorded parse error
while the rest of the repository indexes normally. Platforms without a
bounds query fall back to a fixed descent budget that is safe on any
stack ≥ 2 MiB. No Worker stack bump; no new crates beyond `libc`
(already in the lock file transitively).

Validated: the reporter's `deep.c` inside a default 4 MiB worker goes
from rc=132/139 to a clean `deferred` exit; `codegraph init` on a repo
holding it exits 0 with the file recorded; 60k-deep expressions in every
default-routed language survive on the main thread and in a worker;
Rust unit tests drive the walkers on a 1 MiB thread; all 15 existing
kernel parity suites unchanged; index wall-clock on express and redis
within run-to-run noise with identical node/edge counts; Linux verified
in Docker (node:22-bookworm, glibc bounds path).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LxZj6W6Y1SHXwvpT3uwJpK
2026-08-22 11:01:26 -07:00
..