fix(native): refuse truncated executable headers at target admission

Target admission accepted a thin Mach-O after reading only its magic and
CPU type, so a 12-byte prefix opened as a valid arm64 executable and the
first provider query failed as a generic execution failure. ELF headers
were likewise accepted after 20 bytes, and a FAT file whose selected slice
lies beyond its end was admitted.

Require the complete fixed header (Mach-O 28 or 32 bytes, ELF 52 or 64),
Mach-O load commands that fit in the file, and a selected FAT slice within
the file, checking commitments against the file size rather than the
probed prefix. Each refusal names the failed constraint.

Fixes #1189

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822andClaude Opus 5.5 committed 2026-10-09 03:51:37 +00:00
1 parent e1afbc1914
commit 0b04d384cc
6 files changed
+137 -20

No files matched your search

+4 -2
View File
@@ -4,7 +4,7 @@ export const elf = (
endian: number,
machine: number,
): Buffer => {
const bytes = Buffer.alloc(20);
const bytes = Buffer.alloc(class_ === 1 ? 52 : 64);
bytes.set([0x7f, 0x45, 0x4c, 0x46, class_, endian]);
if (endian === 1) bytes.writeUInt16LE(machine, 18);
else bytes.writeUInt16BE(machine, 18);
@@ -13,7 +13,9 @@ export const elf = (
/** Build a minimal thin Mach-O header for binary-target parser tests. */
export const thinMach = (magic: number, cpu: number): Buffer => {
const bytes = Buffer.alloc(8);
const bytes = Buffer.alloc(
magic === 0xfeedfacf || magic === 0xcffaedfe ? 32 : 28,
);
bytes.writeUInt32BE(magic, 0);
if (magic === 0xcefaedfe || magic === 0xcffaedfe) bytes.writeUInt32LE(cpu, 4);
else bytes.writeUInt32BE(cpu, 4);