Skip to content

Commit 15867ed

Browse files
committed
Exempt the two config files by name, not the whole savannah domain
The comment claimed a config.guess/config.sub exemption but the pattern was a domain wildcard, so any other unverified download from that host would have been skipped — with the checksummed Ruby URL keeping the count nonzero, silently. Intent and implementation disagreed, and the implementation was the permissive one. Narrowing it first required fixing an extraction bug underneath. Excluding shell metacharacters from the URL pattern also truncated URLs that legitimately contain them: both savannah links were being cut at the first semicolon, down to `?p=config.git`, discarding the `f=config.guess` / `f=config.sub` that says which file is fetched. Nothing to match on. Metacharacters are now allowed inside the match and trimmed from the end instead, which is where they actually signal shell syntax rather than URL content. Verified: real definitions still pass, a different artifact from the same host is now caught, so is the same gitweb config.git path requesting another file, and unquoted URLs trailed by `;` or `&&` are trimmed and still checked.
1 parent da3df67 commit 15867ed

1 file changed

Lines changed: 34 additions & 9 deletions

File tree

‎bin/ci‎

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,30 @@ ERROR=$'\033[1;31m'; SUCCESS=$'\033[1;32m'; RESET=$'\033[0m'
2727

2828
failures=()
2929

30-
# A URL ends at whitespace, a quote, or a shell metacharacter — so `"url"`, `'url'`, a bare
31-
# `url;` and `$(... url)` all yield the same string. Built here rather than inline because
32-
# embedding a single quote inside a single-quoted grep pattern is unreadable.
30+
# A URL ends at whitespace or a quote. Shell metacharacters are deliberately allowed
31+
# *inside* the match and trimmed from the end afterwards (see trim_url): excluding them
32+
# outright truncates legitimate URLs that contain them, and the savannah gitweb links are
33+
# exactly that — `?p=config.git;a=blob_plain;f=config.guess;hb=HEAD` would be cut at the
34+
# first semicolon, discarding the part that says which file it fetches.
35+
#
36+
# Built here rather than inline because embedding a single quote inside a single-quoted
37+
# grep pattern is unreadable.
3338
SQ="'"
34-
URL_RE="https?://[^[:space:];)(&|<>\`\"$SQ]+"
39+
URL_RE="https?://[^[:space:]\"$SQ\`]+"
40+
41+
# Strip trailing shell punctuation left over from an unquoted URL (`…tar.gz; fi`,
42+
# `…tar.gz && echo`). Safe because none of these can legitimately end a URL, unlike the
43+
# semicolons that appear mid-query-string above.
44+
trim_url() {
45+
local u="$1"
46+
while :; do
47+
case "$u" in
48+
*[\;\)\(\&\|\<\>]) u="${u%?}" ;;
49+
*) break ;;
50+
esac
51+
done
52+
printf '%s' "$u"
53+
}
3554

3655
echo "${BANNER}🚀 Local CI for ruby-dev${RESET}"
3756

@@ -111,12 +130,18 @@ lint_checksums() {
111130
ok=true
112131
found=0
113132
while IFS= read -r url; do
133+
url=$(trim_url "$url")
114134
case "$url" in
115-
# The sole exemption. config.guess/config.sub are fetched from GNU's git web view,
116-
# which serves a moving HEAD with no release tarball and no published digest. They
117-
# only teach ancient configure scripts about modern architectures and are never
118-
# linked into the built Ruby. Anything else must carry a digest.
119-
https://git.savannah.gnu.org/*) continue ;;
135+
# The sole exemption, and deliberately spelled out to the exact file rather than
136+
# by domain: config.guess and config.sub come from GNU's git web view, which serves
137+
# a moving HEAD with no release tarball and no published digest. They only teach
138+
# ancient configure scripts about modern architectures and are never linked into
139+
# the built Ruby.
140+
#
141+
# A domain wildcard here would quietly exempt any other unverified download from
142+
# the same host — re-opening the false-green path this check exists to close.
143+
*git.savannah.gnu.org/gitweb/?p=config.git*f=config.guess*|\
144+
*git.savannah.gnu.org/gitweb/?p=config.git*f=config.sub*) continue ;;
120145
esac
121146
found=$(( found + 1 ))
122147
[[ $url =~ \#[0-9a-f]{64}$ ]] || { fail "$f: no sha256 on ${url%%\#*}"; ok=false; }

0 commit comments

Comments
 (0)