Skip to content

fix(interpreter): Box::pin expand_word to prevent stack overflow in nested $()#1109

Merged
chaliy merged 1 commit intomainfrom
fix/issue-1089-stack-overflow
Apr 6, 2026
Merged

fix(interpreter): Box::pin expand_word to prevent stack overflow in nested $()#1109
chaliy merged 1 commit intomainfrom
fix/issue-1089-stack-overflow

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented Apr 6, 2026

Summary

  • Box::pin expand_word and extract execute_cmd_subst helper to prevent stack overflow from nested command substitutions
  • Each $(...) level previously inlined the large expand_word async state machine into the caller's stack frame, causing SIGABRT at ~20-30 levels
  • With both futures boxed, each level uses constant stack space — depth 32 (default max_subst_depth) now completes safely

Changes

  • interpreter/mod.rs: convert expand_word from async fn to fn -> Pin<Box<Future>> wrapper over expand_word_inner; add execute_cmd_subst Box::pin-ed helper for the command substitution body
  • New stack_overflow_regression_tests.rs: 2 tests exercising depth 32 and nested arithmetic substitution
  • specs/006-threat-model.md: add TM-DOS-089

Test plan

  • cargo test --test stack_overflow_regression_tests — 2 new tests pass (previously SIGABRT)
  • cargo test --all-features -- --skip ssh_supabase — all pass
  • cargo clippy --all-targets --all-features -- -D warnings — clean

Closes #1089

…ested $()

Each command substitution level previously inlined the expand_word async
state machine into the caller's stack frame. The state machine is large
(many WordPart match arms with their locals) and at ~20-30 nesting levels
the call stack overflows with SIGABRT.

Fix by boxing two key futures:
- expand_word: wraps the inner implementation in Box::pin so each call
  allocates its future on the heap instead of the parent's stack
- execute_cmd_subst: new helper that Box::pin-s the command substitution
  body (state snapshot, command loop, state restore), keeping those
  large locals off the stack

With both futures boxed, each nesting level uses constant stack space
regardless of depth. The default max_subst_depth of 32 now completes
without overflow (previously crashed at ~20).

Closes #1089
@chaliy chaliy merged commit b4212af into main Apr 6, 2026
18 of 27 checks passed
@chaliy chaliy deleted the fix/issue-1089-stack-overflow branch April 6, 2026 10:25
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.

fuzz: arithmetic_fuzz stack overflow in nested evaluation

1 participant