Files
gstack/browse/test/regression-pr1169-pdf-from-file-invalid-json.test.ts
T
Garry TanandOpenAI Codex 4a3c6a8a3c v1.87.0.0 feat: add verified CSO audits and replayable repair bundles (#2852)
* feat(cso): add verified audits and replayable repair bundles

* fix(cso): harden qualification and setup boundaries

* fix(cso): assemble security canaries at runtime

* fix(cso): bound release proof and maintenance work

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): require complete evaluation reports

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): replay expired snapshots from supplied source

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(cso): synchronize DNS cancellation assertion

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore(ship): exempt repository owner from liveness proof

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(cso): make recheck retention overlap deterministic

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: bump version and changelog (v1.85.0.0)

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): pass native release gates

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: move release to v1.86.0.0

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): resolve rechecks by finding

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: move release to v1.87.0.0

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): pass macOS and Windows release gates

Normalize BSD wc output, compare Windows paths by filesystem identity, preserve portable snapshot race coverage, and narrow POSIX-only Windows fixtures.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): harden native verification gates

* fix(cso): refine Windows native diagnostics

* test(cso): isolate Windows Git startup failure

* test(cso): stabilize Windows native diagnostics

* fix(cso): support hardened Git on Windows

* fix(cso): close final verification gaps

* test(cso): bound cold Docker fixture setup

* fix(cso): restore cross-platform free-suite gates

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
2026-09-14 15:14:58 -07:00

85 lines
3.4 KiB
TypeScript

/**
* Regression test for PR #1169 bug #7 — `pdf --from-file` ran JSON.parse on
* user-supplied file contents with no try/catch. A malformed payload crashed
* the pdf handler with a raw SyntaxError. Codex flagged that JSON.parse
* accepts primitives too (numbers, strings, null) and Array.isArray must be
* checked separately, so the fix added an explicit object-shape gate.
*
* Test surface: parsePdfFromFile, exported for tests at meta-commands.ts:139.
* Fixtures use the system temp directory, which SAFE_DIRECTORIES allows on
* every supported platform and which keeps transient files out of the repo.
*/
import { describe, expect, test, beforeAll, afterAll } from "bun:test";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { parsePdfFromFile } from "../src/meta-commands";
const FIXTURE_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "pr1169-pdf-"));
beforeAll(() => {
// mkdtempSync already created the dir
});
afterAll(() => {
fs.rmSync(FIXTURE_DIR, { recursive: true, force: true });
});
function writeFixture(name: string, body: string): string {
const p = path.join(FIXTURE_DIR, name);
fs.writeFileSync(p, body);
return p;
}
describe("parsePdfFromFile — invalid JSON regression (PR #1169 bug #7)", () => {
test("invalid JSON: throws with file path AND parser detail", () => {
const p = writeFixture("invalid.json", "{ not-json");
expect(() => parsePdfFromFile(p)).toThrow(/not valid JSON/);
expect(() => parsePdfFromFile(p)).toThrow(p);
});
test("empty file: throws JSON-parse style error", () => {
const p = writeFixture("empty.json", "");
// Empty string is invalid JSON per ECMA-404.
expect(() => parsePdfFromFile(p)).toThrow(/not valid JSON/);
});
test("top-level array: throws 'must be a JSON object' with type", () => {
const p = writeFixture("array.json", JSON.stringify(["a", "b"]));
expect(() => parsePdfFromFile(p)).toThrow(/must be a JSON object/);
expect(() => parsePdfFromFile(p)).toThrow(/array/);
});
test("top-level number: throws with 'number' type label", () => {
const p = writeFixture("number.json", "42");
expect(() => parsePdfFromFile(p)).toThrow(/must be a JSON object/);
expect(() => parsePdfFromFile(p)).toThrow(/number/);
});
test("top-level string: throws with 'string' type label", () => {
const p = writeFixture("string.json", JSON.stringify("hello"));
expect(() => parsePdfFromFile(p)).toThrow(/must be a JSON object/);
expect(() => parsePdfFromFile(p)).toThrow(/string/);
});
test("top-level null: throws with 'object' type label (JS null typeof === object)", () => {
const p = writeFixture("null.json", "null");
// null passes typeof === 'object' but the fix's `=== null` branch catches it.
expect(() => parsePdfFromFile(p)).toThrow(/must be a JSON object/);
});
test("top-level boolean: throws with 'boolean' type label", () => {
const p = writeFixture("bool.json", "true");
expect(() => parsePdfFromFile(p)).toThrow(/must be a JSON object/);
expect(() => parsePdfFromFile(p)).toThrow(/boolean/);
});
test("valid object: parses successfully (happy-path regression)", () => {
const p = writeFixture("valid.json", JSON.stringify({ format: "A4", pageNumbers: true }));
const result = parsePdfFromFile(p);
expect(result.format).toBe("A4");
expect(result.pageNumbers).toBe(true);
});
});