From c89b3a00dce8df36ddb696b59c80e1adc6aceac1 Mon Sep 17 00:00:00 2001 From: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> Date: Fri, 9 Oct 2026 01:12:27 -0700 Subject: [PATCH] test(artifacts): read /bin/ls slice layout from its FAT table (#1223) The real-lipo slice test pinned the byte offsets and sizes of one macOS release's /bin/ls, so it failed on any host whose /bin/ls differs (macOS 26.7.1: x86_64 48128 bytes, arm64e 88672, versus the pinned 48112 and 89088). Read the expected layout from the binary's FAT header instead. Co-authored-by: Claude Opus 5.5 --- .../MachOSliceArtifactReader.test.ts | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/artifacts/MachOSliceArtifactReader.test.ts b/src/artifacts/MachOSliceArtifactReader.test.ts index 8db4ab16fc..504dfec6f5 100644 --- a/src/artifacts/MachOSliceArtifactReader.test.ts +++ b/src/artifacts/MachOSliceArtifactReader.test.ts @@ -1,7 +1,24 @@ +import { readFile } from "node:fs/promises"; + import { describe, expect, it } from "vitest"; import { MachOSliceArtifactReader } from "./MachOSliceArtifactReader.js"; +/** + * Read a 32-bit FAT table directly. The host's /bin/ls changes between macOS + * releases, so the expected slice layout comes from the file itself. + */ +const fatSlices = async ( + path: string, +): Promise => { + const bytes = await readFile(path); + expect(bytes.readUInt32BE(0)).toBe(0xca_fe_ba_be); + return Array.from({ length: bytes.readUInt32BE(4) }, (_, index) => { + const entry = 8 + index * 20; + return [bytes.readUInt32BE(entry + 8), bytes.readUInt32BE(entry + 12)]; + }); +}; + describe("Mach-O slice reader with system lipo", () => { it.skipIf(process.platform !== "darwin")( "checks real /bin/ls lipo CPU symbols and ptrauth capabilities against the FAT table", @@ -18,10 +35,7 @@ describe("Mach-O slice reader with system lipo", () => { byteOffset, declaredSize, ]), - ).toEqual([ - [16384, 48112], - [65536, 89088], - ]); + ).toEqual(await fatSlices("/bin/ls")); }, ); });