Reject Mach-O and ZIP entries whose metadata no longer matches the reader inventory, preventing a sibling adapter key from selecting bytes under another entry. Reuse the existing ASAR metadata snapshot and equality rules and read Mach-O ranges from owned records. Move the real system-lipo test to the provider boundary suite, release its reader, and derive slice expectations from the host FAT table. Validation: 68 focused artifact, ASAR and MCP tests plus ZIP cancellation passed. Real macOS lipo was exercised against /bin/ls; Ghidra, IDA and other deep providers were not run. Static, docs, architecture and test discovery checks passed.
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
|
|
import { describe, expect, it, onTestFinished } from "vitest";
|
|
|
|
import { MachOSliceArtifactReader } from "../../../../src/artifacts/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<readonly (readonly [number, number])[]> => {
|
|
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 slice ranges against its FAT table",
|
|
async () => {
|
|
const reader = new MachOSliceArtifactReader("/bin/ls", {});
|
|
onTestFinished(() => reader.close());
|
|
const entries = [];
|
|
for await (const entry of reader.entries()) entries.push(entry);
|
|
expect(new Set(entries.map(({ path }) => path)).size).toBe(
|
|
entries.length,
|
|
);
|
|
expect(entries.every(({ path }) => path.startsWith("slices/"))).toBe(
|
|
true,
|
|
);
|
|
expect(
|
|
entries.map(({ byteOffset, declaredSize }) => [
|
|
byteOffset,
|
|
declaredSize,
|
|
]),
|
|
).toEqual(await fatSlices("/bin/ls"));
|
|
},
|
|
);
|
|
});
|