Skip to content

Commit bfaa95b

Browse files
schmonzclaude
andcommitted
fix(bootstrap): Solaris's digest -a sha256 was missing from the hasher chain
CI run 35535250926, tjs-slow / leg (solaris-amd64, ...) failed: none of sha256sum/shasum/sha256/openssl/cksum exist there, so pick_hasher refused and the leg died loudly (correctly — an unverified engine must never be used). omnios and openindiana, both illumos, passed on the same run, so this is specific to the Oracle Solaris guest, not illumos generally. Add try_hasher 'digest -a sha256' to the chain, same KAT as every other hasher. Solaris's digest -a sha256 <file> prints the bare hex digest with no filename, which the existing extractor already handles, so no change to hash_file's parsing was needed. RED reproduced first: test/bootstrap-engine.test.cjs now shadows all five already-known hashers with exit-1 stubs and adds a stub digest, proving the resolver refused before this change (byte-for-byte the CI failure text) and resolves after it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVks4skLBgHSDcjnQ4kHz6
1 parent ee5c5e3 commit bfaa95b

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

‎scripts/bootstrap-engine.sh‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ pick_hasher() {
238238
return 1
239239
fi
240240
if try_hasher 'sha256sum' || try_hasher 'shasum -a 256' || try_hasher 'sha256 -q' \
241-
|| try_hasher 'openssl dgst -sha256' || try_hasher 'cksum -a sha256'; then return 0; fi
241+
|| try_hasher 'openssl dgst -sha256' || try_hasher 'cksum -a sha256' \
242+
|| try_hasher 'digest -a sha256'; then return 0; fi
242243
return 1
243244
}
244245

@@ -252,7 +253,7 @@ require_hasher() {
252253
fi
253254
die "bootstrap: no working sha256 tool on this host, so a downloaded engine cannot be
254255
verified and will not be used.$KAT_TRIED
255-
Install one (sha256sum / shasum / openssl / cksum -a sha256), or point CLODE_SHA256 at
256+
Install one (sha256sum / shasum / openssl / cksum -a sha256 / digest -a sha256), or point CLODE_SHA256 at
256257
one, or set CLODE_TJS to an engine you already trust."
257258
}
258259

‎test/bootstrap-engine.test.cjs‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,35 @@ shTest('the sha256 tool is KAT-tested, so a lying hasher is refused rather than
675675
assert.ok(r.err.includes(liar), 'and the refusal must name the tool that failed');
676676
});
677677

678+
// A Solaris guest (CI run 35535250926, job tjs-slow / leg (solaris-amd64, ...)) has NONE
679+
// of sha256sum / shasum / sha256 / openssl / cksum -a sha256 — its native digest utility
680+
// is `digest -a sha256 <file>`, printing the BARE hex with no filename (unlike
681+
// sha256sum's "<hex> <file>" shape). omnios and openindiana (both illumos, same CI run)
682+
// passed, so this is specific to the Oracle Solaris image, not to illumos generally.
683+
shTest("Solaris's `digest -a sha256` is accepted when nothing else in the chain is", () => {
684+
const d = mkdtemp();
685+
const bin = path.join(d, 'bin');
686+
fs.mkdirSync(bin, { recursive: true });
687+
// Shadow every hasher already in the fallback chain with a broken stand-in — this is
688+
// what a Solaris guest's PATH actually looks like to pick_hasher: all four fail.
689+
for (const broken of ['sha256sum', 'shasum', 'sha256', 'openssl', 'cksum']) {
690+
fakeExe(path.join(bin, broken), '#!/bin/sh\nexit 1\n');
691+
}
692+
const realShasum = execFileSync('sh', ['-c', 'command -v shasum'], { encoding: 'utf8' }).trim();
693+
// Computed via an ABSOLUTE path so the stub does not depend on any of the names just
694+
// shadowed above being resolvable — it stands in for Solaris's own implementation.
695+
fakeExe(path.join(bin, 'digest'), `#!/bin/sh\nshift 2\n"${realShasum}" -a 256 "$1" | awk '{print $1}'\n`);
696+
const body = FAKE_ENGINE(OK_TOKEN);
697+
const { manifest: mf, base } = localPack(path.join(d, 'base'), { [hostTarget()]: body });
698+
const r = sh([], {
699+
CLODE_CACHE: path.join(d, 'cache'),
700+
CLODE_RELEASE_BASE: base,
701+
CLODE_BOOTSTRAP_MANIFEST: mf,
702+
PATH: `${bin}:${process.env.PATH}`,
703+
});
704+
assert.strictEqual(r.status, 0, `expected digest -a sha256 to be picked up, got ${r.status}: ${r.err}`);
705+
});
706+
678707
// ---------------------------------------------------------------------------
679708
// dash, when this box has one. The scar: shell discovery needs a shell BY NAME,
680709
// and /bin/sh behaviours vary. A resolver that only ever ran under this Mac's sh

0 commit comments

Comments
 (0)