peachPayload.binaryreader-bounds.test.ts

2.4 KB · raw

1// PCH-02-008 regression tests — BinaryReader must bound every read and fail2// with the decoder's existing PAYLOAD_TOO_SHORT code on truncated input.34import { describe, expect, it } from "vitest";5import { BinaryReader } from "./peachPayload";67describe("PCH-02-008 — BinaryReader bounds checks", () => {8  it("u8 past end of buffer throws PAYLOAD_TOO_SHORT", () => {9    const r = new BinaryReader(Uint8Array.of(0xaa), 0);10    expect(r.u8()).toBe(0xaa);11    expect(() => r.u8()).toThrow("PAYLOAD_TOO_SHORT");12  });1314  it("u16 with only one byte remaining throws PAYLOAD_TOO_SHORT", () => {15    const r = new BinaryReader(Uint8Array.of(0x01), 0);16    expect(() => r.u16()).toThrow("PAYLOAD_TOO_SHORT");17  });1819  it("u32 with three bytes remaining throws PAYLOAD_TOO_SHORT", () => {20    const r = new BinaryReader(Uint8Array.of(0x01, 0x02, 0x03), 0);21    expect(() => r.u32()).toThrow("PAYLOAD_TOO_SHORT");22  });2324  it("read(n) past end throws instead of clamping short", () => {25    const r = new BinaryReader(Uint8Array.of(1, 2, 3, 4), 0);26    expect(() => r.read(5)).toThrow("PAYLOAD_TOO_SHORT");27  });2829  it("lpString whose declared length overruns the buffer throws", () => {30    const r = new BinaryReader(Uint8Array.of(200, 0x61, 0x62), 0);31    expect(() => r.lpString(1)).toThrow("PAYLOAD_TOO_SHORT");32  });3334  it("valid reads at exact buffer boundaries still work (regression)", () => {35    const buf = new Uint8Array(11);36    const view = new DataView(buf.buffer);37    buf[0] = 0x7f;38    view.setUint16(1, 0xbeef, true);39    view.setUint32(3, 0xdeadbeef, true);40    buf.set([0x70, 0x65, 0x61, 0x63], 7);4142    const r = new BinaryReader(buf, 0);43    expect(r.u8()).toBe(0x7f);44    expect(r.u16()).toBe(0xbeef);45    expect(r.u32()).toBe(0xdeadbeef);46    expect(Array.from(r.read(4))).toEqual([0x70, 0x65, 0x61, 0x63]);47    expect(() => r.u8()).toThrow("PAYLOAD_TOO_SHORT");48  });4950  it("lpString round-trips a valid length-prefixed string (regression)", () => {51    const text = new TextEncoder().encode("peach");52    const buf = new Uint8Array(1 + text.length);53    buf[0] = text.length;54    buf.set(text, 1);5556    const r = new BinaryReader(buf, 0);57    expect(r.lpString(1)).toBe("peach");58    expect(r.cursor).toBe(buf.length);59  });6061  it("respects a non-zero start offset and bounds from it", () => {62    const buf = Uint8Array.of(0xff, 0xff, 0x2a);63    const r = new BinaryReader(buf, 2);64    expect(r.u8()).toBe(0x2a);65    expect(() => r.u8()).toThrow("PAYLOAD_TOO_SHORT");66  });67});