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;
}