OLD | NEW |
(Empty) | |
| 1 //===-- pnacl-bcfuzz.cpp - Record fuzzer for PNaCl bitcode ----------------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // Generates (record-level) fuzzed PNaCl bitcode files from an input |
| 11 // PNaCl bitcode file. |
| 12 // |
| 13 //===----------------------------------------------------------------------===// |
| 14 |
| 15 #include "llvm/Bitcode/NaCl/NaClFuzz.h" |
| 16 #include "llvm/Support/CommandLine.h" |
| 17 #include "llvm/Support/FileSystem.h" |
| 18 #include "llvm/Support/ManagedStatic.h" |
| 19 #include "llvm/Support/MemoryBuffer.h" |
| 20 #include "llvm/Support/PrettyStackTrace.h" |
| 21 #include "llvm/Support/Signals.h" |
| 22 #include "llvm/Support/ToolOutputFile.h" |
| 23 |
| 24 using namespace llvm; |
| 25 using namespace naclfuzz; |
| 26 |
| 27 static cl::opt<std::string> |
| 28 InputFilename(cl::Positional, cl::desc("<frozen file>"), cl::init("-")); |
| 29 |
| 30 static cl::opt<std::string> |
| 31 OutputPrefix("output", cl::desc("<output prefix>"), cl::init("")); |
| 32 |
| 33 static cl::opt<unsigned> |
| 34 FuzzCount("count", cl::desc("Number of fuzz results to generate"), |
| 35 cl::init(1)); |
| 36 |
| 37 static cl::opt<std::string> |
| 38 RandomSeed("random-seed", |
| 39 cl::desc("Use this value for seed of random number generator " |
| 40 "(rather than input)"), |
| 41 cl::init("")); |
| 42 |
| 43 static cl::opt<bool> |
| 44 ShowFuzzRecordDistribution( |
| 45 "record-distribution", |
| 46 cl::desc("Show distribution of record edits while fuzzing"), |
| 47 cl::init(false)); |
| 48 |
| 49 static cl::opt<bool> |
| 50 ShowFuzzEditDistribution( |
| 51 "edit-distribution", |
| 52 cl::desc("Show distribution of editing actions while fuzzing"), |
| 53 cl::init(false)); |
| 54 |
| 55 static cl::opt<unsigned> |
| 56 PercentageToEdit( |
| 57 "edit-percentage", |
| 58 cl::desc("Percentage of records to edit during fuzz (between 1 and" |
| 59 " '-percentage-base')"), |
| 60 cl::init(1)); |
| 61 |
| 62 static cl::opt<unsigned> |
| 63 PercentageBase( |
| 64 "percentage-base", |
| 65 cl::desc("Base that '-edit-precentage' is defined on (defaults to 100)"), |
| 66 cl::init(100)); |
| 67 |
| 68 static cl::opt<bool> |
| 69 Verbose("verbose", |
| 70 cl::desc("Show details of fuzzing/writing of bitcode files"), |
| 71 cl::init(false)); |
| 72 |
| 73 static void WriteOutputFile(SmallVectorImpl<char> &Buffer, |
| 74 StringRef OutputFilename) { |
| 75 std::error_code EC; |
| 76 std::unique_ptr<tool_output_file> Out( |
| 77 new tool_output_file(OutputFilename, EC, sys::fs::F_None)); |
| 78 if (EC) { |
| 79 errs() << EC.message() << '\n'; |
| 80 exit(1); |
| 81 } |
| 82 |
| 83 for (SmallVectorImpl<char>::const_iterator |
| 84 Iter = Buffer.begin(), IterEnd = Buffer.end(); |
| 85 Iter != IterEnd; ++Iter) { |
| 86 Out->os() << *Iter; |
| 87 } |
| 88 |
| 89 // Declare success. |
| 90 Out->keep(); |
| 91 } |
| 92 |
| 93 int main(int argc, char **argv) { |
| 94 // Print a stack trace if we signal out. |
| 95 sys::PrintStackTraceOnErrorSignal(); |
| 96 PrettyStackTraceProgram X(argc, argv); |
| 97 |
| 98 cl::ParseCommandLineOptions(argc, argv, "Fuzz a PNaCl bitcode file\n"); |
| 99 |
| 100 if (PercentageToEdit > PercentageBase) { |
| 101 errs() << "Edit percentage " << PercentageToEdit |
| 102 << " must not exceed: " << PercentageBase << "\n"; |
| 103 return 1; |
| 104 } |
| 105 |
| 106 if (OutputPrefix.empty()) { |
| 107 errs() << "Output prefix not specified!\n"; |
| 108 return 1; |
| 109 } |
| 110 |
| 111 ErrorOr<std::unique_ptr<MemoryBuffer>> |
| 112 MemBuf(MemoryBuffer::getFile(InputFilename)); |
| 113 if (!MemBuf) { |
| 114 errs() << MemBuf.getError().message() << "\n"; |
| 115 return 1; |
| 116 } |
| 117 |
| 118 // Stream to dump bitcode write errors to if not verbose. |
| 119 raw_null_ostream NullStrm; |
| 120 |
| 121 NaClMungedBitcode Bitcode(std::move(MemBuf.get())); |
| 122 |
| 123 std::string RandSeed(RandomSeed); |
| 124 if (RandomSeed.empty()) |
| 125 RandSeed = InputFilename; |
| 126 |
| 127 DefaultRandomNumberGenerator Generator(RandSeed); |
| 128 std::unique_ptr<RecordFuzzer> Fuzzer( |
| 129 RecordFuzzer::createSimpleRecordFuzzer(Bitcode, Generator)); |
| 130 |
| 131 for (size_t i = 1; i <= FuzzCount; ++i) { |
| 132 Generator.saltSeed(i); |
| 133 std::string OutputFile; |
| 134 { |
| 135 raw_string_ostream StrBuf(OutputFile); |
| 136 StrBuf << OutputPrefix << "-" << i; |
| 137 StrBuf.flush(); |
| 138 } |
| 139 |
| 140 if (Verbose) |
| 141 errs() << "Generating " << OutputFile << "\n"; |
| 142 |
| 143 if (!Fuzzer->fuzz(PercentageToEdit, PercentageBase)) { |
| 144 errs() << "Error: Fuzzing failed: " << OutputFile << "\n"; |
| 145 continue; |
| 146 } |
| 147 |
| 148 if (Verbose) { |
| 149 errs() << "Records:\n"; |
| 150 for (const auto &Record : Bitcode) { |
| 151 errs() << " " << Record << "\n"; |
| 152 } |
| 153 } |
| 154 |
| 155 SmallVector<char, 100> Buffer; |
| 156 NaClMungedBitcode::WriteFlags WriteFlags; |
| 157 WriteFlags.setTryToRecover(true); |
| 158 if (!Verbose) { |
| 159 WriteFlags.setErrStream(NullStrm); |
| 160 } |
| 161 if (!Bitcode.write(Buffer, true, WriteFlags)) { |
| 162 errs() << "Error: Failed to write fuzzed code: " |
| 163 << OutputFile << "\n"; |
| 164 continue; |
| 165 } |
| 166 WriteOutputFile(Buffer, OutputFile); |
| 167 } |
| 168 |
| 169 |
| 170 if (ShowFuzzRecordDistribution) |
| 171 Fuzzer->showRecordDistribution(outs()); |
| 172 if (ShowFuzzEditDistribution) |
| 173 Fuzzer->showEditDistribution(outs()); |
| 174 |
| 175 return 0; |
| 176 } |
OLD | NEW |