Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion lib/checkrun/autolint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,15 @@ _autolint_read_files0() {
# field for both EOF and descriptor errors. Reject a closed descriptor and
# directory source before reading so an invalid stream cannot become a
# silent no-op. Pipes, regular files, sockets, and terminals remain valid.
if { [ ! -r /dev/stdin ] && [ ! -r /dev/fd/0 ]; } ||
# Test descriptor openness by duplicating fd 0 into a subshell rather
# than by probing /dev/stdin readability: on the ubuntu-26.04 runner
# a closed stdin arrives as /dev/null (the runner's bash reopens it
# at process startup, verified with a fresh `bash -c` probe), so the
# /dev probe passes and the read loop treats it as EOF. Duplicating
# a closed descriptor fails; duplicating an open one succeeds
# regardless of what it points at. (Duplicating fd 0 onto itself is
# a no-op even when closed, so the target must differ.)
if ! ( exec 3<&0 ) 2>/dev/null ||
[ -d /dev/stdin ] || [ -d /dev/fd/0 ]; then
echo "autolint: --files0-from - requires a readable stream on standard input" >&2
return 2
Expand Down
8 changes: 7 additions & 1 deletion test/suites/autolint-test
Original file line number Diff line number Diff line change
Expand Up @@ -3056,7 +3056,13 @@ _assert_exit "files0 stdin: empty input is a no-op" 0 "$rc"
_assert_eq "files0 stdin: empty input is quiet" "" "$output"

set +e
output=$("$AUTOLINT" --files0-from - <&- 2>&1)
# Invoke in-process, not via bin/autolint: the ubuntu-26.04 runner's bash
# reopens /dev/null for a closed stdin at process startup (verified: a
# fresh `bash -c` probe with closed stdin arrives with fd 0 -> /dev/null),
# so a subprocess invocation can never observe the closed descriptor the
# guard is meant to reject. A command-substitution subshell forks without
# re-running bash startup, so the closed fd survives to _autolint_main.
output=$(. "$CHECKRUN_TEST_ROOT/lib/checkrun/autolint.sh"; _autolint_main --files0-from - <&- 2>&1)
rc=$?
set -e
_assert_exit "files0 stdin: closed descriptor exits 2" 2 "$rc"
Expand Down
Loading