Files
reverse-engineering-anything/tests/boundary/filesystem/bunMetadataReadBudget.test.ts
T
8188497f13 feat(artifacts): inspect and extract Bun standalone module graphs (#6998)
* feat(artifacts): inventory and extract Bun standalone executable module graphs

Adds a Bun standalone artifact reader for Mach-O, PE, ELF and appended
trailers, supporting the 36-byte and 52-byte module record layouts. It
preserves module names, entry-point details and raw metadata, and
exposes contents, sourcemaps, bytecode and module-info as separate
entries for safe extraction without executing the binary. Parsing
rejects malformed or ambiguous graphs and enforces module-count,
retained-byte and expansion limits. Adds synthetic parser tests, CLI and
MCP coverage, agent skill guidance, and a verification script for
Bun-produced executables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix(artifacts): bound Bun section probes and reject truncated sections

Split Bun recognition into a bounded probe that reads only section
headers, length prefixes, and the Offsets/trailer suffix, and a single
payload load used by the reader. Inventory classification and extraction
admission no longer allocate the whole graph.

Match ELF `.bun` section names by comparing only the name bytes and
terminator, so many headers sharing one long name cost constant work each.
Reject sections whose declared extent ends past EOF instead of reading a
silently shortened window.

Launch Bun, Docker, and REA in the standalone verifier through the shared
owned verifier commands, and release the runtime root only after those
command families have settled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* style(artifacts): format Bun reader integration

* fix(contracts): describe static Bun inventory facts

* fix(artifacts): bound Bun metadata reads and combined path growth

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-29 22:31:50 +08:00

122 lines
4.1 KiB
TypeScript

import { open, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import {
BUN_TRAILER,
locateBunStandaloneGraph,
} from "../../../src/artifacts/bun/BunModuleGraphLayout.js";
import { decodeBunModuleGraph } from "../../../src/artifacts/bun/BunModuleGraphMembers.js";
import { elfAppendedBunPayload } from "../../../src/artifacts/bun/BunStandalone.fixture.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
it("keeps scattered tiny metadata reads proportional to the graph instead of cache pages", async () => {
const count = 200;
const tableAt = 6 * 65_536;
const data = Buffer.alloc(tableAt + count * 52);
for (let page = 0; page < 6; page++) data[page * 65_536 + 100] = 97;
for (let index = 0; index < count; index++) {
const row = data.subarray(tableAt + index * 52, tableAt + (index + 1) * 52);
for (const [field, page] of [
[0, (index * 3) % 6],
[8, (index * 3 + 1) % 6],
[40, (index * 3 + 2) % 6],
] as const) {
row.writeUInt32LE(page * 65_536 + 100, field);
row.writeUInt32LE(1, field + 4);
}
row[48] = 1;
row[49] = 1;
row[50] = 1;
}
const offsets = Buffer.alloc(32);
offsets.writeBigUInt64LE(BigInt(data.length));
offsets.writeUInt32LE(tableAt, 8);
offsets.writeUInt32LE(count * 52, 12);
const bytes = elfAppendedBunPayload(
Buffer.concat([data, offsets, BUN_TRAILER]),
);
const path = join(
await createTestTempDirectory("rea-bun-scattered-metadata-"),
"app",
);
await writeFile(path, bytes);
const handle = await open(path, "r");
const read = handle.read.bind(handle);
let bytesRead = 0;
const guard = bytes.length * 2;
const counted = new Proxy(handle, {
get: (target, key) =>
key === "read"
? async (...args: Parameters<typeof read>) => {
const result = await read(...args);
bytesRead += result.bytesRead;
if (bytesRead > guard)
throw new Error(
"Metadata read amplification crossed the owned test guard",
);
return result;
}
: Reflect.get(target, key),
});
try {
const located = await locateBunStandaloneGraph(counted, bytes.length);
if (located.status !== "present" || located.graph === undefined)
throw new Error("Missing graph");
const decoded = await decodeBunModuleGraph(located.graph);
expect(decoded.modules).toHaveLength(count);
expect(
decoded.modules.every((module) => module.nameText.text === "a"),
).toBe(true);
expect(bytesRead).toBeLessThan(guard);
} finally {
await handle.close();
}
});
it("refuses cumulative uncached metadata work before the next file read", async () => {
const rangeLength = 256 * 1024 + 1;
const data = Buffer.alloc(rangeLength);
const offsets = Buffer.alloc(32);
offsets.writeBigUInt64LE(BigInt(data.length));
const bytes = elfAppendedBunPayload(
Buffer.concat([data, offsets, BUN_TRAILER]),
);
const path = join(
await createTestTempDirectory("rea-bun-metadata-work-"),
"app",
);
await writeFile(path, bytes);
const handle = await open(path, "r");
let reads = 0;
const read = handle.read.bind(handle);
const counted = new Proxy(handle, {
get: (target, key) =>
key === "read"
? async (...args: Parameters<typeof read>) => {
reads++;
return read(...args);
}
: Reflect.get(target, key),
});
try {
const located = await locateBunStandaloneGraph(counted, bytes.length);
if (located.status !== "present" || located.graph === undefined)
throw new Error("Missing graph");
const graph = located.graph;
for (
let index = 0;
index < Math.floor((256 * 1024 * 1024) / rangeLength);
index++
)
await graph.data.read(0, rangeLength);
const admittedReads = reads;
await expect(graph.data.read(0, rangeLength)).rejects.toMatchObject({
reason: "limit",
boundary: "capacity",
});
expect(reads).toBe(admittedReads);
} finally {
await handle.close();
}
});