fix(il2cpp): deduplicate aliased registration fields

Fixes #6715
This commit is contained in:
morluto
2026-10-23 21:13:51 +08:00
parent 4f0c33e8c4
commit f40bd0c4fb
3 changed files with 22 additions and 1 deletions
+6 -1
View File
@@ -209,6 +209,7 @@ export function* findCodeRegistration(
const expected = new Set(modules.map((module) => module.address));
const total = BigInt(modules.length);
const matches: { field: bigint; array: bigint }[] = [];
const matchedFields = new Set<bigint>();
for (const mapping of image.container.mappings) {
const start = Number((8n - (mapping.address % 8n)) % 8n);
for (let at = start; at + 16 <= mapping.size; at += 8) {
@@ -225,12 +226,16 @@ export function* findCodeRegistration(
seen.add(pointer);
}
if (seen.size === modules.length) {
const field = mapping.address + BigInt(at);
// Exact load aliases can visit one virtual registration field twice.
if (matchedFields.has(field)) continue;
matchedFields.add(field);
if (matches.length !== 0)
throw new Il2cppBinaryFormatFailure(
"code-registration-not-found",
"multiple CodeRegistration module tables match",
);
matches.push({ field: mapping.address + BigInt(at), array });
matches.push({ field, array });
}
}
}
@@ -114,6 +114,16 @@ it.each([
},
);
it("still rejects distinct CodeRegistration module table fields", () => {
expect(
failure(
createElfFixture(
createIl2cppBinaryFixture({ duplicateCodeRegistration: true }),
),
),
).toEqual({ reason: "code-registration-not-found", kind: "malformed" });
});
it("rejects reused MethodDef tokens within an image but preserves cross-image reuse and folded addresses", () => {
const duplicateTokens = Uint32Array.from(facts.methodTokens);
duplicateTokens[1] = duplicateTokens[0]!;
+6
View File
@@ -25,6 +25,8 @@ export interface Il2cppBinaryFixtureOptions {
readonly chainedFixups?: boolean;
/** Omit the CodeRegistration module count and array pointer. */
readonly codeRegistration?: boolean;
/** Write a second distinct CodeRegistration module count and array pair. */
readonly duplicateCodeRegistration?: boolean;
/** Write a RIP-relative `lea rax, [module array]`, as an inlined build loads it. */
readonly codeReference?: boolean;
/** Omit the MetadataRegistration type table. */
@@ -125,6 +127,10 @@ export const createIl2cppBinaryFixture = (
if (options.codeRegistration !== false) {
bytes.writeBigUInt64LE(2n, REGISTRATION);
bytes.writeBigUInt64LE(address(MODULE_ARRAY), REGISTRATION + 8);
if (options.duplicateCodeRegistration === true) {
bytes.writeBigUInt64LE(2n, REGISTRATION + 0x80);
bytes.writeBigUInt64LE(address(MODULE_ARRAY), REGISTRATION + 0x88);
}
}
// Il2CppType records: 8-byte data, then attrs:16 and type:8 bits.
const types: readonly [kind: number, data: bigint][] = [