Files
regex-tools/scripts/cpp-engine-pack.test.ts

200 lines
7.1 KiB
TypeScript

// @vitest-environment node
import { createHash } from "node:crypto";
import { cp, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { writeEngineChecksums } from "./checksummed-engine-pack.mjs";
import { CPP_LOCK, verifyCppPack } from "./cpp-engine-pack.mjs";
const temporaryDirectories: string[] = [];
afterEach(async () => {
await Promise.all(
temporaryDirectories
.splice(0)
.map((directory) => rm(directory, { recursive: true, force: true })),
);
});
describe("C++ engine-pack gate", () => {
it("verifies the installed exact Emscripten/libc++ pack and bridge sources", async () => {
await expect(
verifyCppPack(path.resolve("public", "engines", "cpp")),
).resolves.toEqual(
expect.objectContaining({
engineVersion: "Emscripten 6.0.4 libc++ std::wregex",
bridge: expect.objectContaining({
abiVersion: 1,
dynamicExecutionDisabled: true,
replacement: {
semantics: "libc++ match_results::format default grammar",
implementation:
"bounded streaming expansion without materializing an unbounded native format result",
paritySelfTest:
"load-time fixtures compare the bounded expander with libc++ match_results::format",
},
}),
toolchain: expect.objectContaining({
version: "6.0.4",
commitSha1: "fe5be6afdff43ad58860d821fcc8572a23f92d19",
emsdkCommitSha1: "224ec5f9f2f72f09f9ce0e26d66bae7dbd8b692f",
releaseCommitSha1: "b23272fac5d05617cd36dc451356dca0f79bf22d",
llvmVersion: "24.0.0git",
llvmCommitSha1: "c050c487e9edb97ef44f53cb29fe1d8bcddb8f76",
}),
licensing: {
sourceManifest: "SOURCE-MANIFEST.json",
linkedComponentCount: 6,
auditedExclusions: ["libunwind"],
independentlyPinnedLegalFiles: 6,
},
}),
);
});
it("pins exception-enabled compilation and its exact traced native component set", async () => {
expect(CPP_LOCK.emscriptenVersion).toBe("6.0.4");
expect(CPP_LOCK.linkedArchives).toEqual([
"libc++.a",
"libc++abi.a",
"libc.a",
"libclang_rt.builtins.a",
"libembind-rtti.a",
"libemmalloc.a",
"libnoexit.a",
"libstubs.a",
]);
const metadata = JSON.parse(
await readFile(
path.resolve("public", "engines", "cpp", "engine-metadata.json"),
"utf8",
),
) as { toolchain: { command: string } };
expect(metadata.toolchain.command).toContain("-fexceptions");
expect(metadata.toolchain.command).toContain("-sMALLOC=emmalloc");
expect(metadata.toolchain.command).toContain("-Wl,--trace");
const sourceManifest = JSON.parse(
await readFile(
path.resolve("public", "engines", "cpp", "SOURCE-MANIFEST.json"),
"utf8",
),
) as {
buildSelection: { exactLinkedArchives: string[] };
sourceEvidence: { sourcePath: string; sourceSha256: string }[];
linkedComponents: {
id: string;
linked: boolean;
legalFiles: string[];
}[];
};
expect(sourceManifest.buildSelection.exactLinkedArchives).toEqual(
CPP_LOCK.linkedArchives,
);
expect(sourceManifest.sourceEvidence).toContainEqual({
sourcePath: "system/lib/emmalloc.c",
sourceSha256:
"00eb577cbef51a3359c309f45a7c99a814b8c6151ab75c9a3c78a56f0169146b",
});
expect(
sourceManifest.linkedComponents
.filter(({ linked }) => linked)
.map(({ id }) => id),
).toEqual([
"emscripten-runtime",
"musl",
"emmalloc",
"compiler-rt",
"libc++",
"libc++abi",
]);
expect(
sourceManifest.linkedComponents.find(({ id }) => id === "libunwind"),
).toEqual(
expect.objectContaining({
linked: false,
legalFiles: ["LICENSE-libunwind.txt"],
}),
);
const module = await readFile(
path.resolve("public", "engines", "cpp", "cpp-regex.mjs"),
"utf8",
);
expect(module).not.toContain("new Function");
expect(module).not.toMatch(/\beval\s*\(/u);
});
it("rejects substituted legal text even when self-reported checksums are regenerated", async () => {
const directory = await mkdtemp(path.join(tmpdir(), "regex-cpp-pack-"));
temporaryDirectories.push(directory);
const pack = path.join(directory, "cpp");
await cp(path.resolve("public", "engines", "cpp"), pack, {
recursive: true,
});
const replacement = Buffer.from("substituted legal text\n");
await writeFile(path.join(pack, "LICENSE-Emscripten.txt"), replacement);
const metadataFile = path.join(pack, "engine-metadata.json");
const metadata = JSON.parse(await readFile(metadataFile, "utf8")) as {
files: { path: string; sha256: string; bytes: number }[];
};
const record = metadata.files.find(
({ path: name }) => name === "LICENSE-Emscripten.txt",
);
expect(record).toBeDefined();
if (!record) return;
record.sha256 = createHash("sha256").update(replacement).digest("hex");
record.bytes = replacement.byteLength;
await writeFile(metadataFile, `${JSON.stringify(metadata, null, 2)}\n`);
await writeEngineChecksums(pack);
await expect(verifyCppPack(pack)).rejects.toThrow(
/metadata drifted from its pinned sources/u,
);
});
it("rejects a forged source inventory even when self-reported checksums are regenerated", async () => {
const directory = await mkdtemp(path.join(tmpdir(), "regex-cpp-pack-"));
temporaryDirectories.push(directory);
const pack = path.join(directory, "cpp");
await cp(path.resolve("public", "engines", "cpp"), pack, {
recursive: true,
});
const sourceManifestFile = path.join(pack, "SOURCE-MANIFEST.json");
const sourceManifest = JSON.parse(
await readFile(sourceManifestFile, "utf8"),
) as {
linkedComponents: { id: string; linked: boolean }[];
};
const libunwind = sourceManifest.linkedComponents.find(
({ id }) => id === "libunwind",
);
expect(libunwind).toBeDefined();
if (!libunwind) return;
libunwind.linked = true;
const replacement = Buffer.from(
`${JSON.stringify(sourceManifest, null, 2)}\n`,
);
await writeFile(sourceManifestFile, replacement);
const metadataFile = path.join(pack, "engine-metadata.json");
const metadata = JSON.parse(await readFile(metadataFile, "utf8")) as {
files: { path: string; sha256: string; bytes: number }[];
};
const record = metadata.files.find(
({ path: name }) => name === "SOURCE-MANIFEST.json",
);
expect(record).toBeDefined();
if (!record) return;
record.sha256 = createHash("sha256").update(replacement).digest("hex");
record.bytes = replacement.byteLength;
await writeFile(metadataFile, `${JSON.stringify(metadata, null, 2)}\n`);
await writeEngineChecksums(pack);
await expect(verifyCppPack(pack)).rejects.toThrow(
/metadata drifted from its pinned sources/u,
);
});
});