import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const REPRODUCER_DIR = path.join(process.cwd(), "examples/reproducers"); const ARTIFACTS_DIR = path.join(process.cwd(), "artifacts"); // Ensure directories exist if (!fs.existsSync(REPRODUCER_DIR)) { fs.mkdirSync(REPRODUCER_DIR, { recursive: true }); } if (!fs.existsSync(ARTIFACTS_DIR)) { fs.mkdirSync(ARTIFACTS_DIR, { recursive: true }); } export const rng = { bool: () => Math.random() > 0.5, int: (min = 0, max = 100) => Math.floor(Math.random() * (max - min + 1)) + min, float: (min = 0, max = 100) => Math.random() * (max - min) + min, oneOf: (arr) => arr[Math.floor(Math.random() * arr.length)], string: (maxLength = 100) => { const len = Math.floor(Math.random() * maxLength); const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; for (let i = 0; i < len; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; }, nastyString: () => { const candidates = [ "", "null", "undefined", "NaN", "\x00", "\n", "\r", "\t", " ", " ", "https://example.com", "wss://relay.example.com", "", "' OR 1=1 --", "javascript:void(0)", "data:text/plain;base64,SGVsbG8=", "😀", "ñ", "\uD83D\uDCA9", // Pile of poo "\uD800", // Lone surrogate (high) "\uDFFF", // Lone surrogate (low) "A".repeat(1000), // Long string "A".repeat(10000), // Very long string JSON.stringify({ foo: "bar" }), "{}", "[]" ]; return candidates[Math.floor(Math.random() * candidates.length)]; }, mixedString: (maxLength = 100) => { if (Math.random() < 0.3) return rng.nastyString(); return rng.string(maxLength); }, array: (generator, maxLen = 10) => { const len = rng.int(0, maxLen); const result = []; for (let i = 0; i < len; i++) { result.push(generator()); } return result; }, object: (keyGen, valGen, maxKeys = 10) => { const len = rng.int(0, maxKeys); const result = {}; for (let i = 0; i < len; i++) { result[keyGen()] = valGen(); } return result; }, recursiveObject: (depth = 3) => { if (depth <= 0) return rng.mixedString(); const type = rng.int(0, 4); if (type === 0) return rng.int(-1000, 1000); if (type === 1) return rng.mixedString(); if (type === 2) return rng.bool(); if (type === 3) return null; if (type === 4) { // Array const len = rng.int(0, 5); const arr = []; for(let i=0; i 0) { process.stdout.write("."); } } process.stdout.write("\n"); stats.endTime = Date.now(); stats.duration = stats.endTime - stats.startTime; console.log(`[FUZZ] Finished. ${stats.passed} passed, ${stats.failed} failed.`); saveReport(targetName, stats); return stats; }