Repository navigation
fix(interp): charge tilde expansion to the execution budget - #2672
Conversation
tilde_expand_literal built its result with String::new + push_str, so a script with many tildes (x=~:~:~:...) could grow output without ever touching ExecutionBudget (TM-DOS-134). Route all tilde paths through BudgetedString, hold declaration leases across expansion, and cover it with budget regression tests.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | 91997c5 | Commit Preview URL Branch Preview URL |
Oct 11 2026, 06:54 AM |
Move the BudgetedString temporaries out of expand_word_buffer's Literal arm into append_literal_segment, so each $(...) nesting level's poll frame stays small. Measured depth-32 stack threshold restored to the pre-tilde-change baseline (pass at 1968 KiB, abort at/below 1952 KiB); the inline version cost 16-32 KiB and aborted the coverage job under tarpaulin instrumentation.
|
The current CI watcher has a concrete completion bug, separate from CI status. Please cancel this exact still-live faulty watcher through supported cancel_task No stack-size waiver, force push, test/CI weakening, model change or duplicate |
|
Current afc0f81 still fails actual Linux Use a changed, matched diagnosis: macOS instrumented thresholds alone do not Monitor stopped ONLY the confirmed faulty SHA-gated watcher group85598 and |
|
Current working-tree review (04:03 UTC), before any new push: The plain-String redesign of tilde_expand_literal replaces BudgetedString::try_push_str with String::push_str, and only leases expanded.len() in callers after expansion has already allocated. That reintroduces the original finding: HOME/directory length multiplied by tilde count can allocate far beyond the live-memory budget before the later lease rejects. consume_work is not a live-memory reservation. The new comment claims reservation before allocation, but the code no longer does it. The operand suffix at expansion.rs around2281 also grows before leasing. Do not ship this scratch-allocation workaround or weaken its regression to repair stack coverage. Keep budget reservation before every growth and retain the lease while scratch/output coexist. Reduce stack frames by preserving the existing checked builder behind a smaller synchronous/heap-indirected boundary or another repository-consistent design, rather than allocating first and accounting afterward. Add bounded evidence that low live-memory limits prevent the original repeated-tilde amplification before allocation, plus finite compatibility and the still-required green Linux instrumented depth32 gate. Assembly frame size and macOS depth50 baseline do not waive either requirement. Preserve working changes and diagnostics; no model change, hook bypass or duplicate PR. |
append_literal_segment only fails with budget exhaustion, so return the small limit type directly instead of the shared Error. Keeps the hot poll frame lean (x86_64 closure sub rsp 1320 -> 1288; base 1144) with identical Error::from(LimitExceeded) semantics at the single conversion point. No accounting change: budget/stack suites green, depth-32 threshold unchanged.
What changed
Tilde expansion (
~user,x=~,x=~:~,${u-~}) now charges the shared execution budget. Previouslytilde_expand_literalbuilt results with an unbudgetedString, so a script stacking tildes could grow output without ever tripping budget limits.Why
Execution-budget E5 requires every interpreter allocation site to charge budget. Unbudgeted tilde expansion is a resource-exhaustion hole (TM-DOS-134): each
:operand re-resolves the home directory for free.Before / After
New regression tests fail on the old code (5 of 7 fail without the fix; the 2 parity tests pass both ways) and pass with it:
cargo test -p bashkit --test integration execution_budget: 32/32 passecho ~; x=~; echo "$x"; echo ~root; echo ~/sub; v=${u-~}; echo "$v"expands correctly (sandbox homes by design)Risk
Checklist