diff --git a/docs/binary-diagnostics.md b/docs/binary-diagnostics.md index 9820f3bcb..fc110b685 100644 --- a/docs/binary-diagnostics.md +++ b/docs/binary-diagnostics.md @@ -181,7 +181,8 @@ payload ranges are supported. The supported tree has three levels: type, name, and language. Other resource payload formats remain opaque. `max_file_bytes` defaults to 64 MiB (maximum 512 MiB); `max_entries` defaults to -4096 (maximum 65536). CLI options are `--max-file-bytes` and `--max-entries`. +16384, the largest stock Windows resource image measured with headroom +(maximum 65536). CLI options are `--max-file-bytes` and `--max-entries`. Metadata is bounded to 8 MiB; exceeding any budget fails without truncation. Large Evidence envelopes may require a caller-configured MCP transport receive buffer because envelope copies add overhead. Requests honor cancellation during diff --git a/src/domain/native/peResources.ts b/src/domain/native/peResources.ts index 977ac36ad..80fcc80bb 100644 --- a/src/domain/native/peResources.ts +++ b/src/domain/native/peResources.ts @@ -22,12 +22,17 @@ export const inspectPeResourcesInputSchema = z.strictObject({ .max(536870912) .default(67108864) .describe("Maximum stable artifact bytes to read (default 64 MiB)"), + // Windows resource images carry thousands of entries: Windows 11 25H2 + // SystemResources measures imageres.dll.mun at 6476 examined entries, + // shell32.dll.mun at 5903 and wmploc.DLL.mun at 5440. The default admits + // those stock images with headroom; the independent 8 MiB metadata budget + // still bounds allocation. max_entries: z .number() .int() .min(1) .max(65536) - .default(4096) + .default(16384) .describe( "Maximum resource directory entries to examine; exceeding the budget fails without partial success", ), diff --git a/src/native/pe/PeResources.fixture.ts b/src/native/pe/PeResources.fixture.ts index 803ae3377..d50136e29 100644 --- a/src/native/pe/PeResources.fixture.ts +++ b/src/native/pe/PeResources.fixture.ts @@ -37,6 +37,7 @@ export const peResourceFixture = ( { type: 10, name: 7, language: 1041, payload: Buffer.from("World") }, { type: 14, name: 42, language: 1033, payload: iconGroup() }, ], + sectionBytes = 65536, ) => { const tree: Tree = { children: new Map() }; for (const resource of resources) { @@ -58,7 +59,7 @@ export const peResourceFixture = ( if ("children" in child.value) parent = child.value; } } - const section = Buffer.alloc(65536); + const section = Buffer.alloc(sectionBytes); let cursor = 0; const allocate = (size: number, alignment = 4): number => { cursor = Math.ceil(cursor / alignment) * alignment; diff --git a/tests/boundary/filesystem/peResources.test.ts b/tests/boundary/filesystem/peResources.test.ts index 5196f3949..70ae2b4f2 100644 --- a/tests/boundary/filesystem/peResources.test.ts +++ b/tests/boundary/filesystem/peResources.test.ts @@ -58,4 +58,40 @@ describe("PE resource stable filesystem boundary", () => { if (result.ok) throw new Error("Expected cancellation"); expect(result.error._tag).toBe("AnalysisCancelledError"); }); + + it("admits the largest measured stock Windows resource table by default", async () => { + // Windows 11 25H2 SystemResources measures imageres.dll.mun at 6476 + // examined entries; the default budget must admit real system images, not + // only small fixtures. Two types with 1620 and 1617 one-language names + // examine 2 + 2 * 3237 entries. + const resources = [ + ...Array.from({ length: 1620 }, (_unused, index) => ({ + type: 10, + name: index + 1, + language: 1033, + payload: Buffer.from([index % 256]), + })), + ...Array.from({ length: 1617 }, (_unused, index) => ({ + type: 3, + name: index + 1, + language: 1033, + payload: Buffer.from([index % 256]), + })), + ]; + const root = await createTestTempDirectory("rea-pe-resource-stock-scale-"); + const path = join(root, "image.exe"); + await writeFile(path, peResourceFixture(false, resources, 262144).bytes); + const result = await createPeResourcesService().inspect({ path }); + if (!result.ok) + throw new Error( + `Expected the default budgets to admit the image: ${result.error.message}`, + ); + expect(result.value.normalized_result).toMatchObject({ + coverage: { + status: "complete", + examined_entries: 6476, + resources: 3237, + }, + }); + }); });