mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(contracts): advertise NUL with a portable hex escape
Use the equivalent hex NUL spelling in named public contracts while preserving current path and reserved-name validation. Verify converted JSON Schema and real stdio catalog consumers. Closes #1329 Co-authored-by: Yi-111-a <97448247+Yi-111-a@users.noreply.github.com>
This commit is contained in:
1 parent
5f16124a31
commit
3f59a84bd1
7 files changed
+27
-18
No files matched your search
@@ -71,7 +71,7 @@ export const swiftSymbolsSchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
.regex(/^[^\n]*$/u, "Each Swift symbol must be one line.")
|
||||
.regex(/^[^\u0000]*$/u, "Swift symbols cannot contain NUL."),
|
||||
.regex(/^[^\x00]*$/u, "Swift symbols cannot contain NUL."),
|
||||
)
|
||||
.min(1);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
* patterns avoid look-around, which RE2 and Rust validators reject.
|
||||
*/
|
||||
const ROOT_RELATIVE_PATH =
|
||||
/^(?:[^\x2f\\\u0000.][^\x2f\\\u0000]*|\.[^\x2f\\\u0000.][^\x2f\\\u0000]*|\.\.[^\x2f\\\u0000]+)(?:\x2f(?:[^\x2f\\\u0000.][^\x2f\\\u0000]*|\.[^\x2f\\\u0000.][^\x2f\\\u0000]*|\.\.[^\x2f\\\u0000]+))*$/u;
|
||||
/^(?:[^\x2f\\\x00.][^\x2f\\\x00]*|\.[^\x2f\\\x00.][^\x2f\\\x00]*|\.\.[^\x2f\\\x00]+)(?:\x2f(?:[^\x2f\\\x00.][^\x2f\\\x00]*|\.[^\x2f\\\x00.][^\x2f\\\x00]*|\.\.[^\x2f\\\x00]+))*$/u;
|
||||
const rootRelativePathSchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
|
||||
@@ -81,7 +81,7 @@ export const electronActiveObservationInputSchema = z.strictObject({
|
||||
.array(
|
||||
z
|
||||
.string()
|
||||
.regex(/^[^\u0000]*$/u, "Electron arguments must not contain NUL"),
|
||||
.regex(/^[^\x00]*$/u, "Electron arguments must not contain NUL"),
|
||||
)
|
||||
.default([]),
|
||||
actions: z.array(actionSchema).default([]),
|
||||
|
||||
+10
-2
@@ -1,11 +1,19 @@
|
||||
import { isAbsolute, relative, sep } from "node:path";
|
||||
import { z } from "zod";
|
||||
|
||||
/** Preserve selected filesystem names while rejecting OS-invalid NUL bytes. */
|
||||
/**
|
||||
* Preserve selected filesystem names while rejecting OS-invalid NUL bytes.
|
||||
*
|
||||
* The pattern spells NUL as `\x00` rather than `\u0000`. Both accept exactly the
|
||||
* same strings. The hex form also avoids the short `\0` spelling rejected by
|
||||
* strict schema consumers. A client can reject its entire tool request when
|
||||
* one advertised pattern cannot compile. See `offsetDateTimeSchema` for the
|
||||
* same hex-escape convention.
|
||||
*/
|
||||
export const localPathStringSchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
.regex(/^[^\u0000]*$/u, "Local filesystem paths cannot contain NUL");
|
||||
.regex(/^[^\x00]*$/u, "Local filesystem paths cannot contain NUL");
|
||||
|
||||
/** Test lexical containment on the host platform; callers must resolve symlinks first. */
|
||||
export const isPathWithinRoot = (root: string, path: string): boolean => {
|
||||
|
||||
@@ -5,7 +5,7 @@ const hexSchema = z.string().regex(/^0x[0-9a-f]+$/u);
|
||||
const nativeString = z
|
||||
.string()
|
||||
.regex(
|
||||
/^[^\u0000]*$/u,
|
||||
/^[^\x00]*$/u,
|
||||
"Native launch and breakpoint strings cannot contain NUL",
|
||||
);
|
||||
/** Objective-C class names and selectors never contain spaces or brackets. */
|
||||
@@ -61,10 +61,8 @@ export const nativeCallObservationInputSchema = z.strictObject({
|
||||
z
|
||||
.string()
|
||||
.min(1)
|
||||
.regex(/^[^=\u0000]+$/u, "Environment names cannot contain '=' or NUL"),
|
||||
z
|
||||
.string()
|
||||
.regex(/^[^\u0000]*$/u, "Environment values cannot contain NUL"),
|
||||
.regex(/^[^=\x00]+$/u, "Environment names cannot contain '=' or NUL"),
|
||||
z.string().regex(/^[^\x00]*$/u, "Environment values cannot contain NUL"),
|
||||
)
|
||||
.default({})
|
||||
.describe("Overrides on top of the environment REA runs with."),
|
||||
|
||||
@@ -5,7 +5,7 @@ import { z } from "zod";
|
||||
const positiveBudget = z.number().int().safe().positive();
|
||||
const timedEventBase = { at_ms: z.number().int().safe().nonnegative() };
|
||||
const reservedRunIdEnvironmentName = "REA_PROCESS_RUN_ID";
|
||||
const ENVIRONMENT_NAME_CHARACTER = "[^=\\u0000]";
|
||||
const ENVIRONMENT_NAME_CHARACTER = "[^=\\x00]";
|
||||
|
||||
/**
|
||||
* Nonempty environment names other than the reserved run identifier. The
|
||||
@@ -20,7 +20,7 @@ const environmentNamePattern = (reserved: string): RegExp => {
|
||||
const character = reserved[index] ?? "";
|
||||
// Diverge here, match the next reserved character, or (after a nonempty
|
||||
// prefix) end the name early.
|
||||
const choice = `[^=\\u0000${character}]${ENVIRONMENT_NAME_CHARACTER}*|${character}${rest}`;
|
||||
const choice = `[^=\\x00${character}]${ENVIRONMENT_NAME_CHARACTER}*|${character}${rest}`;
|
||||
rest = index === 0 ? choice : `(?:${choice})?`;
|
||||
}
|
||||
return new RegExp(`^(?:${rest})$`, "u");
|
||||
@@ -38,7 +38,7 @@ const environmentName = z
|
||||
const childProcessString = z
|
||||
.string()
|
||||
.regex(
|
||||
/^[^\u0000]*$/u,
|
||||
/^[^\x00]*$/u,
|
||||
"Values passed to operating-system APIs cannot contain NUL",
|
||||
);
|
||||
export const normalizationSchema = z.object({
|
||||
|
||||
@@ -79,9 +79,12 @@ it("advertises portable NUL escapes and patterns that compile in all JS modes",
|
||||
).toEqual([]);
|
||||
|
||||
// DeepSeek rejects the short NUL escape even though V8 accepts it in all
|
||||
// three modes. Schema compilation must not hide that interchange failure.
|
||||
expect(patterns.filter(({ pattern }) => pattern.includes("\\0"))).toEqual([]);
|
||||
expect(patterns.some(({ pattern }) => pattern.includes("\\u0000"))).toBe(
|
||||
true,
|
||||
);
|
||||
// three modes. Keep the shared hex spelling across the advertised catalog;
|
||||
// actual provider acceptance is verified separately from JS compilation.
|
||||
expect(
|
||||
patterns.filter(
|
||||
({ pattern }) => pattern.includes("\\0") || pattern.includes("\\u0000"),
|
||||
),
|
||||
).toEqual([]);
|
||||
expect(patterns.some(({ pattern }) => pattern.includes("\\x00"))).toBe(true);
|
||||
});
|
||||
Reference in new issue
Block a user