Skip to content

Commit

Permalink
Move random number generator inside of Mutator.
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalybuka committed Sep 1, 2019
1 parent 315e6d2 commit 379f5ab
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 38 deletions.
8 changes: 4 additions & 4 deletions src/libfuzzer/libfuzzer_macro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class BinaryOutputWriter : public OutputWriter {

size_t MutateMessage(unsigned int seed, const InputReader& input,
OutputWriter* output, protobuf::Message* message) {
RandomEngine random(seed);
Mutator mutator(&random);
Mutator mutator;
mutator.Seed(seed);
input.Read(message);
mutator.Mutate(message, output->size() > input.size()
? (output->size() - input.size())
Expand All @@ -108,8 +108,8 @@ size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
const InputReader& input2, OutputWriter* output,
protobuf::Message* message1,
protobuf::Message* message2) {
RandomEngine random(seed);
Mutator mutator(&random);
Mutator mutator;
mutator.Seed(seed);
input1.Read(message1);
input2.Read(message2);
mutator.CrossOver(*message2, message1);
Expand Down
57 changes: 28 additions & 29 deletions src/mutator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -448,13 +448,13 @@ struct CreateField : public FieldFunction<CreateField> {

} // namespace

Mutator::Mutator(RandomEngine* random) : random_(random) {}
void Mutator::Seed(uint32_t value) { random_.seed(value); }

void Mutator::Mutate(Message* message, size_t size_increase_hint) {
bool repeat;
do {
repeat = false;
MutationSampler mutation(keep_initialized_, random_, message);
MutationSampler mutation(keep_initialized_, &random_, message);
switch (mutation.mutation()) {
case Mutation::None:
break;
Expand All @@ -470,7 +470,7 @@ void Mutator::Mutate(Message* message, size_t size_increase_hint) {
DeleteField()(mutation.field());
break;
case Mutation::Copy: {
DataSourceSampler source(mutation.field(), random_, message);
DataSourceSampler source(mutation.field(), &random_, message);
if (source.IsEmpty()) {
repeat = true;
break;
Expand Down Expand Up @@ -530,20 +530,20 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,

// Shuffle
for (int j = 0; j < field_size2; ++j) {
if (int k = GetRandomIndex(random_, field_size2 - j)) {
if (int k = GetRandomIndex(&random_, field_size2 - j)) {
reflection->SwapElements(message2, field, j, j + k);
}
}

int keep = GetRandomIndex(random_, field_size2 + 1);
int keep = GetRandomIndex(&random_, field_size2 + 1);

if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
int remove = field_size2 - keep;
// Cross some message to keep with messages to remove.
int cross = GetRandomIndex(random_, std::min(keep, remove) + 1);
int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
for (int j = 0; j < cross; ++j) {
int k = GetRandomIndex(random_, keep);
int r = keep + GetRandomIndex(random_, remove);
int k = GetRandomIndex(&random_, keep);
int r = keep + GetRandomIndex(&random_, remove);
assert(k != r);
CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
reflection->MutableRepeatedMessage(message2, field, k));
Expand All @@ -556,10 +556,10 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,

} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (!reflection->HasField(message1, field)) {
if (GetRandomBool(random_))
if (GetRandomBool(&random_))
DeleteField()(FieldInstance(message2, field));
} else if (!reflection->HasField(*message2, field)) {
if (GetRandomBool(random_)) {
if (GetRandomBool(&random_)) {
ConstFieldInstance source(&message1, field);
CopyField()(source, FieldInstance(message2, field));
}
Expand All @@ -568,7 +568,7 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,
reflection->MutableMessage(message2, field));
}
} else {
if (GetRandomBool(random_)) {
if (GetRandomBool(&random_)) {
if (reflection->HasField(message1, field)) {
ConstFieldInstance source(&message1, field);
CopyField()(source, FieldInstance(message2, field));
Expand Down Expand Up @@ -623,58 +623,58 @@ void Mutator::InitializeAndTrim(Message* message, int max_depth) {
}
}

int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, random_); }
int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }

int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, random_); }
int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }

uint32_t Mutator::MutateUInt32(uint32_t value) {
return FlipBit(value, random_);
return FlipBit(value, &random_);
}

uint64_t Mutator::MutateUInt64(uint64_t value) {
return FlipBit(value, random_);
return FlipBit(value, &random_);
}

float Mutator::MutateFloat(float value) { return FlipBit(value, random_); }
float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }

double Mutator::MutateDouble(double value) { return FlipBit(value, random_); }
double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }

bool Mutator::MutateBool(bool value) { return !value; }

size_t Mutator::MutateEnum(size_t index, size_t item_count) {
if (item_count <= 1) return 0;
return (index + 1 + GetRandomIndex(random_, item_count - 1)) % item_count;
return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
}

std::string Mutator::MutateString(const std::string& value,
size_t size_increase_hint) {
std::string result = value;

while (!result.empty() && GetRandomBool(random_)) {
result.erase(GetRandomIndex(random_, result.size()), 1);
while (!result.empty() && GetRandomBool(&random_)) {
result.erase(GetRandomIndex(&random_, result.size()), 1);
}

while (result.size() < size_increase_hint && GetRandomBool(random_)) {
size_t index = GetRandomIndex(random_, result.size() + 1);
result.insert(result.begin() + index, GetRandomIndex(random_, 1 << 8));
while (result.size() < size_increase_hint && GetRandomBool(&random_)) {
size_t index = GetRandomIndex(&random_, result.size() + 1);
result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
}

if (result != value) return result;

if (result.empty()) {
result.push_back(GetRandomIndex(random_, 1 << 8));
result.push_back(GetRandomIndex(&random_, 1 << 8));
return result;
}

if (!result.empty())
FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), random_);
FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
return result;
}

std::string Mutator::MutateUtf8String(const std::string& value,
size_t size_increase_hint) {
std::string str = MutateString(value, size_increase_hint);
FixUtf8String(&str, random_);
FixUtf8String(&str, &random_);
return str;
}

Expand All @@ -686,12 +686,11 @@ bool Mutator::ApplyCustomMutations(protobuf::Message* message,

// Randomly select one of the registered mutators. The default behavior is
// performed for index 0.
size_t field_index = GetRandomIndex(random_, itr->second.size() + 1);
size_t field_index = GetRandomIndex(&random_, itr->second.size() + 1);
if (field_index == itr->second.size())
return false;

if (GetRandomBool(random_, 100))
itr->second[field_index](message);
if (GetRandomBool(&random_, 100)) itr->second[field_index](message);
return true;
}

Expand Down
9 changes: 6 additions & 3 deletions src/mutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ namespace protobuf_mutator {
class Mutator {
public:
// seed: value to initialize random number generator.
explicit Mutator(RandomEngine* random);
Mutator() = default;
virtual ~Mutator() = default;

// Initialized internal random number generator.
void Seed(uint32_t value);

// message: message to mutate.
// size_increase_hint: approximate number of bytes which can be added to the
// message. Method does not guarantee that real result size increase will be
Expand Down Expand Up @@ -82,7 +85,7 @@ class Mutator {
// * Callbacks to recursive traversal.
// * Callbacks for particular proto level mutations.

RandomEngine* random() { return random_; }
RandomEngine* random() { return &random_; }

static std::unordered_map<
const protobuf::FieldDescriptor*,
Expand All @@ -101,7 +104,7 @@ class Mutator {
const protobuf::FieldDescriptor* field);
bool keep_initialized_ = true;
size_t random_to_default_ratio_ = 100;
RandomEngine* random_;
RandomEngine random_;
};

} // namespace protobuf_mutator
Expand Down
4 changes: 2 additions & 2 deletions src/mutator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ const char kRepeatedNestedFields[] = R"(
class TestMutator : public Mutator {
public:
explicit TestMutator(bool keep_initialized,
size_t random_to_default_ratio = 0)
: Mutator(&random_), random_(17) {
size_t random_to_default_ratio = 0) {
Seed(17);
if (random_to_default_ratio)
random_to_default_ratio_ = random_to_default_ratio;
keep_initialized_ = keep_initialized;
Expand Down

0 comments on commit 379f5ab

Please sign in to comment.