| Index: tools/pnacl-bcfuzz/pnacl-bcfuzz.cpp
|
| diff --git a/tools/pnacl-bcfuzz/pnacl-bcfuzz.cpp b/tools/pnacl-bcfuzz/pnacl-bcfuzz.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d7bf00434de43e53b591fea500cec600815f5ca3
|
| --- /dev/null
|
| +++ b/tools/pnacl-bcfuzz/pnacl-bcfuzz.cpp
|
| @@ -0,0 +1,176 @@
|
| +//===-- pnacl-bcfuzz.cpp - Record fuzzer for PNaCl bitcode ----------------===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// Generates (record-level) fuzzed PNaCl bitcode files from an input
|
| +// PNaCl bitcode file.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#include "llvm/Bitcode/NaCl/NaClFuzz.h"
|
| +#include "llvm/Support/CommandLine.h"
|
| +#include "llvm/Support/FileSystem.h"
|
| +#include "llvm/Support/ManagedStatic.h"
|
| +#include "llvm/Support/MemoryBuffer.h"
|
| +#include "llvm/Support/PrettyStackTrace.h"
|
| +#include "llvm/Support/Signals.h"
|
| +#include "llvm/Support/ToolOutputFile.h"
|
| +
|
| +using namespace llvm;
|
| +using namespace naclfuzz;
|
| +
|
| +static cl::opt<std::string>
|
| +InputFilename(cl::Positional, cl::desc("<frozen file>"), cl::init("-"));
|
| +
|
| +static cl::opt<std::string>
|
| +OutputPrefix("output", cl::desc("<output prefix>"), cl::init(""));
|
| +
|
| +static cl::opt<unsigned>
|
| +FuzzCount("count", cl::desc("Number of fuzz results to generate"),
|
| + cl::init(1));
|
| +
|
| +static cl::opt<std::string>
|
| +RandomSeed("random-seed",
|
| + cl::desc("Use this value for seed of random number generator "
|
| + "(rather than input)"),
|
| + cl::init(""));
|
| +
|
| +static cl::opt<bool>
|
| +ShowFuzzRecordDistribution(
|
| + "record-distribution",
|
| + cl::desc("Show distribution of record edits while fuzzing"),
|
| + cl::init(false));
|
| +
|
| +static cl::opt<bool>
|
| +ShowFuzzEditDistribution(
|
| + "edit-distribution",
|
| + cl::desc("Show distribution of editing actions while fuzzing"),
|
| + cl::init(false));
|
| +
|
| +static cl::opt<unsigned>
|
| +PercentageToEdit(
|
| + "edit-percentage",
|
| + cl::desc("Percentage of records to edit during fuzz (between 1 and"
|
| + " '-percentage-base')"),
|
| + cl::init(1));
|
| +
|
| +static cl::opt<unsigned>
|
| +PercentageBase(
|
| + "percentage-base",
|
| + cl::desc("Base that '-edit-precentage' is defined on (defaults to 100)"),
|
| + cl::init(100));
|
| +
|
| +static cl::opt<bool>
|
| +Verbose("verbose",
|
| + cl::desc("Show details of fuzzing/writing of bitcode files"),
|
| + cl::init(false));
|
| +
|
| +static void WriteOutputFile(SmallVectorImpl<char> &Buffer,
|
| + StringRef OutputFilename) {
|
| + std::error_code EC;
|
| + std::unique_ptr<tool_output_file> Out(
|
| + new tool_output_file(OutputFilename, EC, sys::fs::F_None));
|
| + if (EC) {
|
| + errs() << EC.message() << '\n';
|
| + exit(1);
|
| + }
|
| +
|
| + for (SmallVectorImpl<char>::const_iterator
|
| + Iter = Buffer.begin(), IterEnd = Buffer.end();
|
| + Iter != IterEnd; ++Iter) {
|
| + Out->os() << *Iter;
|
| + }
|
| +
|
| + // Declare success.
|
| + Out->keep();
|
| +}
|
| +
|
| +int main(int argc, char **argv) {
|
| + // Print a stack trace if we signal out.
|
| + sys::PrintStackTraceOnErrorSignal();
|
| + PrettyStackTraceProgram X(argc, argv);
|
| +
|
| + cl::ParseCommandLineOptions(argc, argv, "Fuzz a PNaCl bitcode file\n");
|
| +
|
| + if (PercentageToEdit > PercentageBase) {
|
| + errs() << "Edit percentage " << PercentageToEdit
|
| + << " must not exceed: " << PercentageBase << "\n";
|
| + return 1;
|
| + }
|
| +
|
| + if (OutputPrefix.empty()) {
|
| + errs() << "Output prefix not specified!\n";
|
| + return 1;
|
| + }
|
| +
|
| + ErrorOr<std::unique_ptr<MemoryBuffer>>
|
| + MemBuf(MemoryBuffer::getFile(InputFilename));
|
| + if (!MemBuf) {
|
| + errs() << MemBuf.getError().message() << "\n";
|
| + return 1;
|
| + }
|
| +
|
| + // Stream to dump bitcode write errors to if not verbose.
|
| + raw_null_ostream NullStrm;
|
| +
|
| + NaClMungedBitcode Bitcode(std::move(MemBuf.get()));
|
| +
|
| + std::string RandSeed(RandomSeed);
|
| + if (RandomSeed.empty())
|
| + RandSeed = InputFilename;
|
| +
|
| + DefaultRandomNumberGenerator Generator(RandSeed);
|
| + std::unique_ptr<RecordFuzzer> Fuzzer(
|
| + RecordFuzzer::createSimpleRecordFuzzer(Bitcode, Generator));
|
| +
|
| + for (size_t i = 1; i <= FuzzCount; ++i) {
|
| + Generator.saltSeed(i);
|
| + std::string OutputFile;
|
| + {
|
| + raw_string_ostream StrBuf(OutputFile);
|
| + StrBuf << OutputPrefix << "-" << i;
|
| + StrBuf.flush();
|
| + }
|
| +
|
| + if (Verbose)
|
| + errs() << "Generating " << OutputFile << "\n";
|
| +
|
| + if (!Fuzzer->fuzz(PercentageToEdit, PercentageBase)) {
|
| + errs() << "Error: Fuzzing failed: " << OutputFile << "\n";
|
| + continue;
|
| + }
|
| +
|
| + if (Verbose) {
|
| + errs() << "Records:\n";
|
| + for (const auto &Record : Bitcode) {
|
| + errs() << " " << Record << "\n";
|
| + }
|
| + }
|
| +
|
| + SmallVector<char, 100> Buffer;
|
| + NaClMungedBitcode::WriteFlags WriteFlags;
|
| + WriteFlags.setTryToRecover(true);
|
| + if (!Verbose) {
|
| + WriteFlags.setErrStream(NullStrm);
|
| + }
|
| + if (!Bitcode.write(Buffer, true, WriteFlags)) {
|
| + errs() << "Error: Failed to write fuzzed code: "
|
| + << OutputFile << "\n";
|
| + continue;
|
| + }
|
| + WriteOutputFile(Buffer, OutputFile);
|
| + }
|
| +
|
| +
|
| + if (ShowFuzzRecordDistribution)
|
| + Fuzzer->showRecordDistribution(outs());
|
| + if (ShowFuzzEditDistribution)
|
| + Fuzzer->showEditDistribution(outs());
|
| +
|
| + return 0;
|
| +}
|
|
|