Repository navigation
Decision: How the Guard Reads a Shell-Rewritable Word in a timeout Run (#2117) #2118
Copy link
Copy link
Closed
Description
Question
Pull request #2117 (handoff #2072, track auto-1634, branch feature/auto-1634 at cd97e26) fixes #1634. Decision #2079 said to open it and let the review loop dispose of that pass's findings. The pass raised one finding, fixed in 62ac767. The next pass raised 3, fixed in cd97e26. The pass after that raised 3 more, all introduced. Both edit rounds for this push are spent, so editing stopped. How should the guard read a word the shell may rewrite?
What the branch holds now
- A
timeoutsending signal 0 is no bound unless a duration-form-kfollows it. - An option word or option value the shell may rewrite (
-${F}0,-k $K,-s $SIG, a brace, a glob, a tilde) is read as both a signal-0-sand a-kof no duration form. A later literal-sor-kreplaces its own half. - A nested
timeoutchain is bounded only when every outer one sends signal 0 with no-kand the innermost one is a bound. Past the prefixes and assignments directly after an outer duration, a word namingtimeout, or one the shell may rewrite, is read as nesting. --selftestpasses, each new row was checked by reverting its logic, and every local gate is clean.
Open findings from the last strict pass
introduced, 3. Each is an allow, and each was run against GNU timeout 9.7 with the loop outliving the outer bound.
- An assignment argument is skipped unread.
timeout -s KILL 10 env X=$T 800 bash -c '<the loop>'withT='1 timeout'is allowed. The prefix skip passesX=$Tbefore the rewrite check sees it, and afterenvthe shell word-splits it, so an innertimeoutruns. - A launcher builds the inner
timeoutfrom its own arguments.timeout -s KILL 10 env -S 'timeout 800' bash -c '<the loop>'andecho timeout | timeout -s KILL 10 xargs -I% % 800 bash -c '<the loop>'are allowed. No whole word namestimeout. - "A later
-sor-kreplaces its own half" is false. A rewritten word can split into a duration and a command, which ends option parsing, so the later literal-kbecomes that command's argument.timeout -$X -k 30 900 bash -c '<the loop>'is allowed, withXholdings0 900 bash -c '<shifts>'. The self-test row allowingtimeout -${F}0 -k 30 900 ...rests on the same false premise.
Each pass on this lane has found new holes in the rewrite model itself, and finding 3 is against text the last round wrote.
Options
- Recommended: deny any rewritable word in a
timeoutrun. Any word betweentimeoutand the wrapper that the shell may rewrite makes the run no bound, whatever follows it. That covers the options, the values, the prefix span, and assignment arguments. No later-sor-krescues it. This closes findings 1 and 3 by construction instead of modelling what the rewrite yields. Finding 2 is a different class, a launcher building a command from its arguments. It would be declared in README requirement 7 as a shape not reached and filed as a follow-up. The cost is a declared false deny on a rare shape such astimeout 900 env PATH=$HOME/bin bash -c '<the loop>'. - Keep the current model and declare all three as limits. Remove the false sentence and the false self-test row, then list the three shapes in README requirement 7 as not reached. The PR review loop takes it from there. This is the smallest diff, but the rewrite model stays one that each pass finds new holes in.
- Fix the three within the current model. Read assignment arguments,
env -S, andxargs, and drop the "later option replaces" rule. The lane parks again if the next pass finds anythingintroduced, which every pass on this lane has so far.
Blocks
- Handoff Session Handoff [auto-1634]: Narrow Nested timeout Handling per #2056 #2072 (track
auto-1634). - Pull request Deny a Signal-0 timeout as a Wait Bound in the Guard #2117 to develop, head cd97e26.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
ptr727 commentedon Sep 30, 2026
Answered by the maintainer on 2026-09-30: option 1: deny any rewritable word in a
timeoutrun, whatever follows it. Declare the launcher class (finding 2) as a shape not reached in README requirement 7, and file it as a follow-up.Deny Any Rewritable Word in a timeout Run