Files
reverse-engineering-anything/src/firmware/FirmwareNestedCoverage.test.ts
T
morluto fd9d362d98 fix(firmware): derive nested coverage from each reported file (#10077)
* fix(firmware): account for unclassified nested file bytes

* fix(firmware): describe nested gaps without invented chunk facts
2026-11-11 18:18:00 +08:00

265 lines
7.7 KiB
TypeScript

import { createHash } from "node:crypto";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { gzipSync } from "node:zlib";
import { expect, it } from "vitest";
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
import { createAnalysisExecution } from "../application/AnalysisProvider.js";
import { FirmwareAnalysisService } from "../application/firmware/FirmwareAnalysisService.js";
import { ok } from "../domain/result.js";
import { startFirmwareDeadline } from "./FirmwareDeadline.js";
import {
FirmwareFileAccess,
inventoryFirmwareOutput,
} from "./FirmwareFiles.js";
import { publishFirmwareExtraction } from "./FirmwarePublication.js";
import { normalizeUnblobReport } from "./FirmwareReports.js";
const hash = (bytes: Buffer) =>
createHash("sha256").update(bytes).digest("hex");
const known = (id: string, start: number, end: number) => ({
__typename__: "ChunkReport",
id,
start_offset: start,
end_offset: end,
size: end - start,
handler_name: "authored-handler",
is_encrypted: false,
extraction_reports: [],
});
const cases = [
{ name: "opaque child", spans: [], gaps: [[0, 6]], coverage: "partial" },
{
name: "partly classified child",
spans: [[2, 4]],
gaps: [
[0, 2],
[4, 2],
],
coverage: "partial",
},
{
name: "fully classified child",
spans: [[0, 6]],
gaps: [],
coverage: "complete",
},
{
name: "explicit unknown child",
spans: [],
gaps: [],
coverage: "partial",
unknown: true,
},
{
name: "empty child",
spans: [],
gaps: [],
coverage: "complete",
empty: true,
},
] as const;
/** Inert gzip bytes and matching authored Unblob task reports; no engine runs. */
const capture = async (selection: (typeof cases)[number]) => {
const root = await createTestTempDirectory("rea-nested-firmware-coverage-");
const staging = join(root, "staging");
await mkdir(staging);
const child = Buffer.from("empty" in selection ? "" : "opaque");
const compressed = gzipSync(child);
const original = Buffer.concat([
Buffer.from("prefix!"),
compressed,
Buffer.from("suffix"),
]);
const path = join(root, "firmware.bin");
const inputPath = join(root, "selected.gz");
const childPath = join(staging, "child.bin");
await writeFile(path, original);
await writeFile(inputPath, compressed);
await writeFile(childPath, child);
const task = {
path: childPath,
depth: 1,
blob_id: "container",
is_multi_file: false,
};
const stat = (path: string, size: number) => ({
__typename__: "StatReport",
path,
size,
is_file: true,
is_dir: false,
is_link: false,
link_target: null,
});
const raw = [
{
task: { path: inputPath, depth: 0, blob_id: "", is_multi_file: false },
reports: [
stat(inputPath, compressed.length),
{ __typename__: "HashReport", sha256: hash(compressed) },
known("container", 0, compressed.length),
],
subtasks: [task],
},
{
task,
reports: [
stat(childPath, child.length),
{ __typename__: "HashReport", sha256: hash(child) },
...selection.spans.map(([start, end], index) =>
known(String(index), start, end),
),
...("unknown" in selection
? [
{
__typename__: "UnknownChunkReport",
id: "opaque",
start_offset: 0,
end_offset: child.length,
size: child.length,
},
]
: []),
],
subtasks: [],
},
];
return {
root,
staging,
path,
inputPath,
child,
original,
raw,
context: {
inputPath,
outputRoot: staging,
sha256: hash(compressed),
length: compressed.length,
offset: 7,
maxDepth: 3,
},
};
};
/** Exercise actual file publication and the shared Evidence boundary. */
const evidence = async (fixture: Awaited<ReturnType<typeof capture>>) => {
const files = new FirmwareFileAccess();
const output = join(fixture.root, "published");
try {
const normalized = normalizeUnblobReport(fixture.raw, fixture.context);
const published = await publishFirmwareExtraction({
files,
workspacePath: fixture.root,
deadline: startFirmwareDeadline("publication", 120_000),
analysisTimeoutMs: 120_000,
outputDirectory: output,
entries: await inventoryFirmwareOutput(
fixture.staging,
1024,
10,
1024,
"extract_firmware",
),
normalized,
selection: {
offset: 7,
length: fixture.context.length,
sha256: fixture.context.sha256,
},
maxDepth: 3,
engine: {
name: "unblob",
version: "authored-fixture",
executable_path: "/inert/unused/unblob",
executable_sha256: "a".repeat(64),
source_revision: null,
worker_count: 1,
},
signal: new AbortController().signal,
retainCleanup: () => {
throw new Error("Unexpected fixture cleanup failure");
},
});
const execution = createAnalysisExecution(
published,
{ id: "unblob", name: "Authored Unblob report", version: "fixture" },
{
subject: {
path: fixture.path,
sha256: hash(fixture.original),
format: "file",
},
rawResult: fixture.raw,
},
);
const result = await new FirmwareAnalysisService({
execute: async () => ok(execution),
}).execute("extract_firmware", {
path: fixture.path,
range: { offset: 7, length: fixture.context.length },
output_directory: output,
});
if (!result.ok) throw result.error;
expect(result.value.normalized_result).toHaveProperty(
"extraction_gaps",
published.extraction_gaps,
);
expect(result.value.normalized_result).toHaveProperty(
"extraction_continuations",
published.extraction_continuations,
);
expect(
(await readFile(join(output, "child.bin"))).equals(fixture.child),
).toBe(true);
expect((await readFile(fixture.path)).equals(fixture.original)).toBe(true);
expect(result.value.raw_result).toEqual(fixture.raw);
return { value: result.value, published };
} finally {
await files.close();
}
};
it.each(cases)(
"retains $name coverage and child-relative gaps in service Evidence",
async (selection) => {
const fixture = await capture(selection);
const result = await evidence(fixture);
expect(result.value.normalized_result).toMatchObject({
coverage: selection.coverage,
});
const implicit = result.published.extraction_gaps.filter(
(gap) => gap.kind === "unclassified-range",
);
expect(implicit).toMatchObject(
selection.gaps.map(([offset, length]) => ({
input_path: "$output/child.bin",
range: { offset, length },
root_file_range: null,
})),
);
expect(implicit).toHaveLength(selection.gaps.length);
if ("unknown" in selection)
expect(result.published.extraction_gaps).toMatchObject([
{
kind: "unknown-chunk-handler",
input_path: "$output/child.bin",
range: { offset: 0, length: 6 },
root_file_range: null,
},
]);
if (selection.gaps.length > 0)
for (const continuation of result.published.extraction_continuations)
expect(continuation.instruction).not.toContain("was carved");
for (const gap of result.published.extraction_gaps) {
expect(result.published.extraction_continuations).toContainEqual({
id: gap.continuation_id,
instruction: expect.stringContaining("relative to the published child"),
});
}
},
);