From 44310bba32b02b7d88d3721341bcc88c27282d88 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:37:39 +0800 Subject: [PATCH] fix(il2cpp): validate selected FAT slice identity --- src/il2cpp/Il2cppBinaryImage.ts | 18 ++++++++---------- tests/boundary/il2cpp/il2cppBinaryFile.test.ts | 11 +++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/il2cpp/Il2cppBinaryImage.ts b/src/il2cpp/Il2cppBinaryImage.ts index abde218167..20cf05a953 100644 --- a/src/il2cpp/Il2cppBinaryImage.ts +++ b/src/il2cpp/Il2cppBinaryImage.ts @@ -1,6 +1,7 @@ import { classifyFatContainerEvidence, readFatContainerHeader, + readMachoHeaderPrefixFacts, validateFatSlice, } from "../domain/apple/machoContainer.js"; import { binaryMetadataArchitecture } from "../domain/binaryMetadataArchitecture.js"; @@ -77,10 +78,15 @@ const selectImage = ( "slice-not-found", `universal Mach-O holds ${available.join(", ")}, not ${architecture}`, ); - const issue = validateFatSlice(slice, bytes.length, fat.tableEnd); + const image = bytes.subarray(slice.offset, slice.offset + slice.size); + const embedded = readMachoHeaderPrefixFacts(image).identity; + const issue = + embedded === null + ? `FAT architecture ${slice.index} has a truncated Mach-O identity` + : validateFatSlice(slice, bytes.length, fat.tableEnd, embedded); if (issue !== null) throw new Il2cppBinaryFormatFailure("malformed-container", issue); - return bytes.subarray(slice.offset, slice.offset + slice.size); + return image; }; export interface NativeImage { @@ -118,14 +124,6 @@ export function* openImageSteps( ); throw cause; } - if ( - architecture !== undefined && - (container.format !== "macho" || container.architecture !== architecture) - ) - throw new Il2cppBinaryFormatFailure( - "malformed-container", - "Selected FAT declaration disagrees with the slice header architecture.", - ); if (container.bits !== 64 || container.byte_order !== "little") throw new Il2cppBinaryFormatFailure( "unsupported-container", diff --git a/tests/boundary/il2cpp/il2cppBinaryFile.test.ts b/tests/boundary/il2cpp/il2cppBinaryFile.test.ts index 96877525f8..c158bc44a0 100644 --- a/tests/boundary/il2cpp/il2cppBinaryFile.test.ts +++ b/tests/boundary/il2cpp/il2cppBinaryFile.test.ts @@ -1226,6 +1226,17 @@ it("checks the observed slice header against the caller-selected FAT architectur ]); expect(failure(bytes, "amd64").reason).toBe("malformed-container"); }); +it.each([1, 0x80000000])( + "checks the complete FAT CPU subtype including capability bits (%i)", + (subtype) => { + const thin = createIl2cppBinaryFixture(); + thin.writeUInt32LE(subtype, 8); + const bytes = createUniversalFixture([{ cpu: 0x0100000c, bytes: thin }]); + expect(failure(bytes, "arm64").reason).toBe("malformed-container"); + bytes.writeUInt32BE(subtype, 12); + expect(link(bytes, "arm64").method_addresses).toEqual(expectedAddresses); + }, +); it("still validates version 27 type indices when rendered names are unavailable", () => { const decoded = readIl2cppMetadataForLinking( createIl2cppMetadataFixture({ version: 27 }).bytes,