Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 4dd3b8a

Browse files
committed
Initial implementation of a record-level bitcode fuzzer.
Initial implementation of a record-level bitcod fuzzer for PNaCl bitcode files. Uses "rand" for the random number generator, as well as some simplistic rules for generating values for the bitcode records. The simplistic rules use lists of weighted values, and values are chosen from the list based on the corresponding weighted distribution. Also fixes minor bug in the bitstream writer where no checks were applied to see if an abbreviation definition was outside any scope. BUG=https://code.google.com/p/nativeclient/issues/detail?id=4169 [email protected] Review URL: https://codereview.chromium.org/1156103003
1 parent 2c9a36e commit 4dd3b8a

File tree

14 files changed

+979
-4
lines changed

14 files changed

+979
-4
lines changed

include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ class NaClMungedBitcode {
238238

239239
bool write(SmallVectorImpl<char> &Buffer, bool AddHeader,
240240
const WriteFlags &Flags) const {
241-
return writeMaybeRepair(Buffer, AddHeader, Flags).NumErrors == 0;
241+
WriteResults Results = writeMaybeRepair(Buffer, AddHeader, Flags);
242+
return Results.NumErrors == 0
243+
|| (Flags.getTryToRecover() && Results.NumErrors == Results.NumRepairs);
242244
}
243245

244246
bool write(SmallVectorImpl<char> &Buffer, bool AddHeader) const {

include/llvm/Bitcode/NaCl/NaClFuzz.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===- NaClFuzz.h - Fuzz PNaCl bitcode records ------------------*- C++ -*-===//
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+
// This file defines a basic fuzzer for a list of PNaCl bitcode records.
11+
//
12+
// *** WARNING *** The implementation of the fuzzer uses a random
13+
// number generator. As a result, this code is not thread safe.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef LLVM_BITCODE_NACL_NACLFUZZ_H
18+
#define LLVM_BITCODE_NACL_NACLFUZZ_H
19+
20+
#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
21+
#include "llvm/Bitcode/NaCl/NaClRandNumGen.h"
22+
23+
namespace naclfuzz {
24+
25+
using namespace llvm;
26+
27+
/// \brief Fuzzes a list of editable bitcode records.
28+
class RecordFuzzer {
29+
RecordFuzzer(const RecordFuzzer&) = delete;
30+
void operator=(const RecordFuzzer&) = delete;
31+
public:
32+
typedef NaClMungedBitcode::iterator iterator;
33+
34+
/// \brief The set of possible fuzzing actions.
35+
enum EditAction {
36+
/// \brief Inserts a new record into the list of bitcode records.
37+
InsertRecord,
38+
/// \brief Mutate contents of an existing bitcode record.
39+
MutateRecord,
40+
/// \brief Removes an existing record from the list of bitcode
41+
/// records.
42+
RemoveRecord,
43+
/// \brief Replaces an existing record with a new bitcode record.
44+
ReplaceRecord,
45+
/// \brief Swaps two records in the bitcode record list.
46+
SwapRecord
47+
};
48+
49+
virtual ~RecordFuzzer();
50+
51+
/// \brief Generates a random mutation of the bitcode, using the
52+
/// provided random number generator. Percentage (a value between 0
53+
/// and 1 defined by Count/Base) is used to define the number of
54+
/// fuzzing actions applied to the bitcode. Returns true if fuzzing
55+
/// succeeded.
56+
///
57+
/// May be called an arbitrary number of times. Results are left in
58+
/// the munged bitcode records passed into static method
59+
/// createSimpleRecordFuzzer.
60+
virtual bool fuzz(unsigned Count, unsigned Base=100) = 0;
61+
62+
/// \brief Shows how many times each record was edited in the
63+
/// corresponding (input) bitcode, over all calls to fuzz.
64+
virtual void showRecordDistribution(raw_ostream &Out) const = 0;
65+
66+
/// \brief Shows how many times each type of edit action was applied
67+
/// to the corresponding bitcode, over all calls to fuzz.
68+
virtual void showEditDistribution(raw_ostream &Out) const = 0;
69+
70+
// Creates an instance of a fuzzer for the given bitcode.
71+
static RecordFuzzer
72+
*createSimpleRecordFuzzer(NaClMungedBitcode &Bitcode,
73+
RandomNumberGenerator &RandGenerator);
74+
75+
/// Returns printable name for the edit action.
76+
static const char *actionName(EditAction Action);
77+
78+
protected:
79+
RecordFuzzer(NaClMungedBitcode &Bitcode, RandomNumberGenerator &Generator);
80+
81+
// Holds the bitcode being munged.
82+
NaClMungedBitcode &Bitcode;
83+
84+
// Hold the random number generator.
85+
RandomNumberGenerator &Generator;
86+
87+
// Erases the last fuzzing result from the munged bitcode records
88+
// in Bitcode.
89+
virtual void clear();
90+
};
91+
92+
} // end of namespace naclfuzz
93+
94+
#endif // LLVM_BITCODE_NACL_NACLFUZZ_H
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===- NaClRandNumGen.h - random number generator ---------------*- C++ -*-===//
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+
// This file defines a random number generator API for 64-bit unsigned
11+
// values, and a corresponding default implementation.
12+
//
13+
// *** WARNING *** One should assume that random number generators are not
14+
// thread safe.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef LLVM_BITCODE_NACL_NACLRANDNUMGEN_H
19+
#define LLVM_BITCODE_NACL_NACLRANDNUMGEN_H
20+
21+
#include "llvm/ADT/StringRef.h"
22+
#include <random>
23+
24+
namespace naclfuzz {
25+
26+
/// Defines API for a random number generator to use with fuzzing.
27+
class RandomNumberGenerator {
28+
RandomNumberGenerator(const RandomNumberGenerator&) = delete;
29+
void operator=(const RandomNumberGenerator&) = delete;
30+
public:
31+
virtual ~RandomNumberGenerator();
32+
/// Returns a random number.
33+
virtual uint64_t operator()() = 0;
34+
// Returns a random value in [0..Limit)
35+
uint64_t chooseInRange(uint64_t Limit) {
36+
return (*this)() % Limit;
37+
}
38+
protected:
39+
RandomNumberGenerator() {}
40+
};
41+
42+
/// Defines a random number generator based on C++ generator std::mt19937_64.
43+
class DefaultRandomNumberGenerator : public RandomNumberGenerator {
44+
DefaultRandomNumberGenerator(const DefaultRandomNumberGenerator&) = delete;
45+
void operator=(const DefaultRandomNumberGenerator&) = delete;
46+
public:
47+
DefaultRandomNumberGenerator(llvm::StringRef Seed);
48+
uint64_t operator()() final;
49+
~DefaultRandomNumberGenerator() final {}
50+
// Resets random number seed by salting the seed of constructor with Salt.
51+
void saltSeed(uint64_t Salt);
52+
private:
53+
// 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000
54+
// http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
55+
// This RNG is deterministically portable across C++11
56+
// implementations.
57+
std::mt19937_64 Generator;
58+
// Seed for the random number generator.
59+
std::string Seed;
60+
};
61+
62+
} // end of namespace naclfuzz
63+
64+
#endif // LLVM_BITCODE_NACL_NACLRANDNUMGEN_H

lib/Bitcode/NaCl/TestUtils/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@ add_llvm_library(LLVMNaClBitTestUtils
33
NaClBitcodeMungeReader.cpp
44
NaClBitcodeMungeUtils.cpp
55
NaClBitcodeMungeWriter.cpp
6+
NaClFuzz.cpp
7+
NaClRandNumGen.cpp
8+
NaClSimpleRecordFuzzer.cpp
69
)
710
add_dependencies(LLVMNaClBitTestUtils intrinsics_gen)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===- NaClFuzz.cpp - Fuzz PNaCl bitcode records --------------------------===//
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+
// This file implements a basic fuzzer for a list of PNaCl bitcode records.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/ADT/STLExtras.h"
15+
#include "llvm/Bitcode/NaCl/NaClFuzz.h"
16+
17+
using namespace llvm;
18+
19+
namespace {
20+
21+
// Names for edit actions.
22+
const char *ActionNameArray[] = {
23+
"Insert",
24+
"Mutate",
25+
"Remove",
26+
"Replace",
27+
"Swap"
28+
};
29+
30+
} // end of anonymous namespace
31+
32+
namespace naclfuzz {
33+
34+
const char *RecordFuzzer::actionName(EditAction Action) {
35+
return Action < array_lengthof(ActionNameArray)
36+
? ActionNameArray[Action] : "???";
37+
}
38+
39+
RecordFuzzer::RecordFuzzer(NaClMungedBitcode &Bitcode,
40+
RandomNumberGenerator &Generator)
41+
: Bitcode(Bitcode), Generator(Generator) {
42+
if (Bitcode.getBaseRecords().empty())
43+
report_fatal_error(
44+
"Sorry, the fuzzer doesn't know how to fuzz an empty record list");
45+
}
46+
47+
RecordFuzzer::~RecordFuzzer() {}
48+
49+
void RecordFuzzer::clear() {
50+
Bitcode.removeEdits();
51+
}
52+
53+
} // end of namespace naclfuzz
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===- NaClRandNumGen.cpp - Random number generator -----------------------===//
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+
// This file provides a default implementation of a random number generator.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/Bitcode/NaCl/NaClRandNumGen.h"
15+
16+
#include <vector>
17+
#include <algorithm>
18+
19+
namespace naclfuzz {
20+
21+
// Put destructor in .cpp file guarantee vtable construction.
22+
RandomNumberGenerator::~RandomNumberGenerator() {}
23+
24+
DefaultRandomNumberGenerator::DefaultRandomNumberGenerator(llvm::StringRef Seed)
25+
: Seed(Seed) {
26+
saltSeed(0);
27+
}
28+
29+
uint64_t DefaultRandomNumberGenerator::operator()() {
30+
return Generator();
31+
}
32+
33+
void DefaultRandomNumberGenerator::saltSeed(uint64_t Salt) {
34+
// Combine seed and salt and pass to generator.
35+
std::vector<uint32_t> Data;
36+
Data.reserve(Seed.size() + 2);
37+
Data.push_back(static_cast<uint32_t>(Salt));
38+
Data.push_back(static_cast<uint32_t>(Salt >> 32));
39+
std::copy(Seed.begin(), Seed.end(), Data.end());
40+
std::seed_seq SeedSeq(Data.begin(), Data.end());
41+
Generator.seed(SeedSeq);
42+
}
43+
44+
} // end of namespace naclfuzz

0 commit comments

Comments
 (0)