mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-05-28 11:35:43 +00:00
92 lines
2.7 KiB
JavaScript
92 lines
2.7 KiB
JavaScript
import { gzipSync } from "node:zlib";
|
|
import { describe, it, expect, beforeAll } from "vitest";
|
|
import { decodeTgsBuffer } from "@/js/tgsDecode.js";
|
|
|
|
beforeAll(() => {
|
|
const ctx = {
|
|
fillStyle: "",
|
|
strokeStyle: "",
|
|
fillRect: vi.fn(),
|
|
clearRect: vi.fn(),
|
|
save: vi.fn(),
|
|
restore: vi.fn(),
|
|
translate: vi.fn(),
|
|
scale: vi.fn(),
|
|
rotate: vi.fn(),
|
|
beginPath: vi.fn(),
|
|
closePath: vi.fn(),
|
|
moveTo: vi.fn(),
|
|
lineTo: vi.fn(),
|
|
arc: vi.fn(),
|
|
fill: vi.fn(),
|
|
stroke: vi.fn(),
|
|
setTransform: vi.fn(),
|
|
drawImage: vi.fn(),
|
|
measureText: vi.fn(() => ({ width: 0 })),
|
|
createLinearGradient: vi.fn(() => ({ addColorStop: vi.fn() })),
|
|
createRadialGradient: vi.fn(() => ({ addColorStop: vi.fn() })),
|
|
};
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => ctx);
|
|
});
|
|
|
|
function randomUint8Array(n) {
|
|
const u = new Uint8Array(n);
|
|
crypto.getRandomValues(u);
|
|
return u;
|
|
}
|
|
|
|
function randomJsonValue(depth) {
|
|
if (depth <= 0) {
|
|
return null;
|
|
}
|
|
const r = Math.random();
|
|
if (r < 0.2) {
|
|
return null;
|
|
}
|
|
if (r < 0.4) {
|
|
return Math.floor(Math.random() * 1_000_000);
|
|
}
|
|
if (r < 0.55) {
|
|
return String.fromCharCode(32 + Math.floor(Math.random() * 80));
|
|
}
|
|
if (r < 0.75) {
|
|
const n = Math.floor(Math.random() * 8);
|
|
return Array.from({ length: n }, () => randomJsonValue(depth - 1));
|
|
}
|
|
const n = Math.floor(Math.random() * 6);
|
|
const o = {};
|
|
for (let i = 0; i < n; i++) {
|
|
o[`k${i}`] = randomJsonValue(depth - 1);
|
|
}
|
|
return o;
|
|
}
|
|
|
|
describe("fuzzing: TGS decode", () => {
|
|
it("fuzzing: decodeTgsBuffer handles random buffers without unhandled rejection", async () => {
|
|
for (let i = 0; i < 2000; i++) {
|
|
const len = Math.floor(Math.random() * 6144);
|
|
const buf = randomUint8Array(len).buffer;
|
|
try {
|
|
await decodeTgsBuffer(buf);
|
|
} catch {
|
|
/* JSON.parse, gzip, or missing DecompressionStream */
|
|
}
|
|
}
|
|
expect(true).toBe(true);
|
|
});
|
|
|
|
it("fuzzing: decodeTgsBuffer handles gzip-compressed random JSON", async () => {
|
|
for (let i = 0; i < 400; i++) {
|
|
const payload = JSON.stringify(randomJsonValue(6));
|
|
const gz = gzipSync(Buffer.from(payload, "utf8"));
|
|
const ab = gz.buffer.slice(gz.byteOffset, gz.byteOffset + gz.byteLength);
|
|
try {
|
|
await decodeTgsBuffer(ab);
|
|
} catch {
|
|
/* invalid JSON after decompress */
|
|
}
|
|
}
|
|
expect(true).toBe(true);
|
|
});
|
|
});
|