mirror of
https://github.com/morluto/rea.git
synced 2026-10-27 09:55:46 +00:00
Replace the lookahead-based pattern with separate allOf/not JSON Schema rules for quartet length, alphabet, padding and canonical pad bits. Share the runtime predicates with HAR and padded base64 parsing. Validate converted advertised leaves with the MCP SDK validator, preserve permissive versus canonical semantics, and exercise every pattern near the 32 MiB encoded-input budget in all JavaScript modes.
139 lines
3.7 KiB
TypeScript
139 lines
3.7 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import { z } from "zod";
|
|
|
|
import {
|
|
BASE64_QUARTET_LENGTH_PATTERN,
|
|
INVALID_BASE64_CHARACTER_PATTERN,
|
|
INVALID_BASE64_PADDING_PATTERN,
|
|
INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN,
|
|
IDENTIFIER_PATTERN,
|
|
STABLE_IDENTIFIER_PATTERN,
|
|
canonicalBase64Schema,
|
|
isCanonicalBase64,
|
|
isPaddedBase64,
|
|
} from "./stringPatterns.js";
|
|
|
|
it("preserves identifier grammars under Unicode and Unicode-set compilation", () => {
|
|
const variants = [
|
|
{ pattern: IDENTIFIER_PATTERN, previous: /^[A-Za-z][A-Za-z0-9._-]*$/u },
|
|
{
|
|
pattern: STABLE_IDENTIFIER_PATTERN,
|
|
previous: /^[A-Za-z][A-Za-z0-9._:/-]*$/u,
|
|
},
|
|
];
|
|
const samples = [
|
|
"",
|
|
"a",
|
|
"A",
|
|
"_id",
|
|
"1id",
|
|
"é",
|
|
"aé",
|
|
"a/b:c",
|
|
"a-b.c_1",
|
|
"a\n",
|
|
"a\\b",
|
|
];
|
|
for (let code = 0; code < 128; code += 1) {
|
|
const character = String.fromCharCode(code);
|
|
samples.push(character, `A${character}`, `A${character}B`);
|
|
}
|
|
for (const { pattern, previous } of variants) {
|
|
for (const flag of ["u", "v"]) {
|
|
const projected = new RegExp(pattern.source, flag);
|
|
for (const sample of samples)
|
|
expect(projected.test(sample), JSON.stringify({ flag, sample })).toBe(
|
|
previous.test(sample),
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("preserves canonical and permissive padded base64 validation", () => {
|
|
const previous =
|
|
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?$/;
|
|
const samples = [
|
|
"",
|
|
"AA==",
|
|
"AB==",
|
|
"AAA=",
|
|
"AAB=",
|
|
"////",
|
|
"A",
|
|
"AA",
|
|
"AAA",
|
|
"====",
|
|
"AA==\n",
|
|
"AA==\r\n",
|
|
"AA==\u2028",
|
|
"AA==\u2029",
|
|
"AA\nAA",
|
|
"AA=\n=",
|
|
"AA-_",
|
|
"a b c",
|
|
];
|
|
const alphabet =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
for (const first of alphabet)
|
|
for (const second of alphabet)
|
|
samples.push(`${first}${second}==`, `A${first}${second}=`);
|
|
for (const sample of samples) {
|
|
expect(isCanonicalBase64(sample), JSON.stringify({ sample })).toBe(
|
|
previous.test(sample),
|
|
);
|
|
expect(isPaddedBase64(sample), JSON.stringify({ sample })).toBe(
|
|
sample.length % 4 === 0 && /^[A-Za-z0-9+/]*(?:==|=)?$/.test(sample),
|
|
);
|
|
}
|
|
});
|
|
|
|
it("advertises every portable base64 constraint and keeps large inputs stack-safe", () => {
|
|
const jsonSchema = z.toJSONSchema(canonicalBase64Schema, {
|
|
target: "draft-2020-12",
|
|
});
|
|
expect(jsonSchema).toMatchObject({
|
|
allOf: expect.arrayContaining([
|
|
{ pattern: BASE64_QUARTET_LENGTH_PATTERN.source },
|
|
{ not: { pattern: INVALID_BASE64_CHARACTER_PATTERN.source } },
|
|
{ not: { pattern: INVALID_BASE64_PADDING_PATTERN.source } },
|
|
{ not: { pattern: INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN.source } },
|
|
]),
|
|
});
|
|
|
|
const body = Buffer.alloc(24 * 1024 * 1024 - 3, 0x81);
|
|
const encoded = body.toString("base64");
|
|
for (const flag of ["", "u", "v"]) {
|
|
expect(
|
|
new RegExp(BASE64_QUARTET_LENGTH_PATTERN.source, flag).test(encoded),
|
|
flag,
|
|
).toBe(true);
|
|
expect(
|
|
new RegExp(INVALID_BASE64_CHARACTER_PATTERN.source, flag).test(encoded),
|
|
flag,
|
|
).toBe(false);
|
|
expect(
|
|
new RegExp(INVALID_BASE64_PADDING_PATTERN.source, flag).test(encoded),
|
|
flag,
|
|
).toBe(false);
|
|
expect(
|
|
new RegExp(INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN.source, flag).test(
|
|
encoded,
|
|
),
|
|
flag,
|
|
).toBe(false);
|
|
expect(
|
|
new RegExp(INVALID_BASE64_CHARACTER_PATTERN.source, flag).test(
|
|
`${encoded.slice(0, -1)}!`,
|
|
),
|
|
flag,
|
|
).toBe(true);
|
|
expect(
|
|
new RegExp(INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN.source, flag).test(
|
|
`${encoded.slice(0, -3)}R==`,
|
|
),
|
|
flag,
|
|
).toBe(true);
|
|
}
|
|
expect(isCanonicalBase64(encoded)).toBe(true);
|
|
});
|