Skip to content

Commit e9f2eda

Browse files
xinhaoyuancopybara-github
authored andcommitted
Track the mutant origin.
This is to enable input reduction (replacing corpus input with smaller mutants if the coverage matches) and corpus mutation stats for new scheduling methods. PiperOrigin-RevId: 821630139
1 parent d8e979e commit e9f2eda

46 files changed

Lines changed: 612 additions & 424 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

centipede/BUILD

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ cc_library(
366366
deps = [
367367
":centipede_callbacks",
368368
":environment",
369-
":mutation_input",
369+
":mutation_data",
370370
":runner_result",
371371
":stop",
372372
":thread_pool",
@@ -439,6 +439,7 @@ cc_library(
439439
# used in centipede_runner.
440440
":feature",
441441
":execution_metadata",
442+
":mutation_data",
442443
":shared_memory_blob_sequence",
443444
"@com_google_fuzztest//common:defs",
444445
],
@@ -454,14 +455,14 @@ cc_library(
454455
# used in centipede_runner.
455456
":shared_memory_blob_sequence",
456457
":execution_metadata",
457-
":mutation_input",
458+
":mutation_data",
458459
"@com_google_fuzztest//common:defs",
459460
],
460461
)
461462

462463
cc_library(
463-
name = "mutation_input",
464-
hdrs = ["mutation_input.h"],
464+
name = "mutation_data",
465+
hdrs = ["mutation_data.h"],
465466
copts = DISABLE_SANCOV_COPTS,
466467
deps = [
467468
# This target must have a minimal set of dependencies since it is
@@ -480,7 +481,7 @@ cc_library(
480481
deps = [
481482
":execution_metadata",
482483
":knobs",
483-
":mutation_input",
484+
":mutation_data",
484485
"@abseil-cpp//absl/base:nullability",
485486
"@com_google_fuzztest//common:defs",
486487
],
@@ -624,7 +625,7 @@ cc_library(
624625
":control_flow",
625626
":environment",
626627
":fuzztest_mutator",
627-
":mutation_input",
628+
":mutation_data",
628629
":runner_request",
629630
":runner_result",
630631
":shared_memory_blob_sequence",
@@ -716,7 +717,7 @@ cc_library(
716717
":environment",
717718
":feature",
718719
":feature_set",
719-
":mutation_input",
720+
":mutation_data",
720721
":pc_info",
721722
":runner_result",
722723
":rusage_profiler",
@@ -852,7 +853,7 @@ cc_library(
852853
deps = [
853854
":centipede_callbacks",
854855
":environment",
855-
":mutation_input",
856+
":mutation_data",
856857
":runner_result",
857858
":stop",
858859
"@abseil-cpp//absl/status",
@@ -870,7 +871,7 @@ cc_library(
870871
":byte_array_mutator",
871872
":execution_metadata",
872873
":knobs",
873-
":mutation_input",
874+
":mutation_data",
874875
"@abseil-cpp//absl/random",
875876
"@abseil-cpp//absl/types:span",
876877
"@com_google_fuzztest//common:defs",
@@ -938,6 +939,7 @@ cc_library(
938939
name = "runner_cmp_trace",
939940
hdrs = ["runner_cmp_trace.h"],
940941
copts = DISABLE_SANCOV_COPTS,
942+
deps = ["@abseil-cpp//absl/base:core_headers"],
941943
)
942944

943945
# Library for manipulating centipede runner flags. This is not used by the
@@ -955,6 +957,7 @@ cc_library(
955957
hdrs = ["dispatcher.h"],
956958
deps = [
957959
":execution_metadata",
960+
":mutation_data",
958961
":runner_request",
959962
":runner_result",
960963
":shared_memory_blob_sequence",
@@ -1030,7 +1033,7 @@ RUNNER_DEPS = [
10301033
":foreach_nonzero",
10311034
":int_utils",
10321035
":knobs",
1033-
":mutation_input",
1036+
":mutation_data",
10341037
":rolling_hash",
10351038
":runner_cmp_trace",
10361039
":runner_fork_server",
@@ -1095,7 +1098,7 @@ cc_library(
10951098
linkstatic = True, # Must be linked statically even when dynamic_mode=on.
10961099
deps = [
10971100
":centipede_runner_no_main",
1098-
":mutation_input",
1101+
":mutation_data",
10991102
"@abseil-cpp//absl/base:nullability",
11001103
"@com_google_fuzztest//common:defs",
11011104
],
@@ -1234,7 +1237,7 @@ cc_library(
12341237
":corpus",
12351238
":environment",
12361239
":feature",
1237-
":mutation_input",
1240+
":mutation_data",
12381241
":runner_result",
12391242
":util",
12401243
"@com_google_fuzztest//common:defs",
@@ -1506,6 +1509,7 @@ cc_test(
15061509
deps = [
15071510
":execution_metadata",
15081511
":feature",
1512+
":mutation_data",
15091513
":runner_result",
15101514
":shared_memory_blob_sequence",
15111515
"@com_google_fuzztest//common:defs",
@@ -1515,10 +1519,10 @@ cc_test(
15151519
)
15161520

15171521
cc_test(
1518-
name = "mutation_input_test",
1519-
srcs = ["mutation_input_test.cc"],
1522+
name = "mutation_data_test",
1523+
srcs = ["mutation_data_test.cc"],
15201524
deps = [
1521-
":mutation_input",
1525+
":mutation_data",
15221526
"@com_google_fuzztest//common:defs",
15231527
"@googletest//:gtest_main",
15241528
],
@@ -1531,7 +1535,7 @@ cc_test(
15311535
":byte_array_mutator",
15321536
":execution_metadata",
15331537
":knobs",
1534-
":mutation_input",
1538+
":mutation_data",
15351539
":runner_cmp_trace",
15361540
"@abseil-cpp//absl/container:flat_hash_set",
15371541
"@com_google_fuzztest//common:defs",
@@ -1564,7 +1568,7 @@ cc_test(
15641568
":execution_metadata",
15651569
":fuzztest_mutator",
15661570
":knobs",
1567-
":mutation_input",
1571+
":mutation_data",
15681572
"@abseil-cpp//absl/container:flat_hash_set",
15691573
"@abseil-cpp//absl/strings",
15701574
"@com_google_fuzztest//common:defs",
@@ -1911,7 +1915,7 @@ cc_test(
19111915
":centipede_interface",
19121916
":environment",
19131917
":feature",
1914-
":mutation_input",
1918+
":mutation_data",
19151919
":runner_result",
19161920
":stop",
19171921
":util",

centipede/byte_array_mutator.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
#include "./centipede/execution_metadata.h"
2626
#include "./centipede/knobs.h"
27-
#include "./centipede/mutation_input.h"
27+
#include "./centipede/mutation_data.h"
2828
#include "./common/defs.h"
2929

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

324-
std::vector<ByteArray> ByteArrayMutator::MutateMany(
325-
const std::vector<MutationInputRef> &inputs, size_t num_mutants) {
324+
std::vector<Mutant> ByteArrayMutator::MutateMany(
325+
const std::vector<MutationInputRef>& inputs, size_t num_mutants) {
326326
if (inputs.empty()) abort();
327327
// TODO(xinhaoyuan): Consider metadata in other inputs instead of always the
328328
// first one.
329329
SetMetadata(inputs[0].metadata != nullptr ? *inputs[0].metadata
330330
: ExecutionMetadata());
331331
size_t num_inputs = inputs.size();
332-
std::vector<ByteArray> mutants;
332+
std::vector<Mutant> mutants;
333333
mutants.reserve(num_mutants);
334334
for (size_t i = 0; i < num_mutants; ++i) {
335-
auto mutant = inputs[rng_() % num_inputs].data;
336-
if (mutant.size() <= max_len_ &&
335+
Mutant mutant;
336+
mutant.origin = rng_() % num_inputs;
337+
mutant.data = inputs[mutant.origin].data;
338+
if (mutant.data.size() <= max_len_ &&
337339
knobs_.GenerateBool(knob_mutate_or_crossover, rng_())) {
338340
// Do crossover only if the mutant is not over the max_len_.
339341
// Perform crossover with some other input. It may be the same input.
340342
const auto &other_input = inputs[rng_() % num_inputs].data;
341-
CrossOver(mutant, other_input);
343+
CrossOver(mutant.data, other_input);
342344
} else {
343345
// Perform mutation.
344-
Mutate(mutant);
346+
Mutate(mutant.data);
345347
}
346348
mutants.push_back(std::move(mutant));
347349
}

centipede/byte_array_mutator.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
#include "absl/base/nullability.h"
2626
#include "./centipede/execution_metadata.h"
2727
#include "./centipede/knobs.h"
28-
#include "./centipede/mutation_input.h"
28+
#include "./centipede/mutation_data.h"
2929
#include "./common/defs.h"
3030

3131
namespace fuzztest::internal {
3232

3333
// A simple class representing an array of up to kMaxEntrySize bytes.
3434
class DictEntry {
3535
public:
36-
static constexpr uint8_t kMaxEntrySize = 16;
36+
static constexpr uint8_t kMaxEntrySize = 128;
3737

3838
explicit DictEntry(ByteSpan bytes)
3939
: bytes_{}, // initialize bytes_ to all zeros
@@ -108,8 +108,8 @@ class ByteArrayMutator {
108108
}
109109

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

114114
using CrossOverFn = void (ByteArrayMutator::*)(ByteArray &,
115115
const ByteArray &);

centipede/byte_array_mutator_test.cc

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
#include <cstdint>
1919
#include <cstring>
2020
#include <limits>
21+
#include <numeric>
2122
#include <vector>
2223

2324
#include "gmock/gmock.h"
2425
#include "gtest/gtest.h"
2526
#include "absl/container/flat_hash_set.h"
2627
#include "./centipede/execution_metadata.h"
2728
#include "./centipede/knobs.h"
28-
#include "./centipede/mutation_input.h"
29+
#include "./centipede/mutation_data.h"
2930
#include "./centipede/runner_cmp_trace.h"
3031
#include "./common/defs.h"
3132

@@ -93,8 +94,9 @@ TEST(ByteArrayMutator, RoundDownToRemoveCorrectly) {
9394
namespace {
9495

9596
TEST(DictEntry, DictEntry) {
96-
uint8_t bytes[17] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
97-
9, 10, 11, 12, 13, 14, 15, 16};
97+
uint8_t bytes[129];
98+
std::iota(bytes, bytes + 129, 0);
99+
98100
DictEntry a_0_10({bytes + 0, 10});
99101
DictEntry a_0_4({bytes + 0, 4});
100102
DictEntry a_1_8({bytes + 1, 8});
@@ -103,7 +105,7 @@ TEST(DictEntry, DictEntry) {
103105
EXPECT_LT(a_0_10, a_1_8);
104106
EXPECT_EQ(memcmp(a_0_10.begin(), bytes, a_0_10.end() - a_0_10.begin()), 0);
105107

106-
EXPECT_DEATH({ DictEntry a_0_10({bytes, 17}); }, "");
108+
EXPECT_DEATH({ DictEntry a_0_10({bytes, 129}); }, "");
107109
}
108110

109111
TEST(CmpDictionary, CmpDictionary) {
@@ -158,11 +160,11 @@ TEST(CmpDictionary, CmpDictionary) {
158160
}
159161

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

167169
ExecutionMetadata metadata;
168170
bool append_failed = false;
@@ -928,12 +930,12 @@ TEST(ByteArrayMutator, MutateManyWithAlignedInputs) {
928930
{0, 1, 2, 3, 4, 5, 6, 7},
929931
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
930932
};
931-
const std::vector<ByteArray> mutants =
933+
const std::vector<Mutant> mutants =
932934
mutator.MutateMany(GetMutationInputRefsFromDataInputs(aligned_inputs),
933935
kNumMutantsToGenerate);
934936
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);
935-
for (const ByteArray &mutant : mutants) {
936-
EXPECT_EQ(mutant.size() % kSizeAlignment, 0);
937+
for (const Mutant& mutant : mutants) {
938+
EXPECT_EQ(mutant.data.size() % kSizeAlignment, 0);
937939
}
938940
}
939941

@@ -958,13 +960,13 @@ TEST(ByteArrayMutator, MutateManyWithUnalignedInputs) {
958960
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
959961
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
960962
};
961-
const std::vector<ByteArray> mutants =
963+
const std::vector<Mutant> mutants =
962964
mutator.MutateMany(GetMutationInputRefsFromDataInputs(unaligned_inputs),
963965
kNumMutantsToGenerate);
964966
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);
965-
for (const ByteArray &mutant : mutants) {
966-
if (mutant.size() % kSizeAlignment != 0) {
967-
EXPECT_LE(mutant.size(), 11);
967+
for (const Mutant& mutant : mutants) {
968+
if (mutant.data.size() % kSizeAlignment != 0) {
969+
EXPECT_LE(mutant.data.size(), 11);
968970
}
969971
}
970972
}
@@ -982,12 +984,12 @@ TEST(ByteArrayMutator, MutateManyWithMaxLen) {
982984
{0, 1, 2},
983985
{0, 1, 2, 3},
984986
};
985-
const std::vector<ByteArray> mutants = mutator.MutateMany(
987+
const std::vector<Mutant> mutants = mutator.MutateMany(
986988
GetMutationInputRefsFromDataInputs(inputs), kNumMutantsToGenerate);
987989
EXPECT_EQ(mutants.size(), kNumMutantsToGenerate);
988990

989-
for (const ByteArray &mutant : mutants) {
990-
EXPECT_LE(mutant.size(), kMaxLen);
991+
for (const Mutant& mutant : mutants) {
992+
EXPECT_LE(mutant.data.size(), kMaxLen);
991993
}
992994
}
993995

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

1008-
for (const ByteArray &mutant : mutants) {
1009-
if (mutant.size() > kMaxLen) {
1010+
for (const Mutant& mutant : mutants) {
1011+
if (mutant.data.size() > kMaxLen) {
10101012
// The only mutant larger than max length should be the same large input
10111013
// that mutation originally started with. All other mutants should be
10121014
// within the maximum length specified.
1013-
EXPECT_EQ(mutant, large_input[0]);
1015+
EXPECT_EQ(mutant.data, large_input[0]);
10141016
}
10151017
}
10161018
}

0 commit comments

Comments
 (0)