mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 09:52:27 +00:00
fix(limits): carry runtime ceilings into Hopper and pwntools recovery
A runtime bridge ceiling is injected into the Hopper bootstrap. Pwntools input-limit guidance names the layer that selected the ceiling.
This commit is contained in:
1 parent
b9be864801
commit
57dd7f26b1
4 files changed
+88
-3
No files matched your search
@@ -671,7 +671,7 @@ export const bridgeBootstrapSource = (
|
||||
): string => {
|
||||
const limit = options.bridgeMaxRequestBytes;
|
||||
const injectedLimit =
|
||||
limit?.source === "setting" &&
|
||||
(limit?.source === "setting" || limit?.source === "runtime") &&
|
||||
Number.isSafeInteger(limit.maximumBytes) &&
|
||||
limit.maximumBytes >= MINIMUM_BRIDGE_MAX_REQUEST_BYTES &&
|
||||
limit.maximumBytes <= MAXIMUM_BRIDGE_MAX_REQUEST_BYTES
|
||||
|
||||
@@ -39,3 +39,16 @@ it("injects a caller-selected ceiling before the bridge is executed", () => {
|
||||
expect(injected).toBeGreaterThanOrEqual(0);
|
||||
expect(injected).toBeLessThan(source.indexOf("exec(compile"));
|
||||
});
|
||||
|
||||
it("injects a runtime ceiling before the bridge is executed", () => {
|
||||
const source = bridgeBootstrapSource(
|
||||
session,
|
||||
{
|
||||
...options,
|
||||
bridgeMaxRequestBytes: { maximumBytes: 65_536, source: "runtime" },
|
||||
},
|
||||
true,
|
||||
"/target",
|
||||
);
|
||||
expect(source).toContain("REA_BRIDGE_MAX_REQUEST_BYTES = 65536");
|
||||
});
|
||||
@@ -56,7 +56,46 @@ it("keeps the caller-selected pwntools input-limit source", () => {
|
||||
source: "request",
|
||||
update_mode: "parameter",
|
||||
pending_restart: false,
|
||||
parameter: "producer_limits.input_bytes",
|
||||
});
|
||||
expect(projected.remediation.action).toContain(
|
||||
"producer_limits.input_bytes is 4096 bytes",
|
||||
);
|
||||
expect(projected.remediation.action).not.toContain("launch default of");
|
||||
});
|
||||
|
||||
it("names a runtime pwntools ceiling instead of the built-in default", () => {
|
||||
const projected = projectAnalysisError(
|
||||
pwntoolsDecoderFailure(
|
||||
new ArtifactReaderFailure(
|
||||
"limit",
|
||||
"artifact exceeds the input allowance",
|
||||
{},
|
||||
),
|
||||
"artifact-read",
|
||||
"/selected",
|
||||
"/python",
|
||||
{},
|
||||
{
|
||||
operation: "inspect_binary_layout",
|
||||
providerId: "pwntools",
|
||||
producerLimits: resolvePwntoolsLimits(undefined, 67_108_864),
|
||||
inputBytesSource: "runtime",
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(projected.details?.limit).toMatchObject({
|
||||
effective_value: 67_108_864,
|
||||
source: "runtime",
|
||||
update_mode: "runtime",
|
||||
});
|
||||
expect(projected.remediation.action).toContain(
|
||||
"67108864 bytes (source runtime)",
|
||||
);
|
||||
expect(projected.remediation.action).toContain("update_analysis_settings");
|
||||
expect(projected.message).not.toContain(
|
||||
"Selected producer_limits.input_bytes is",
|
||||
);
|
||||
});
|
||||
|
||||
it("distinguishes the wall deadline from caller-selected producer resource budgets", () => {
|
||||
|
||||
@@ -53,6 +53,36 @@ export interface PwntoolsFailureContext {
|
||||
| undefined;
|
||||
}
|
||||
|
||||
const pwntoolsInputLimitFact = (
|
||||
bytes: number,
|
||||
source: PwntoolsFailureContext["inputBytesSource"],
|
||||
): string => {
|
||||
const effective = String(bytes);
|
||||
if (source === "request")
|
||||
return `Selected producer_limits.input_bytes is ${effective} bytes.`;
|
||||
if (source === "runtime")
|
||||
return `The runtime pwntools.max_input_bytes ceiling is ${effective} bytes.`;
|
||||
if (source === "setting")
|
||||
return `REA_PWNTOOLS_MAX_INPUT_BYTES selected ${effective} bytes.`;
|
||||
return `The launch default pwntools.max_input_bytes ceiling is ${effective} bytes.`;
|
||||
};
|
||||
|
||||
const pwntoolsInputLimitRecovery = (
|
||||
bytes: number,
|
||||
source: PwntoolsFailureContext["inputBytesSource"],
|
||||
): string => {
|
||||
const effective = String(bytes);
|
||||
const shared =
|
||||
"CPU, memory, output and transport allowances remain independent.";
|
||||
if (source === "request")
|
||||
return `producer_limits.input_bytes is ${effective} bytes for this call. Raise it on the next call (CLI --producer-limits JSON). ${shared}`;
|
||||
if (source === "runtime")
|
||||
return `pwntools.max_input_bytes is ${effective} bytes (source runtime) and can be changed with update_analysis_settings. The launch seed is REA_PWNTOOLS_MAX_INPUT_BYTES. producer_limits.input_bytes overrides that ceiling on the next call. ${shared}`;
|
||||
if (source === "setting")
|
||||
return `REA_PWNTOOLS_MAX_INPUT_BYTES is ${effective} bytes (source setting). Change pwntools.max_input_bytes with update_analysis_settings, or set producer_limits.input_bytes on the next call. The built-in default is ${String(PWNTOOLS_LIMITS.input_bytes)} bytes. ${shared}`;
|
||||
return `pwntools.max_input_bytes is the launch default of ${effective} bytes and can be changed with update_analysis_settings. The launch seed is REA_PWNTOOLS_MAX_INPUT_BYTES. producer_limits.input_bytes overrides that default on the next call. ${shared}`;
|
||||
};
|
||||
|
||||
/** Recovery identifies the selected controls rather than unrelated wall deadlines. */
|
||||
export const pwntoolsBudgetRecovery = (
|
||||
limits: PwntoolsProducerLimits = resolvePwntoolsLimits(),
|
||||
@@ -302,8 +332,11 @@ const classifyPwntoolsDecoderFailure = (
|
||||
...stableArtifactInputRecovery(cause),
|
||||
...(cause.reason === "limit"
|
||||
? {
|
||||
userMessage: `${cause.message} Selected producer_limits.input_bytes is ${String(limits.input_bytes)} bytes. ${budgetRecovery}`,
|
||||
remediationAction: `pwntools.max_input_bytes is the launch default of ${String(PWNTOOLS_LIMITS.input_bytes)} bytes and can be changed at runtime with update_analysis_settings. The launch seed is REA_PWNTOOLS_MAX_INPUT_BYTES. producer_limits.input_bytes overrides that default on the next call (CLI --producer-limits JSON). The effective input_bytes for this call is ${String(limits.input_bytes)}. CPU, memory, output and transport allowances remain independent.`,
|
||||
userMessage: `${cause.message} ${pwntoolsInputLimitFact(limits.input_bytes, context.inputBytesSource)} ${budgetRecovery}`,
|
||||
remediationAction: pwntoolsInputLimitRecovery(
|
||||
limits.input_bytes,
|
||||
context.inputBytesSource,
|
||||
),
|
||||
limit: analysisSettingLimit(
|
||||
"pwntools.max_input_bytes",
|
||||
limits.input_bytes,
|
||||
|
||||
Reference in new issue
Block a user