fix(il2cpp): reject module image references outside retained inventory (#8956)

This commit is contained in:
Jiabin Yin authored and GitHub committed 2026-11-05 18:33:36 +08:00
1 parent 4362a0848e
commit da79ea0baa
3 files changed
+103

No files matched your search

@@ -482,6 +482,34 @@ const linkedReport = (): Il2cppMetadata => ({
parameter_types: [{ type: 0, name: "int" }],
});
it.each([-1, 1, 99])(
"rejects imported code-generation module image reference %i",
(image) => {
const value = linkedReport();
value.binary!.code_gen_modules[0]!.image = image;
const parsed = il2cppMetadataParentSchema.safeParse(value);
expect(parsed.success).toBe(false);
if (!parsed.success)
expect(parsed.error.issues).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: ["binary", "code_gen_modules", 0, "image"],
}),
]),
);
for (const selection of [{}, { image_indices: [image] }]) {
const view = projectIl2cppMetadataView(parent(value, false), {
kind: "il2cpp-metadata",
collection: "code_gen_modules",
...selection,
offset: 0,
limit: 64,
});
expect(view.ok).toBe(false);
}
},
);
it("selects every folded method by numeric address with stable indices and both source identities", () => {
const source = parent(freezeJsonSnapshot(linkedReport()), true);
const view = projectIl2cppMetadataView(source, {
+8
View File
@@ -444,6 +444,14 @@ const validateMetadataFacts = (
"Type reference is outside the linked type table or names an unavailable type.",
});
});
report.binary?.code_gen_modules.forEach((row, index) => {
if (row.image >= report.images.length)
context.addIssue({
code: "custom",
path: ["binary", "code_gen_modules", index, "image"],
message: "Code-generation module image is outside the retained images.",
});
});
report.method_addresses?.forEach((row, index) => {
if (codeRowContradicts(row, report.binary?.image_base))
context.addIssue({
@@ -56,6 +56,73 @@ const parseMetadataSummary = (value: unknown) =>
parseEvidence(value).normalized_result,
);
cliTest(
"rejects out-of-range module image references through CLI and MCP",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-il2cpp-module-image-");
const path = join(root, "global-metadata.dat");
const binaryPath = join(root, "GameAssembly.dylib");
await writeFile(
path,
createLinkedIl2cppMetadataFixture({ version: 39 }).bytes,
);
await writeFile(binaryPath, createIl2cppBinaryFixture());
const produced = await runFileCli(cli, {
arguments: [
"inspect-il2cpp-metadata",
path,
"--binary",
binaryPath,
"--detail",
"complete",
"--json",
],
});
expect(produced.exitCode, produced.stderr).toBe(0);
const original = parseCliMetadata(produced.json);
expect(original.binary!.code_gen_modules.length).toBeGreaterThan(0);
const { call } = await connectLocalToolsMcp();
for (const image of [
0,
original.images.length - 1,
-1,
original.images.length,
99,
]) {
const report = structuredClone(original);
report.binary!.code_gen_modules[0]!.image = image;
const evidence = createEvidence(
{ path, format: "file", sha256: report.artifact.sha256 },
{ id: "il2cpp-metadata", name: "IL2CPP", version: "1" },
{
operation: "inspect_il2cpp_metadata",
parameters: { path },
result: report,
},
);
const request = {
source: { kind: "inline", evidence },
view: { kind: "il2cpp-metadata", collection: "code_gen_modules" },
};
const query = join(root, `image-${image}.json`);
await writeFile(query, JSON.stringify(request));
const result = await runFileCli(cli, {
arguments: ["inspect-analysis-view", query, "--json"],
});
const mcp = await call("inspect_analysis_view", request);
if (image >= 0 && image < original.images.length) {
expect(result.exitCode, result.stderr).toBe(0);
expect(mcp.isError, JSON.stringify(mcp)).not.toBe(true);
} else {
expect(result.exitCode, `image ${image}`).toBe(1);
expect(result.json).toMatchObject({ code: "invalid_request" });
expect(parseMcpToolError(mcp).error.code).toBe("invalid_request");
}
}
},
30000,
);
cliTest(
"rejects impossible imported metadata owners through CLI and MCP",
async ({ cli }) => {