Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions centipede/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ cc_library(
deps = [
":centipede_callbacks",
":environment",
":mutation_input",
":mutation_data",
":runner_result",
":stop",
":thread_pool",
Expand Down Expand Up @@ -439,6 +439,7 @@ cc_library(
# used in centipede_runner.
":feature",
":execution_metadata",
":mutation_data",
":shared_memory_blob_sequence",
"@com_google_fuzztest//common:defs",
],
Expand All @@ -454,14 +455,14 @@ cc_library(
# used in centipede_runner.
":shared_memory_blob_sequence",
":execution_metadata",
":mutation_input",
":mutation_data",
"@com_google_fuzztest//common:defs",
],
)

cc_library(
name = "mutation_input",
hdrs = ["mutation_input.h"],
name = "mutation_data",
hdrs = ["mutation_data.h"],
copts = DISABLE_SANCOV_COPTS,
deps = [
# This target must have a minimal set of dependencies since it is
Expand All @@ -480,7 +481,7 @@ cc_library(
deps = [
":execution_metadata",
":knobs",
":mutation_input",
":mutation_data",
"@abseil-cpp//absl/base:nullability",
"@com_google_fuzztest//common:defs",
],
Expand Down Expand Up @@ -624,7 +625,7 @@ cc_library(
":control_flow",
":environment",
":fuzztest_mutator",
":mutation_input",
":mutation_data",
":runner_request",
":runner_result",
":shared_memory_blob_sequence",
Expand Down Expand Up @@ -716,7 +717,7 @@ cc_library(
":environment",
":feature",
":feature_set",
":mutation_input",
":mutation_data",
":pc_info",
":runner_result",
":rusage_profiler",
Expand Down Expand Up @@ -852,7 +853,7 @@ cc_library(
deps = [
":centipede_callbacks",
":environment",
":mutation_input",
":mutation_data",
":runner_result",
":stop",
"@abseil-cpp//absl/status",
Expand All @@ -870,7 +871,7 @@ cc_library(
":byte_array_mutator",
":execution_metadata",
":knobs",
":mutation_input",
":mutation_data",
"@abseil-cpp//absl/random",
"@abseil-cpp//absl/types:span",
"@com_google_fuzztest//common:defs",
Expand Down Expand Up @@ -938,6 +939,7 @@ cc_library(
name = "runner_cmp_trace",
hdrs = ["runner_cmp_trace.h"],
copts = DISABLE_SANCOV_COPTS,
deps = ["@abseil-cpp//absl/base:core_headers"],
)

# Library for manipulating centipede runner flags. This is not used by the
Expand Down Expand Up @@ -1030,7 +1032,7 @@ RUNNER_DEPS = [
":foreach_nonzero",
":int_utils",
":knobs",
":mutation_input",
":mutation_data",
":rolling_hash",
":runner_cmp_trace",
":runner_fork_server",
Expand Down Expand Up @@ -1095,7 +1097,7 @@ cc_library(
linkstatic = True, # Must be linked statically even when dynamic_mode=on.
deps = [
":centipede_runner_no_main",
":mutation_input",
":mutation_data",
"@abseil-cpp//absl/base:nullability",
"@com_google_fuzztest//common:defs",
],
Expand Down Expand Up @@ -1234,7 +1236,7 @@ cc_library(
":corpus",
":environment",
":feature",
":mutation_input",
":mutation_data",
":runner_result",
":util",
"@com_google_fuzztest//common:defs",
Expand Down Expand Up @@ -1506,6 +1508,7 @@ cc_test(
deps = [
":execution_metadata",
":feature",
":mutation_data",
":runner_result",
":shared_memory_blob_sequence",
"@com_google_fuzztest//common:defs",
Expand All @@ -1515,10 +1518,10 @@ cc_test(
)

cc_test(
name = "mutation_input_test",
srcs = ["mutation_input_test.cc"],
name = "mutation_data_test",
srcs = ["mutation_data_test.cc"],
deps = [
":mutation_input",
":mutation_data",
"@com_google_fuzztest//common:defs",
"@googletest//:gtest_main",
],
Expand All @@ -1531,7 +1534,7 @@ cc_test(
":byte_array_mutator",
":execution_metadata",
":knobs",
":mutation_input",
":mutation_data",
":runner_cmp_trace",
"@abseil-cpp//absl/container:flat_hash_set",
"@com_google_fuzztest//common:defs",
Expand Down Expand Up @@ -1564,7 +1567,7 @@ cc_test(
":execution_metadata",
":fuzztest_mutator",
":knobs",
":mutation_input",
":mutation_data",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/strings",
"@com_google_fuzztest//common:defs",
Expand Down Expand Up @@ -1911,7 +1914,7 @@ cc_test(
":centipede_interface",
":environment",
":feature",
":mutation_input",
":mutation_data",
":runner_result",
":stop",
":util",
Expand Down
17 changes: 9 additions & 8 deletions centipede/byte_array_mutator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include "./centipede/execution_metadata.h"
#include "./centipede/knobs.h"
#include "./centipede/mutation_input.h"
#include "./centipede/mutation_data.h"
#include "./common/defs.h"

namespace fuzztest::internal {
Expand Down Expand Up @@ -321,27 +321,28 @@ void ByteArrayMutator::CrossOver(ByteArray &data, const ByteArray &other) {
// TODO(kcc): add tests with different values of knobs.
const KnobId knob_mutate_or_crossover = Knobs::NewId("mutate_or_crossover");

std::vector<ByteArray> ByteArrayMutator::MutateMany(
const std::vector<MutationInputRef> &inputs, size_t num_mutants) {
std::vector<Mutant> ByteArrayMutator::MutateMany(
const std::vector<MutationInputRef>& inputs, size_t num_mutants) {
if (inputs.empty()) abort();
// TODO(xinhaoyuan): Consider metadata in other inputs instead of always the
// first one.
SetMetadata(inputs[0].metadata != nullptr ? *inputs[0].metadata
: ExecutionMetadata());
size_t num_inputs = inputs.size();
std::vector<ByteArray> mutants;
std::vector<Mutant> mutants;
mutants.reserve(num_mutants);
for (size_t i = 0; i < num_mutants; ++i) {
auto mutant = inputs[rng_() % num_inputs].data;
if (mutant.size() <= max_len_ &&
Mutant mutant;
mutant.data = inputs[rng_() % num_inputs].data;
if (mutant.data.size() <= max_len_ &&
knobs_.GenerateBool(knob_mutate_or_crossover, rng_())) {
// Do crossover only if the mutant is not over the max_len_.
// Perform crossover with some other input. It may be the same input.
const auto &other_input = inputs[rng_() % num_inputs].data;
CrossOver(mutant, other_input);
CrossOver(mutant.data, other_input);
} else {
// Perform mutation.
Mutate(mutant);
Mutate(mutant.data);
}
mutants.push_back(std::move(mutant));
}
Expand Down
8 changes: 4 additions & 4 deletions centipede/byte_array_mutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
#include "absl/base/nullability.h"
#include "./centipede/execution_metadata.h"
#include "./centipede/knobs.h"
#include "./centipede/mutation_input.h"
#include "./centipede/mutation_data.h"
#include "./common/defs.h"

namespace fuzztest::internal {

// A simple class representing an array of up to kMaxEntrySize bytes.
class DictEntry {
public:
static constexpr uint8_t kMaxEntrySize = 16;
static constexpr uint8_t kMaxEntrySize = 128;

explicit DictEntry(ByteSpan bytes)
: bytes_{}, // initialize bytes_ to all zeros
Expand Down Expand Up @@ -108,8 +108,8 @@ class ByteArrayMutator {
}

// Takes non-empty `inputs` and produces `num_mutants` mutants.
std::vector<ByteArray> MutateMany(const std::vector<MutationInputRef> &inputs,
size_t num_mutants);
std::vector<Mutant> MutateMany(const std::vector<MutationInputRef>& inputs,
size_t num_mutants);

using CrossOverFn = void (ByteArrayMutator::*)(ByteArray &,
const ByteArray &);
Expand Down
42 changes: 22 additions & 20 deletions centipede/byte_array_mutator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
#include <cstdint>
#include <cstring>
#include <limits>
#include <numeric>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/flat_hash_set.h"
#include "./centipede/execution_metadata.h"
#include "./centipede/knobs.h"
#include "./centipede/mutation_input.h"
#include "./centipede/mutation_data.h"
#include "./centipede/runner_cmp_trace.h"
#include "./common/defs.h"

Expand Down Expand Up @@ -93,8 +94,9 @@ TEST(ByteArrayMutator, RoundDownToRemoveCorrectly) {
namespace {

TEST(DictEntry, DictEntry) {
uint8_t bytes[17] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16};
uint8_t bytes[129];
std::iota(bytes, bytes + 129, 0);

DictEntry a_0_10({bytes + 0, 10});
DictEntry a_0_4({bytes + 0, 4});
DictEntry a_1_8({bytes + 1, 8});
Expand All @@ -103,7 +105,7 @@ TEST(DictEntry, DictEntry) {
EXPECT_LT(a_0_10, a_1_8);
EXPECT_EQ(memcmp(a_0_10.begin(), bytes, a_0_10.end() - a_0_10.begin()), 0);

EXPECT_DEATH({ DictEntry a_0_10({bytes, 17}); }, "");
EXPECT_DEATH({ DictEntry a_0_10({bytes, 129}); }, "");
}

TEST(CmpDictionary, CmpDictionary) {
Expand Down Expand Up @@ -158,11 +160,11 @@ TEST(CmpDictionary, CmpDictionary) {
}

TEST(CmpDictionary, CmpDictionaryIsCompatibleWithCmpTrace) {
CmpTrace<0, 13> traceN;
CmpTrace<0, 13> traceN = {};
traceN.Clear();
constexpr uint8_t long_array[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
traceN.Capture(20, long_array, long_array); // will be trimmed to 16.
traceN.Capture(20, long_array, long_array);

ExecutionMetadata metadata;
bool append_failed = false;
Expand Down Expand Up @@ -928,12 +930,12 @@ TEST(ByteArrayMutator, MutateManyWithAlignedInputs) {
{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
};
const std::vector<ByteArray> mutants =
const std::vector<Mutant> mutants =
mutator.MutateMany(GetMutationInputRefsFromDataInputs(aligned_inputs),
kNumMutantsToGenerate);
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);
for (const ByteArray &mutant : mutants) {
EXPECT_EQ(mutant.size() % kSizeAlignment, 0);
for (const Mutant& mutant : mutants) {
EXPECT_EQ(mutant.data.size() % kSizeAlignment, 0);
}
}

Expand All @@ -958,13 +960,13 @@ TEST(ByteArrayMutator, MutateManyWithUnalignedInputs) {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
};
const std::vector<ByteArray> mutants =
const std::vector<Mutant> mutants =
mutator.MutateMany(GetMutationInputRefsFromDataInputs(unaligned_inputs),
kNumMutantsToGenerate);
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);
for (const ByteArray &mutant : mutants) {
if (mutant.size() % kSizeAlignment != 0) {
EXPECT_LE(mutant.size(), 11);
for (const Mutant& mutant : mutants) {
if (mutant.data.size() % kSizeAlignment != 0) {
EXPECT_LE(mutant.data.size(), 11);
}
}
}
Expand All @@ -982,12 +984,12 @@ TEST(ByteArrayMutator, MutateManyWithMaxLen) {
{0, 1, 2},
{0, 1, 2, 3},
};
const std::vector<ByteArray> mutants = mutator.MutateMany(
const std::vector<Mutant> mutants = mutator.MutateMany(
GetMutationInputRefsFromDataInputs(inputs), kNumMutantsToGenerate);
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);

for (const ByteArray &mutant : mutants) {
EXPECT_LE(mutant.size(), kMaxLen);
for (const Mutant& mutant : mutants) {
EXPECT_LE(mutant.data.size(), kMaxLen);
}
}

Expand All @@ -1001,16 +1003,16 @@ TEST(ByteArrayMutator, MutateManyWithMaxLenWithStartingLargeInput) {
const std::vector<ByteArray> large_input = {
{0, 1, 2, 3, 4, 5, 6, 7}, {0}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3},
};
const std::vector<ByteArray> mutants = mutator.MutateMany(
const std::vector<Mutant> mutants = mutator.MutateMany(
GetMutationInputRefsFromDataInputs(large_input), kNumMutantsToGenerate);
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);

for (const ByteArray &mutant : mutants) {
if (mutant.size() > kMaxLen) {
for (const Mutant& mutant : mutants) {
if (mutant.data.size() > kMaxLen) {
// The only mutant larger than max length should be the same large input
// that mutation originally started with. All other mutants should be
// within the maximum length specified.
EXPECT_EQ(mutant, large_input[0]);
EXPECT_EQ(mutant.data, large_input[0]);
}
}
}
Expand Down
Loading
Loading