fix(firmware): reject malformed UTF-8 producer reports
This commit is contained in:
parent
2b86ea9c7c
commit
4a45c14742
|
|
@ -129,8 +129,9 @@ tree semantics, vulnerability scanning, emulation or hardware runtime capture.
|
|||
Unblob one worker. No automatic parallel extraction engines.
|
||||
- **120-second** deadline; inherited **1 GiB per-process address-space** limit,
|
||||
120 CPU seconds and zero core-dump allowance through `prlimit`.
|
||||
- JSON reports: at most **8 MiB**; oversized reports fail without a truncated
|
||||
success. Diagnostic output is bounded with exact captured byte counts.
|
||||
- JSON reports: at most **8 MiB** and valid UTF-8; malformed encoding and
|
||||
oversized reports fail without repairing or truncating producer data.
|
||||
Diagnostic output is bounded with exact captured byte counts.
|
||||
- Default staging budget: **256 MiB** and **10,000 entries**, configurable using
|
||||
`max_output_bytes` / `max_output_files` (CLI `--max-output-bytes` /
|
||||
`--max-output-files`). Depth defaults to 3, allowed range 1–10.
|
||||
|
|
|
|||
|
|
@ -153,7 +153,11 @@ export const readFirmwareReport = async (
|
|||
`Report exceeded ${FIRMWARE_LIMITS.reportBytes} bytes`,
|
||||
);
|
||||
try {
|
||||
const value: unknown = JSON.parse(bytes.toString("utf8"));
|
||||
const value: unknown = JSON.parse(
|
||||
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
||||
bytes,
|
||||
),
|
||||
);
|
||||
return value;
|
||||
} catch (cause: unknown) {
|
||||
throw new AnalysisOutputError(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
import { writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { readFirmwareReport } from "../../../src/firmware/FirmwareFiles.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
it.each([
|
||||
["invalid leading byte", [0xff]],
|
||||
["incomplete sequence", [0xe2, 0x82]],
|
||||
["overlong sequence", [0xc0, 0xaf]],
|
||||
["encoded surrogate", [0xed, 0xa0, 0x80]],
|
||||
])(
|
||||
"rejects complete JSON containing %s without repairing producer bytes",
|
||||
async (_name, bytes) => {
|
||||
const root = await createTestTempDirectory("rea-firmware-report-");
|
||||
const path = join(root, "report.json");
|
||||
await writeFile(
|
||||
path,
|
||||
Buffer.concat([
|
||||
Buffer.from('{"description":"'),
|
||||
Buffer.from(bytes),
|
||||
Buffer.from('"}'),
|
||||
]),
|
||||
);
|
||||
await expect(
|
||||
readFirmwareReport(path, "inspect_firmware_regions"),
|
||||
).rejects.toMatchObject({
|
||||
_tag: "AnalysisOutputError",
|
||||
reason: "Tool report is not valid complete JSON",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("preserves valid Unicode and a literal replacement character in producer JSON", async () => {
|
||||
const root = await createTestTempDirectory("rea-firmware-report-");
|
||||
const path = join(root, "report.json");
|
||||
const report = { description: "固件 🧩 \ufffd", path: "/输入/firmware.bin" };
|
||||
await writeFile(path, JSON.stringify(report));
|
||||
expect(await readFirmwareReport(path, "inspect_firmware_regions")).toEqual(
|
||||
report,
|
||||
);
|
||||
});
|
||||
Loading…
Reference in New Issue