UNPKG

surku

Version:

A mutation-based general purpose fuzzer.

301 lines (279 loc) 7.67 kB
function cmd() { const path = require("path"); const fs = require("fs"); const self = this; this.surkuConfig = { maxMutations: 20, minMutations: 1, useOnly: undefined, seed: undefined, count: 1, outputName: undefined, inputPath: undefined, verbose: undefined, }; const debugPrint = function (message, level) { if ( self.surkuConfig.hasOwnProperty("verbose") && self.surkuConfig.verbose >= level ) { process.stderr.write(message); } }; if ( process.argv.indexOf("-v") !== -1 || process.argv.indexOf("--verbose") !== -1 ) this.surkuConfig.verbose = 5; debugPrint("Args: \n", 1); debugPrint(`${process.argv.toString().replace(/,/g, " ")}\n`, 1); // These are sort of linked lists // /* shortArgs=[ [argument1, argument2], [argument1Function, argument2Function] ] */ const shortArgs = [ [ "-h", "-a", "-V", "-o", "-n", "-s", "-m", "-p", "-g", "-M", "-r", "-l", "-v", "-Mm", "-mm", ], [ outputHelp, outputAbout, outputVersion, parseOutputArg, parseCount, parseSeed, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, setVerbose, setMaxMutations, setMinMutations, ], ]; const longArgs = [ [ "--help", "--about", "--version", "--output", "--count", "--seed", "--mutations", "--patterns", "--generators", "--meta", "--recursive", "--list", "--verbose", "--maxmutations", "--minmutations", ], [ outputHelp, outputAbout, outputVersion, parseOutputArg, parseCount, parseSeed, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, notImplementedYet, setVerbose, setMaxMutations, setMinMutations, ], ]; const argDescriptions = [ [", show this thing"], [", what is this thing"], [", show version info"], [ " <arg>, file name pattern for outputs, e.g. output/fuzz-%n.foo, required", ], [" <arg>, how many files to generate, defaults to 1"], [" <arg>, which seed to use, defaults to random"], [ ' <arg>, which mutators to use, for defaults use argument "-l" or "--list"', ], [], [], [], [], [", list default mutators"], [", verbosed console-outputs"], [" <arg>, set max mutations per output, default 20"], [" <arg>, set min mutations per output, default 2"], ]; function outputHelp() { console.log("This is Surku v0.1.1 Help."); console.log("Usage: node Surku.js [arguments] [file ...]"); for (let x = 0; x < shortArgs[0].length; x++) { if (argDescriptions[x] !== "") { console.log( `${shortArgs[0][x]} | ${longArgs[0][x]}${argDescriptions[x]}` ); } } process.exit(1); } if (process.argv[2] === undefined) { outputHelp(); process.exit(1); } function outputAbout() { debugPrint("Surku about:", 5); console.log("Surku is a general purpose fuzzer"); console.log("Its purpose is to introduce malformations into sample files,"); console.log("in order to trigger errors in program under test."); console.log("In default only general mutators are available,"); console.log("but new mutators can be added by user."); console.log(""); console.log("For more info see doumentation in:"); console.log("http://code.google.com/p/ouspg/"); console.log(""); console.log("Surku as written by Atte Kettunen at OUSPG"); process.exit(1); } function outputVersion() { console.log("Surku version 0.1"); process.exit(1); } function parseOutputArg(cmd, index) { debugPrint("parseOutputArg\n", 5); const outputExpression = process.argv[index + 1]; const resolvedPath = path.resolve(outputExpression); const pathOnly = path.dirname(resolvedPath); const baseName = path.basename(resolvedPath); if (!fs.existsSync(pathOnly)) { console.log("Output path does not exist."); process.exit(2); } else if (baseName.indexOf("%n") === -1) { console.log("Must have output filename syntax. e.g. fuzz-%n.html"); process.exit(2); } else { cmd.surkuConfig.outputName = resolvedPath; } } function parseCount(cmd, index) { debugPrint("parseCount\n", 5); const count = process.argv[index + 1]; if (!isNaN(parseInt(count))) { cmd.surkuConfig.count = count; } else { console.log("Invalid output file count."); process.exit(2); } } function parseSeed(cmd, index) { debugPrint("parseSeed\n", 5); const seed = process.argv[index + 1]; if (!isNaN(parseInt(seed))) { cmd.surkuConfig.seed = seed; } else { console.log("Invalid seed."); process.exit(2); } } function setMaxMutations(cmd, index) { debugPrint(`setMaxMutations: ${process.argv[index + 1]}\n`, 5); const mutations = process.argv[index + 1]; if (!isNaN(parseInt(mutations)) && parseInt(mutations) > 0) { cmd.surkuConfig.maxMutations = mutations; } else { console.log("Invalid max mutations value."); process.exit(2); } } function setMinMutations(cmd, index) { debugPrint(`setMinMutations: ${process.argv[index + 1]}\n`, 5); const mutations = process.argv[index + 1]; if (!isNaN(parseInt(mutations)) && parseInt(mutations) > 0) { cmd.surkuConfig.minMutations = mutations; } else { console.log("Invalid min mutations value."); process.exit(2); } } function setVerbose(cmd, index) { debugPrint("setVerbose\n", 5); cmd.surkuConfig.verbose = 5; } function notImplementedYet(cmd, index) { debugPrint("Not implemented yet.\n"); console.log(`Argument ${process.argv[index]} is not implemented yet.`); } let lastIndex = 2; process.argv.forEach((arg, index) => { const indexShort = shortArgs[0].indexOf(arg); const indexLong = longArgs[0].indexOf(arg); if (indexShort !== -1) { lastIndex = index; shortArgs[1][indexShort](self, index); } if (indexLong !== -1) { lastIndex = index; longArgs[1][indexLong](self, index); } }); if ( parseInt(self.surkuConfig.maxMutations) < parseInt(self.surkuConfig.minMutations) ) { console.log("Set max mutations is smaller than set min mutations."); process.exit(2); } if ( process.argv[process.argv.length - 2] !== "-o" && process.argv[process.argv.length - 2] !== "--output" ) { const inputPath = path.resolve(process.argv[process.argv.length - 1]); debugPrint(`inputPath: ${inputPath}\n`, 5); if (fs.existsSync(inputPath)) { if (fs.statSync(inputPath).isDirectory()) { this.surkuConfig.inputPath = inputPath; } else { const newInputPath = []; for (let x = lastIndex; x < process.argv.length; x++) { if ( fs.existsSync(process.argv[x]) && !fs.statSync(process.argv[x]).isDirectory() ) newInputPath.push(path.resolve(process.argv[x])); } this.surkuConfig.inputFile = newInputPath; } } else { console.log(`Input path ${inputPath} does not exist.`); process.exit(2); } } else { console.log("No input path given."); process.exit(2); } return this.surkuConfig; } module.exports = cmd();