fix(firmware): validate Intel HEX start-record offsets (#7806)

This commit is contained in:
ShuaixinHuang authored and GitHub committed 2026-10-29 07:37:39 +08:00
1 parent c2cc7e6eb0
commit 9ac9f91ab5
3 files changed
+62 -2

No files matched your search

+2 -2
View File
@@ -135,8 +135,8 @@ const parseIntelRecord = (line: Uint8Array): Result<HexRecord, string> => {
`record type ${type} requires ${String(fixed)} data bytes, found ${String(count)}`,
);
const address = readBigEndian(bytes.subarray(1, 3));
// Extended address records set the base; their address field must be 0000.
if ((typeCode === 2 || typeCode === 4) && address !== 0)
// Extended/start address records reserve this field; their values are in data.
if (typeCode >= 2 && address !== 0)
return err(
`record type ${type} requires address 0x0000, found 0x${hex(address, 4)}`,
);
+35
View File
@@ -398,3 +398,38 @@ describe("hex record recognition", () => {
expect(detectHexRecordEncoding(Buffer.from(text))).toBe(expected);
});
});
it.each([3, 5])(
"rejects a nonzero reserved offset in Intel HEX start record %i",
(type) => {
const text = [
intelHexRecord(0, 0x20, [0xa5]),
intelHexRecord(type, 0x1234, [0, 0, 0, 1]),
intelHexRecord(1, 0),
].join("\n");
expect(decode(text)).toMatchObject({
ok: false,
error: { kind: "format" },
});
},
);
it("keeps data offsets, start payloads and the ignored EOF offset distinct", () => {
const parsed = image(
[
intelHexRecord(0, 0x1234, [0xa5]),
intelHexRecord(3, 0, [0x10, 0, 0x12, 0x34]),
intelHexRecord(5, 0, [0x12, 0x34, 0x56, 0x78]),
intelHexRecord(1, 0x1234),
].join("\n"),
);
expect(parsed.metadata).toMatchObject({
start_segment_cs: 0x1000,
start_segment_ip: 0x1234,
start_address: 0x12345678,
});
expect(parsed.terminated).toBe(true);
expect(parsed.regions).toMatchObject([
{ start: 0x1234, end: 0x1234, bytes: Uint8Array.of(0xa5) },
]);
});
+25
View File
@@ -5,6 +5,7 @@ import { cliTest } from "../support/cli/cliFixture.js";
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
import {
INTEL_HEX_I32_GAP,
intelHexRecord,
SREC_S19,
} from "../../src/domain/firmware/hexRecords.fixture.js";
import { parseEvidence } from "../../src/domain/evidence.js";
@@ -101,3 +102,27 @@ cliTest("rejects a malformed record through the CLI", async ({ cli }) => {
"Intel HEX is malformed: line 4: record type 00 checksum 0xc4 does not match computed 0xc3",
);
});
cliTest.for([3, 5])(
"rejects reserved offsets in Intel HEX start record %i through the CLI",
async (type, { cli }) => {
const directory = await createTestTempDirectory("rea-hex-start-cli-");
const source = join(directory, "firmware.hex");
await writeFile(
source,
[
intelHexRecord(0, 0x20, [0xa5]),
intelHexRecord(type, 0x1234, [0, 0, 0, 1]),
intelHexRecord(1, 0),
].join("\n"),
);
const result = await cli.run({
arguments: ["inspect-artifact", source, "--json"],
});
expect(result.exitCode).toBe(1);
expect(result.json).toMatchObject({
code: "artifact_operation_failed",
details: { operation: "inspect_artifact", reason: "format" },
});
},
);