forked from google/centipede
-
Notifications
You must be signed in to change notification settings - Fork 5
/
centipede_callbacks.h
185 lines (159 loc) · 7.17 KB
/
centipede_callbacks.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2022 The Centipede Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_CENTIPEDE_CENTIPEDE_CALLBACKS_H_
#define THIRD_PARTY_CENTIPEDE_CENTIPEDE_CALLBACKS_H_
#include <cstddef>
#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
#include "./byte_array_mutator.h"
#include "./binary_info.h"
#include "./call_graph.h"
#include "./command.h"
#include "./control_flow.h"
#include "./defs.h"
#include "./environment.h"
#include "./execution_result.h"
#include "./knobs.h"
#include "./logging.h"
#include "./shared_memory_blob_sequence.h"
#include "./symbol_table.h"
#include "./util.h"
namespace centipede {
// User must inherit from this class and override at least the
// pure virtual functions.
//
// The classes inherited from this one must be thread-compatible.
// Note: the interface is not yet stable and may change w/o a notice.
class CentipedeCallbacks {
public:
// `env` is used to pass flags to `this`, it must outlive `this`.
CentipedeCallbacks(const Environment &env)
: env_(env),
byte_array_mutator_(env.knobs, GetRandomSeed(env.seed)),
inputs_blobseq_(shmem_name1_.c_str(), env.shmem_size_mb << 20),
outputs_blobseq_(shmem_name2_.c_str(), env.shmem_size_mb << 20) {
CHECK(byte_array_mutator_.set_max_len(env.max_len));
}
virtual ~CentipedeCallbacks() {}
// Feeds `inputs` into the `binary`, for every input populates `batch_result`.
// Old contents of `batch_result` are cleared.
// Returns true on success, false on failure.
// Post-condition:
// `batch_result` has results for every `input`, even on failure.
virtual bool Execute(std::string_view binary,
const std::vector<ByteArray> &inputs,
BatchResult &batch_result) = 0;
// Takes non-empty `inputs`, discards old contents of `mutants`,
// adds `num_mutants` mutated inputs to `mutants`.
virtual void Mutate(const std::vector<ByteArray> &inputs, size_t num_mutants,
std::vector<ByteArray> &mutants) = 0;
// Populates the BinaryInfo using the `symbolizer_path` and `coverage_binary`
// in `env_`. The tables may not be populated if the PC table cannot be
// determined from the `coverage_binary` or if symbolization fails. Exits if
// PC table was not populated and `env_.require_pc_table` is set.
virtual void PopulateBinaryInfo(BinaryInfo &binary_info);
// Returns some simple non-empty valid input.
virtual ByteArray DummyValidInput() { return {0}; }
// Sets the internal CmpDictionary to `cmp_data`.
// TODO(kcc): this is pretty ugly. Instead we need to pass `cmp_data`
// to Mutate() alongside with the inputs.
bool SetCmpDictionary(ByteSpan cmp_data) {
return byte_array_mutator_.SetCmpDictionary(cmp_data);
}
protected:
// Helpers that the user-defined class may use if needed.
// Same as ExecuteCentipedeSancovBinary, but uses shared memory.
// Much faster for fast targets since it uses fewer system calls.
int ExecuteCentipedeSancovBinaryWithShmem(
std::string_view binary, const std::vector<ByteArray> &inputs,
BatchResult &batch_result);
// Constructs a string CENTIPEDE_RUNNER_FLAGS=":flag1:flag2:...",
// where the flags are determined by `env` and also include `extra_flags`.
// If `disable_coverage`, coverage options are not added.
std::string ConstructRunnerFlags(std::string_view extra_flags = "",
bool disable_coverage = false);
// Uses an external binary `binary` to mutate `inputs`.
// The binary should be linked against :centipede_runner and
// implement the Structure-Aware Fuzzing interface, as described here:
// github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md
//
// Produces at most `mutants.size()` non-empty mutants,
// replacing the existing elements of `mutants`,
// and shrinking `mutants` if needed.
//
// Returns true on success.
bool MutateViaExternalBinary(std::string_view binary,
const std::vector<ByteArray> &inputs,
std::vector<ByteArray> &mutants);
// Loads the dictionary from `dictionary_path`,
// returns the number of dictionary entries loaded.
size_t LoadDictionary(std::string_view dictionary_path);
protected:
const Environment &env_;
ByteArrayMutator byte_array_mutator_;
private:
// Returns a Command object with matching `binary` from commands_,
// creates one if needed.
Command &GetOrCreateCommandForBinary(std::string_view binary);
// Variables required for ExecuteCentipedeSancovBinaryWithShmem.
// They are computed in CTOR, to avoid extra computation in the hot loop.
std::string temp_dir_ = TemporaryLocalDirPath();
std::string temp_input_file_path_ =
std::filesystem::path(temp_dir_).append("temp_input_file");
const std::string execute_log_path_ =
std::filesystem::path(temp_dir_).append("log");
std::string failure_description_path_ =
std::filesystem::path(temp_dir_).append("failure_description");
const std::string shmem_name1_ = ProcessAndThreadUniqueID("/centipede-shm1-");
const std::string shmem_name2_ = ProcessAndThreadUniqueID("/centipede-shm2-");
SharedMemoryBlobSequence inputs_blobseq_;
SharedMemoryBlobSequence outputs_blobseq_;
std::vector<Command> commands_;
};
// Abstract class for creating/destroying CentipedeCallbacks objects.
// A typical implementation would simply new/delete objects of appropriate type,
// see DefaultCallbacksFactory below.
// Other implementations (e.g. for tests) may take the object from elsewhere
// and not actually delete it.
class CentipedeCallbacksFactory {
public:
virtual CentipedeCallbacks *create(const Environment &env) = 0;
virtual void destroy(CentipedeCallbacks *callbacks) = 0;
virtual ~CentipedeCallbacksFactory() {}
};
// This is the typical way to implement a CentipedeCallbacksFactory for a Type.
template <typename Type>
class DefaultCallbacksFactory : public CentipedeCallbacksFactory {
public:
CentipedeCallbacks *create(const Environment &env) override {
return new Type(env);
}
void destroy(CentipedeCallbacks *callbacks) override { delete callbacks; }
};
// Creates a CentipedeCallbacks object in CTOR and destroys it in DTOR.
class ScopedCentipedeCallbacks {
public:
ScopedCentipedeCallbacks(CentipedeCallbacksFactory &factory,
const Environment &env)
: factory_(factory), callbacks_(factory_.create(env)) {}
~ScopedCentipedeCallbacks() { factory_.destroy(callbacks_); }
CentipedeCallbacks *callbacks() { return callbacks_; }
private:
CentipedeCallbacksFactory &factory_;
CentipedeCallbacks *callbacks_;
};
} // namespace centipede
#endif // THIRD_PARTY_CENTIPEDE_CENTIPEDE_CALLBACKS_H_