peachScript.bounds.test.ts

2.9 KB · raw

1// PB-26-208: PeachScript normalization before limits.2//3// normalize-then-decode allocated unbounded intermediates (regex copy,4// Array.from) before any ceiling, and decode measured UTF-16 length — not5// decoded bytes — against the export ceiling. One bounded parser replaces6// the sequence: raw code points are capped at ceiling + a small pasted-7// whitespace allowance, then a single scan skips whitespace, validates8// every other code point, and stops once the decoded ceiling is crossed.9import { describe, expect, test, vi } from "vitest";10import { decodePeachScript, isPeachScript } from "./peachScript";11import { IMPORT_LIMITS } from "../shared/import-limits";1213// Mirror of the parser ceilings: floor(MAX_JSON_BYTES / 3) decoded code14// points (each PUA glyph costs 3 UTF-8 bytes, matching the export ceiling)15// plus a 64 KiB raw-whitespace allowance for pasted text.16const MAX_CP = Math.floor(IMPORT_LIMITS.MAX_JSON_BYTES / 3);17const ALLOWANCE = 64 * 1024;18const MAX_RAW = MAX_CP + ALLOWANCE;19const GLYPH = String.fromCodePoint(0xe041);2021describe("PB-26-208 bounded PeachScript parser", () => {22  test("whitespace-only input over ceiling + allowance fails as too large without Array.from", () => {23    const fromSpy = vi.spyOn(Array, "from");24    try {25      expect(() => decodePeachScript(" ".repeat(MAX_RAW + 1))).toThrow(26        "PEACHSCRIPT_TOO_LARGE",27      );28      expect(29        fromSpy.mock.calls.some(30          (args) => typeof args[0] === "string" && args[0].length > MAX_RAW,31        ),32        "decode must not Array.from an over-ceiling input",33      ).toBe(false);34    } finally {35      fromSpy.mockRestore();36    }37  });3839  test("valid script at the encoded ceiling decodes; one more glyph fails", () => {40    const atCeiling = GLYPH.repeat(MAX_CP);41    expect(decodePeachScript(atCeiling).length).toBe(MAX_CP);42    expect(() => decodePeachScript(`${atCeiling}${GLYPH}`)).toThrow(43      "PEACHSCRIPT_TOO_LARGE",44    );45  });4647  test("whitespace allowance boundary: allowance passes, allowance + 1 fails", () => {48    expect(decodePeachScript(" ".repeat(ALLOWANCE) + GLYPH).length).toBe(1);49    expect(() => decodePeachScript(" ".repeat(ALLOWANCE + 1) + GLYPH)).toThrow(50      "PEACHSCRIPT_TOO_LARGE",51    );52  });5354  test("lone surrogates and astral characters throw without partial output", () => {55    expect(() => decodePeachScript(`${GLYPH}\ud800${GLYPH}`)).toThrow(56      "INVALID_PEACHSCRIPT_CHARACTER",57    );58    expect(() => decodePeachScript("\udc00")).toThrow(59      "INVALID_PEACHSCRIPT_CHARACTER",60    );61    expect(() => decodePeachScript(`${GLYPH}\u{1D2E0}`)).toThrow(62      "INVALID_PEACHSCRIPT_CHARACTER",63    );64  });6566  test("isPeachScript shares the bound: oversized input is simply invalid", () => {67    expect(isPeachScript(" ".repeat(MAX_RAW + 1))).toBe(false);68    expect(isPeachScript(GLYPH.repeat(MAX_CP + 1))).toBe(false);69    expect(isPeachScript(`  ${GLYPH}\n`)).toBe(true);70  });71});