Repository navigation
Conversation
Each N<file / N<<< / N<&M redirect retained a StreamData clone in the redirect list with no aggregate or live-bytes accounting, and re-redirecting the same fd appended instead of replacing. Charge consume_input + lease_bytes before every clone/retained allocation across all input branches and replace superseded fd entries.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | 6f46a4a | Commit Preview URL Branch Preview URL |
Oct 12 2026, 06:06 AM |
…th buffers StreamData retains bytes plus decoded text; charge retained_len so the live/aggregate admission covers the full backing store. Store each live-bytes lease with its fd entry so replacing a superseded descriptor releases the old lease while aggregate consumption stays cumulative. Tests: exact 63/64 and 71/72 boundaries, live release on replace (2x transient), cumulative-across-replace, all reachable retaining branches, 1024x /dev/zero shape, session recovery, dup-chain parity, 1MiB heredoc bound.
…p/child bounds The DupInput-into-stdin clone dropped its live lease while retained. The stdin slot now carries the clone lease and the setup struct hands it to callers, who hold it for stdin's lifetime; replacing stdin drops both. Tests: two-phase DupInput proof (source fits, target trips InputBytes), ReadWrite trip, stdin-clone 3x64B live overlap (192 ok / 191 LiveBytes) with recovery, bounded-child original 1024x/dev/zero denial naming aggregate input bytes with clean exit 1.
Under cargo-llvm-cov the spawned CLI inherits LLVM_PROFILE_FILE and flushes a multi-MiB profraw at exit, tripping the child's 1MiB -f cap (SIGXFSZ, wait status 153). Point the child's profile at a controlled temp sink (coverage stays enabled), raise -f to an explicit 128MiB artifact allowance with a size receipt plus cleanup, and stop equating signal death with OOM in assertions.
Required bounded-child proof for current 6f46a4aThe stdin-clone lease handoff, nonvacuous DupInput/overlap tests and exact default-limit original shape are genuine repairs. The SIGXFSZ diagnosis is also more precise than calling every signal OOM. Preserve those improvements. Before merge,
Retain the original 1024 |
What
Every numbered input redirect (
N<file,N<<<str,N<&M) retained a fullStreamDataclone in the redirect list with no budget accounting, and re-redirecting the same fd appended instead of replacing. Each clone now chargesconsume_input(aggregate) +lease_bytes(live, held for the redirect list lifetime) before the clone/allocation, across all five input branches, andreplace_own_fdgives the fd list replace semantics (latest-wins reads unchanged).Why
Unbounded transient memory:
3</big 4</big ...duplicates the buffer once per fd (plus a second copy insideStreamData's bytes+text pair) with no budget trip.Before / After
New tests in
input_redirect_budget_tests.rs(verified failing-first via stash):numbered_input_redirects_charge_aggregate_input_budget:: 3</big 4</big(2x64B, 100B aggregate cap) failed before (exec succeeded), now errorsInputBytes.numbered_input_redirects_hold_live_bytes_budget: same shape againstmax_live_intermediate_bytesnow errorsLiveBytes.superseded_numbered_input_fd_is_replaced:cat 3</a 3</b <&3still prints the second file (behavior guard).Validation
cargo fmt --check,cargo clippy -p bashkit --all-targets: clean{:?}added (TM-INF-022)Produced by yolop