mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 11:13:21 +00:00
fix(ida): report the regex syntax error for invalid search patterns (#9544)
IDA checks a regex search pattern before it starts the provider. That early check returned a generic "Supply a valid regular expression." issue, so IDA callers never saw the parser explanation or the literal-mode recovery that the shared regex worker gives Kuna and Hopper callers. Build both refusals with one helper in RegexMatcher.
This commit is contained in:
3 files changed
+48
-28
No files matched your search
+6
-7
@@ -2,6 +2,7 @@ import { TOOL_CONTRACTS } from "../contracts/toolContracts.js";
|
||||
import { AnalysisInputError } from "../domain/analysisErrorCore.js";
|
||||
import { jsonObjectSchema, type JsonValue } from "../domain/jsonValue.js";
|
||||
import { err, ok } from "../domain/result.js";
|
||||
import { invalidRegexPatternError } from "../process/RegexMatcher.js";
|
||||
import { idaAddressSchema } from "./IdaProtocolValues.js";
|
||||
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
||||
|
||||
@@ -65,13 +66,11 @@ export const parseIdaInput = (
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
return err(
|
||||
new AnalysisInputError(operation, { cause }, [
|
||||
{
|
||||
path: ["pattern"],
|
||||
reason: "invalid_format",
|
||||
message: "Supply a valid regular expression.",
|
||||
},
|
||||
]),
|
||||
invalidRegexPatternError(
|
||||
operation,
|
||||
cause instanceof Error ? cause.message : String(cause),
|
||||
cause,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,10 +662,26 @@ describe("attached IDA function observations", () => {
|
||||
const found = await client.execute("search_strings", { pattern, mode });
|
||||
expect(found.ok && found.value.result).toHaveLength(count);
|
||||
}
|
||||
expect(
|
||||
(await client.execute("search_strings", { pattern: "[", mode: "regex" }))
|
||||
.ok,
|
||||
).toBe(false);
|
||||
const invalid = await client.execute("search_strings", {
|
||||
pattern: "[",
|
||||
mode: "regex",
|
||||
});
|
||||
if (invalid.ok) throw new Error("Expected invalid-pattern refusal");
|
||||
expect(projectAnalysisError(invalid.error)).toMatchObject({
|
||||
code: "invalid_request",
|
||||
message: expect.stringContaining("Invalid regex pattern"),
|
||||
remediation: { action: expect.stringMatching(/pattern.*mode literal/u) },
|
||||
details: {
|
||||
operation: "search_strings",
|
||||
issues: [
|
||||
{
|
||||
path: ["pattern"],
|
||||
reason: "invalid_format",
|
||||
message: expect.stringContaining("Invalid regular expression"),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await client.close();
|
||||
});
|
||||
});
|
||||
|
||||
+22
-17
@@ -518,6 +518,27 @@ export const regexWorkerHeapError = (
|
||||
remediationAction: `${heapBound(heap, request)} Use update_analysis_settings with setting regex.worker_heap_request_mib to change the request for the next worker; launch heap flags can override it. Restart REA after changing --max-old-space-size or ${REGEX_WORKER_HEAP_REQUEST_SETTING} in the launch environment. A launch --max-old-space-size-percentage takes precedence over that flag in either order. Simplify the pattern or use literal mode.`,
|
||||
},
|
||||
);
|
||||
/**
|
||||
* A pattern the regex engine rejects. The caller sees the engine's syntax
|
||||
* error on `pattern` and can retry in literal mode. Providers that check the
|
||||
* pattern before starting share this result with the worker.
|
||||
*/
|
||||
export const invalidRegexPatternError = (
|
||||
operation: string,
|
||||
reason: string,
|
||||
cause?: unknown,
|
||||
): AnalysisInputError =>
|
||||
new AnalysisInputError(
|
||||
operation,
|
||||
{
|
||||
cause,
|
||||
userMessage: `Invalid regex pattern: ${reason}`,
|
||||
remediationAction:
|
||||
"Correct the pattern using the reported regex syntax error, or select mode literal to search for the text literally, then retry.",
|
||||
},
|
||||
[{ path: ["pattern"], reason: "invalid_format", message: reason }],
|
||||
);
|
||||
|
||||
const replySchema = z.discriminatedUnion("status", [
|
||||
z.strictObject({
|
||||
status: z.literal("matched"),
|
||||
@@ -621,23 +642,7 @@ export const matchRegexValues = async (input: {
|
||||
);
|
||||
if (reply.data.status === "invalid_pattern")
|
||||
return finish(
|
||||
err(
|
||||
new AnalysisInputError(
|
||||
input.operation,
|
||||
{
|
||||
userMessage: `Invalid regex pattern: ${reply.data.reason}`,
|
||||
remediationAction:
|
||||
"Correct the pattern using the reported regex syntax error, or select mode literal to search for the text literally, then retry.",
|
||||
},
|
||||
[
|
||||
{
|
||||
path: ["pattern"],
|
||||
reason: "invalid_format",
|
||||
message: reply.data.reason,
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
err(invalidRegexPatternError(input.operation, reply.data.reason)),
|
||||
);
|
||||
if (
|
||||
reply.data.indices.some(
|
||||
|
||||
Reference in new issue
Block a user