test: widen the read-guard sweep to bin/ and to plain-statement reads
The #43 sweep (test/cli.sh:705) matched the literal `-rsp` spelling and scanned commands/ only. #68 was a plain `read -r reply` in bin/rig, so it missed on BOTH axes — the spelling and the path — and the bug survived until a drill hit it. The class is the shape, not the flags: any `read` run as a plain statement under `set -euo pipefail` kills the shell at EOF, before the `case` that would have printed the abort. The failure is silent and exits 1, which is also what a normal refusal exits, so an exit-code assertion passes against it. The new sweep anchors `read` at the start of a statement across bin/ and commands/, whatever its flags or arity, and subtracts only the two shapes that are safe by construction: a `||` guard (the cure itself) and a `<<<` here-string (which cannot return non-zero). `while`/`if ! ` heads need no subtraction — the anchor already excludes them. Guard against reintroduction, not a live fix: the tree is clean once #68's one-token fix lands. Mutation-verified — a bare `read -r foo` planted in bin/rig gives 404 passed, 1 failed, and the old #43 sweep stays green on the same tree, which is precisely the gap being closed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
880e95df21
commit
d144ae379c
1 changed files with 24 additions and 0 deletions
24
test/cli.sh
24
test/cli.sh
|
|
@ -817,6 +817,30 @@ check "runner remove: headless token prompt refuses loudly" 0 "" \
|
|||
# so a bare `read -rsp` (no `||` on its line) must not exist anywhere.
|
||||
check "prompts: no bare read -rsp remains" 1 "" \
|
||||
grep -RE 'read -rsp[^|]*$' "$ROOT/commands/"
|
||||
# ...and the same sweep, widened on the two axes #68 escaped through (#75).
|
||||
# That check reads `-rsp` literally and scans commands/ only; #68 was a plain
|
||||
# `read -r reply` in bin/rig, so it missed on the spelling AND on the path.
|
||||
# The class is the shape, not the flags: any `read` run as a PLAIN STATEMENT
|
||||
# under `set -euo pipefail` kills the shell at EOF, before the `case` that
|
||||
# would have printed the abort — silently, with exit 1, indistinguishable
|
||||
# from a normal refusal.
|
||||
#
|
||||
# So: match `read` at the start of a statement (leading whitespace only),
|
||||
# whatever its flags or arity, then subtract the two shapes that are safe by
|
||||
# construction:
|
||||
# `||` — the guard itself (`|| die`, `|| reply=""`, `|| { echo; die … }`).
|
||||
# An errexit-exempt read, which is the whole cure.
|
||||
# `<<<` — a here-string always supplies a terminating newline, so the read
|
||||
# cannot return non-zero. lib/users-config.sh:50/:78 are these.
|
||||
# `while`/`until`/`if` heads need no subtraction: the anchor already excludes
|
||||
# them, since `read` is not the first word on those lines. Keep the guard on
|
||||
# the read's own line — a `\`-continued `||` reads as unguarded here, by
|
||||
# design, because it is not visible at the point of failure.
|
||||
unguarded_read() {
|
||||
grep -REn '^[[:space:]]*read[[:space:]]' "$ROOT/bin/" "$ROOT/commands/" \
|
||||
| grep -Ev '\|\||<<<'
|
||||
}
|
||||
check "prompts: no unguarded plain-statement read remains (#75)" 1 "" unguarded_read
|
||||
|
||||
# --- runner install: --repo must agree with what the box is already on -------
|
||||
# The bug: `install --repo B` on a box registered to repo A skipped configure,
|
||||
|
|
|
|||
Loading…
Reference in a new issue