mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 00:07:18 +00:00
* test: focus configuration diagnostics on their owners Preserve shape errors, selected paths, recovery guidance, and unchanged-file behavior across parser, setup, and uninstall boundaries. * test: focus artifact and evidence checks on behavior Retain format, identity, malformed-input, and cleanup coverage while removing fixed prose and closing the admitted test source. * refactor(debugger): use configured session admission limits * test: focus evidence and diagnostics on behavior * fix(test): restore verifier export and formatting * test(config): verify debugger limit ranges * test(rizin): keep fixture executable authoritative * test(rizin): isolate debugger fixture environment
66 lines
2.7 KiB
TypeScript
66 lines
2.7 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { access, readFile } from "node:fs/promises";
|
|
import { promisify } from "node:util";
|
|
import { expect, it, onTestFinished } from "vitest";
|
|
import { AnalysisResourceConstraintError } from "../../src/domain/analysisErrorCore.js";
|
|
import { FIRMWARE_LIMITS } from "../../src/firmware/FirmwareRelease.js";
|
|
import { firmwareFileSizeService } from "../fixtures/firmware/fileSizeProducer.js";
|
|
import { assertFirmwareCleanup } from "../fixtures/firmware/provider.js";
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
const budget = 16 * 1024 * 1024;
|
|
|
|
// Lowers this isolated fork's soft RLIMIT_FSIZE to the staging budget, which
|
|
// removes the one byte of headroom the producer limit normally keeps.
|
|
it.skipIf(process.platform !== "linux")(
|
|
"rejects a staged file that reaches an inherited file-size ceiling",
|
|
async () => {
|
|
const limits = await readFile("/proc/self/limits", "utf8");
|
|
const soft = /^Max file size\s+(\S+)/mu.exec(limits)?.[1];
|
|
if (soft === undefined) throw new Error("No inherited file-size limit");
|
|
const setSoftLimit = async (value: string): Promise<void> => {
|
|
await execFileAsync("prlimit", [
|
|
"--pid",
|
|
String(process.pid),
|
|
`--fsize=${value}:`,
|
|
]);
|
|
};
|
|
await setSoftLimit(String(budget));
|
|
onTestFinished(() => setSoftLimit(soft));
|
|
const fixture = await firmwareFileSizeService({
|
|
attemptedBytes: budget + 4096,
|
|
probeFileBytes: FIRMWARE_LIMITS.reportBytes + 1,
|
|
extractionFileBytes: budget,
|
|
});
|
|
const outcome = await fixture.service.execute("extract_firmware", {
|
|
path: fixture.path,
|
|
output_directory: fixture.output,
|
|
max_output_bytes: budget,
|
|
});
|
|
expect(outcome).toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
_tag: "AnalysisResourceConstraintError",
|
|
resource: "file-size",
|
|
reportedLimits: { file_size_bytes: budget },
|
|
retryable: false,
|
|
},
|
|
});
|
|
if (outcome.ok) throw new Error("Expected a file-size refusal");
|
|
if (!(outcome.error instanceof AnalysisResourceConstraintError))
|
|
throw outcome.error;
|
|
// Inventory identifies the inherited ceiling and its recovery independently
|
|
// of the producer's SIGXFSZ guidance.
|
|
const recovery = outcome.error.remediationAction;
|
|
expect(recovery).toContain(String(budget));
|
|
expect(recovery).toMatch(/inherited.*file-size limit.*RLIMIT_FSIZE/iu);
|
|
expect(recovery).toMatch(/raise the file-size limit.*ulimit -f/iu);
|
|
expect(recovery).toMatch(/analysis_timeout_ms does not raise it/iu);
|
|
expect(recovery).toMatch(/unchanged request fails/iu);
|
|
await expect(access(fixture.output)).rejects.toMatchObject({
|
|
code: "ENOENT",
|
|
});
|
|
await assertFirmwareCleanup(fixture.launches);
|
|
},
|
|
);
|