mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 17:59:08 +00:00
feat(settings): read per-call REA_ limits from the operation snapshot
Part of #9881. Move the limits checked on each call into update_analysis_settings, keep their REA_ seeds and bounds, and reject updates outside the allowed range.
This commit is contained in:
1 parent
9924bf3445
commit
b0541c80b3
34 files changed
+704
-254
No files matched your search
@@ -1,5 +1,11 @@
|
||||
import { expect, it } from "vitest";
|
||||
import { AnalysisSettings } from "./AnalysisSettings.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import {
|
||||
applyWindowsChangeTimeSnapshot,
|
||||
resolveWindowsChangeTimeSettle,
|
||||
} from "../config/windowsChangeTimeSettle.js";
|
||||
import { pwntoolsInputBytes } from "../native/pwntools/PwntoolsInputLimit.js";
|
||||
import {
|
||||
runtimeAnalysisConfig,
|
||||
runtimeAsarHeaderAdmission,
|
||||
@@ -159,7 +165,7 @@ it("exposes shared provider controls and preserves the explicit unbounded decomp
|
||||
store
|
||||
.inspect({ provider: "ghidra", operation: "search_strings" })
|
||||
.settings.map(({ setting }) => setting),
|
||||
).toEqual(["ghidra.startup_timeout_ms"]);
|
||||
).toEqual(["ghidra.startup_timeout_ms", "bridge.max_request_bytes"]);
|
||||
expect(
|
||||
store
|
||||
.inspect({ provider: "ida", operation: "search_strings" })
|
||||
@@ -169,7 +175,13 @@ it("exposes shared provider controls and preserves the explicit unbounded decomp
|
||||
store
|
||||
.inspect({ operation: "inventory_artifact" })
|
||||
.settings.map(({ setting }) => setting),
|
||||
).toEqual(["asar.max_listing_bytes", "asar.max_header_bytes"]);
|
||||
).toEqual([
|
||||
"asar.max_listing_bytes",
|
||||
"asar.max_header_bytes",
|
||||
"windows.change_time_drift_ms",
|
||||
"windows.change_time_settle_poll_ms",
|
||||
"windows.change_time_settle_max_polls",
|
||||
]);
|
||||
expect(
|
||||
store.update({
|
||||
changes: [
|
||||
@@ -217,3 +229,73 @@ it("exposes shared provider controls and preserves the explicit unbounded decomp
|
||||
).toBe(true);
|
||||
expect(config.ghidraDecompileTimeoutSeconds).toBe(7);
|
||||
});
|
||||
|
||||
it("rejects an out-of-range per-call limit and reads an accepted value from the operation snapshot", () => {
|
||||
const store = new AnalysisSettings({});
|
||||
const rejected = store.update({
|
||||
changes: [
|
||||
{ setting: "windows.change_time_drift_ms", action: "set", value: 0 },
|
||||
],
|
||||
});
|
||||
expect(rejected.ok).toBe(false);
|
||||
if (!rejected.ok)
|
||||
expect(projectAnalysisError(rejected.error)).toMatchObject({
|
||||
code: "invalid_request",
|
||||
});
|
||||
expect(
|
||||
store.update({
|
||||
changes: [
|
||||
{ setting: "bridge.max_request_bytes", action: "set", value: 1 },
|
||||
],
|
||||
}).ok,
|
||||
).toBe(false);
|
||||
expect(
|
||||
store.update({
|
||||
changes: [
|
||||
{
|
||||
setting: "windows.change_time_settle_max_polls",
|
||||
action: "set",
|
||||
value: 1001,
|
||||
},
|
||||
],
|
||||
}).ok,
|
||||
).toBe(false);
|
||||
const accepted = store.update({
|
||||
changes: [
|
||||
{ setting: "windows.change_time_drift_ms", action: "set", value: 5000 },
|
||||
{ setting: "pwntools.max_input_bytes", action: "set", value: 65536 },
|
||||
{ setting: "bridge.max_request_bytes", action: "set", value: 33554432 },
|
||||
],
|
||||
});
|
||||
expect(accepted.ok).toBe(true);
|
||||
if (!accepted.ok) return;
|
||||
expect(accepted.value).toMatchObject({
|
||||
effect: "immediate",
|
||||
rea_restart_required: false,
|
||||
});
|
||||
const parsed = parseConfig({});
|
||||
if (!parsed.ok) throw parsed.error;
|
||||
const live = runtimeAnalysisConfig(parsed.value, store.read);
|
||||
store.run(() => {
|
||||
const windows = resolveWindowsChangeTimeSettle({});
|
||||
if (!windows.ok) throw windows.error;
|
||||
expect(applyWindowsChangeTimeSnapshot(windows.value)).toMatchObject({
|
||||
driftMs: 5000,
|
||||
driftSource: "runtime",
|
||||
pollSource: "default",
|
||||
});
|
||||
expect(pwntoolsInputBytes({})).toMatchObject({
|
||||
configured: true,
|
||||
bytes: 65536,
|
||||
source: "runtime",
|
||||
});
|
||||
expect(live.bridgeMaxRequestBytes).toMatchObject({
|
||||
maximumBytes: 33554432,
|
||||
source: "runtime",
|
||||
});
|
||||
});
|
||||
expect(pwntoolsInputBytes({})).toMatchObject({
|
||||
bytes: 32 * 1024 * 1024,
|
||||
source: "default",
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { runWithAnalysisOperationSnapshot } from "../domain/analysisOperationSnapshot.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import { launchAnalysisSetting } from "../config/analysisSettings.js";
|
||||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
@@ -42,7 +43,9 @@ export class AnalysisSettings {
|
||||
readonly read = (): AnalysisSettingsSnapshot =>
|
||||
this.#accepted.getStore() ?? this.#current;
|
||||
run<Value>(operation: () => Value): Value {
|
||||
return this.#accepted.run(this.#current, operation);
|
||||
return this.#accepted.run(this.#current, () =>
|
||||
runWithAnalysisOperationSnapshot(this.#current, operation),
|
||||
);
|
||||
}
|
||||
inspect(input: z.infer<typeof inspectAnalysisSettingsInputSchema> = {}) {
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user