1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 // See https://llvm.org/LICENSE.txt for license information.
3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5 // Avoid ODR violations (LibFuzzer is built without ASan and this test is built
6 // with ASan) involving C++ standard library types when using libcxx.
7 #define _LIBCPP_HAS_NO_ASAN
8
9 // Do not attempt to use LLVM ostream etc from gtest.
10 #define GTEST_NO_LLVM_SUPPORT 1
11
12 #include "FuzzerCorpus.h"
13 #include "FuzzerDictionary.h"
14 #include "FuzzerInternal.h"
15 #include "FuzzerMerge.h"
16 #include "FuzzerMutate.h"
17 #include "FuzzerRandom.h"
18 #include "FuzzerTracePC.h"
19 #include "gtest/gtest.h"
20 #include <memory>
21 #include <set>
22 #include <sstream>
23
24 using namespace fuzzer;
25
26 // For now, have LLVMFuzzerTestOneInput just to make it link.
27 // Later we may want to make unittests that actually call LLVMFuzzerTestOneInput.
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)28 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
29 abort();
30 }
31
TEST(Fuzzer,Basename)32 TEST(Fuzzer, Basename) {
33 EXPECT_EQ(Basename("foo/bar"), "bar");
34 EXPECT_EQ(Basename("bar"), "bar");
35 EXPECT_EQ(Basename("/bar"), "bar");
36 EXPECT_EQ(Basename("foo/x"), "x");
37 EXPECT_EQ(Basename("foo/"), "");
38 #if LIBFUZZER_WINDOWS
39 EXPECT_EQ(Basename("foo\\bar"), "bar");
40 EXPECT_EQ(Basename("foo\\bar/baz"), "baz");
41 EXPECT_EQ(Basename("\\bar"), "bar");
42 EXPECT_EQ(Basename("foo\\x"), "x");
43 EXPECT_EQ(Basename("foo\\"), "");
44 #endif
45 }
46
TEST(Fuzzer,CrossOver)47 TEST(Fuzzer, CrossOver) {
48 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
49 fuzzer::EF = t.get();
50 Random Rand(0);
51 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
52 Unit A({0, 1, 2}), B({5, 6, 7});
53 Unit C;
54 Unit Expected[] = {
55 { 0 },
56 { 0, 1 },
57 { 0, 5 },
58 { 0, 1, 2 },
59 { 0, 1, 5 },
60 { 0, 5, 1 },
61 { 0, 5, 6 },
62 { 0, 1, 2, 5 },
63 { 0, 1, 5, 2 },
64 { 0, 1, 5, 6 },
65 { 0, 5, 1, 2 },
66 { 0, 5, 1, 6 },
67 { 0, 5, 6, 1 },
68 { 0, 5, 6, 7 },
69 { 0, 1, 2, 5, 6 },
70 { 0, 1, 5, 2, 6 },
71 { 0, 1, 5, 6, 2 },
72 { 0, 1, 5, 6, 7 },
73 { 0, 5, 1, 2, 6 },
74 { 0, 5, 1, 6, 2 },
75 { 0, 5, 1, 6, 7 },
76 { 0, 5, 6, 1, 2 },
77 { 0, 5, 6, 1, 7 },
78 { 0, 5, 6, 7, 1 },
79 { 0, 1, 2, 5, 6, 7 },
80 { 0, 1, 5, 2, 6, 7 },
81 { 0, 1, 5, 6, 2, 7 },
82 { 0, 1, 5, 6, 7, 2 },
83 { 0, 5, 1, 2, 6, 7 },
84 { 0, 5, 1, 6, 2, 7 },
85 { 0, 5, 1, 6, 7, 2 },
86 { 0, 5, 6, 1, 2, 7 },
87 { 0, 5, 6, 1, 7, 2 },
88 { 0, 5, 6, 7, 1, 2 }
89 };
90 for (size_t Len = 1; Len < 8; Len++) {
91 Set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
92 for (int Iter = 0; Iter < 3000; Iter++) {
93 C.resize(Len);
94 size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(),
95 C.data(), C.size());
96 C.resize(NewSize);
97 FoundUnits.insert(C);
98 }
99 for (const Unit &U : Expected)
100 if (U.size() <= Len)
101 ExpectedUnitsWitThisLength.insert(U);
102 EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
103 }
104 }
105
TEST(Fuzzer,Hash)106 TEST(Fuzzer, Hash) {
107 uint8_t A[] = {'a', 'b', 'c'};
108 fuzzer::Unit U(A, A + sizeof(A));
109 EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U));
110 U.push_back('d');
111 EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
112 }
113
114 typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
115 size_t MaxSize);
116
TestEraseBytes(Mutator M,int NumIter)117 void TestEraseBytes(Mutator M, int NumIter) {
118 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
119 fuzzer::EF = t.get();
120 uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
121 uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
122 uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
123 uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
124 uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
125 uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
126 uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
127 uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
128
129 uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
130 uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
131 uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
132
133 uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
134 uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
135 uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
136
137
138 Random Rand(0);
139 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
140 int FoundMask = 0;
141 for (int i = 0; i < NumIter; i++) {
142 uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
143 size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T));
144 if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
145 if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
146 if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
147 if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
148 if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
149 if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
150 if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
151 if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
152
153 if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
154 if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
155 if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
156
157 if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
158 if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
159 if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
160 }
161 EXPECT_EQ(FoundMask, (1 << 14) - 1);
162 }
163
TEST(FuzzerMutate,EraseBytes1)164 TEST(FuzzerMutate, EraseBytes1) {
165 TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
166 }
TEST(FuzzerMutate,EraseBytes2)167 TEST(FuzzerMutate, EraseBytes2) {
168 TestEraseBytes(&MutationDispatcher::Mutate, 2000);
169 }
170
TestInsertByte(Mutator M,int NumIter)171 void TestInsertByte(Mutator M, int NumIter) {
172 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
173 fuzzer::EF = t.get();
174 Random Rand(0);
175 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
176 int FoundMask = 0;
177 uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
178 uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
179 uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
180 uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
181 uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
182 uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
183 uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
184 uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
185 for (int i = 0; i < NumIter; i++) {
186 uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
187 size_t NewSize = (*MD.*M)(T, 7, 8);
188 if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0;
189 if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1;
190 if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2;
191 if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3;
192 if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4;
193 if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
194 if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
195 if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
196 }
197 EXPECT_EQ(FoundMask, 255);
198 }
199
TEST(FuzzerMutate,InsertByte1)200 TEST(FuzzerMutate, InsertByte1) {
201 TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
202 }
TEST(FuzzerMutate,InsertByte2)203 TEST(FuzzerMutate, InsertByte2) {
204 TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
205 }
206
TestInsertRepeatedBytes(Mutator M,int NumIter)207 void TestInsertRepeatedBytes(Mutator M, int NumIter) {
208 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
209 fuzzer::EF = t.get();
210 Random Rand(0);
211 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
212 int FoundMask = 0;
213 uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
214 uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
215 uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
216 uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
217 uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
218
219 uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
220 uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
221 uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
222 uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
223 uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
224
225 for (int i = 0; i < NumIter; i++) {
226 uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
227 size_t NewSize = (*MD.*M)(T, 4, 8);
228 if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
229 if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
230 if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
231 if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
232 if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
233
234 if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
235 if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
236 if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
237 if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
238 if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
239
240 }
241 EXPECT_EQ(FoundMask, (1 << 10) - 1);
242 }
243
TEST(FuzzerMutate,InsertRepeatedBytes1)244 TEST(FuzzerMutate, InsertRepeatedBytes1) {
245 TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
246 }
TEST(FuzzerMutate,InsertRepeatedBytes2)247 TEST(FuzzerMutate, InsertRepeatedBytes2) {
248 TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
249 }
250
TestChangeByte(Mutator M,int NumIter)251 void TestChangeByte(Mutator M, int NumIter) {
252 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
253 fuzzer::EF = t.get();
254 Random Rand(0);
255 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
256 int FoundMask = 0;
257 uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
258 uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
259 uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
260 uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
261 uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
262 uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
263 uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
264 uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
265 for (int i = 0; i < NumIter; i++) {
266 uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
267 size_t NewSize = (*MD.*M)(T, 8, 9);
268 if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
269 if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
270 if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
271 if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
272 if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
273 if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
274 if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
275 if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
276 }
277 EXPECT_EQ(FoundMask, 255);
278 }
279
TEST(FuzzerMutate,ChangeByte1)280 TEST(FuzzerMutate, ChangeByte1) {
281 TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
282 }
TEST(FuzzerMutate,ChangeByte2)283 TEST(FuzzerMutate, ChangeByte2) {
284 TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
285 }
286
TestChangeBit(Mutator M,int NumIter)287 void TestChangeBit(Mutator M, int NumIter) {
288 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
289 fuzzer::EF = t.get();
290 Random Rand(0);
291 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
292 int FoundMask = 0;
293 uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
294 uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
295 uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
296 uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
297 uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
298 uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
299 uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
300 uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
301 for (int i = 0; i < NumIter; i++) {
302 uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
303 size_t NewSize = (*MD.*M)(T, 8, 9);
304 if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
305 if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
306 if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
307 if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
308 if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
309 if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
310 if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
311 if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
312 }
313 EXPECT_EQ(FoundMask, 255);
314 }
315
TEST(FuzzerMutate,ChangeBit1)316 TEST(FuzzerMutate, ChangeBit1) {
317 TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
318 }
TEST(FuzzerMutate,ChangeBit2)319 TEST(FuzzerMutate, ChangeBit2) {
320 TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
321 }
322
TestShuffleBytes(Mutator M,int NumIter)323 void TestShuffleBytes(Mutator M, int NumIter) {
324 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
325 fuzzer::EF = t.get();
326 Random Rand(0);
327 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
328 int FoundMask = 0;
329 uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
330 uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
331 uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
332 uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
333 uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
334 for (int i = 0; i < NumIter; i++) {
335 uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
336 size_t NewSize = (*MD.*M)(T, 7, 7);
337 if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
338 if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
339 if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
340 if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
341 if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
342 }
343 EXPECT_EQ(FoundMask, 31);
344 }
345
TEST(FuzzerMutate,ShuffleBytes1)346 TEST(FuzzerMutate, ShuffleBytes1) {
347 TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17);
348 }
TEST(FuzzerMutate,ShuffleBytes2)349 TEST(FuzzerMutate, ShuffleBytes2) {
350 TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
351 }
352
TestCopyPart(Mutator M,int NumIter)353 void TestCopyPart(Mutator M, int NumIter) {
354 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
355 fuzzer::EF = t.get();
356 Random Rand(0);
357 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
358 int FoundMask = 0;
359 uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
360 uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
361 uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
362 uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
363 uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
364
365 for (int i = 0; i < NumIter; i++) {
366 uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
367 size_t NewSize = (*MD.*M)(T, 7, 7);
368 if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
369 if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
370 if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
371 if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
372 if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
373 }
374
375 uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
376 uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
377 uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
378 uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
379 uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
380
381 for (int i = 0; i < NumIter; i++) {
382 uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
383 size_t NewSize = (*MD.*M)(T, 5, 8);
384 if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
385 if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
386 if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
387 if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
388 if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
389 }
390
391 EXPECT_EQ(FoundMask, 1023);
392 }
393
TEST(FuzzerMutate,CopyPart1)394 TEST(FuzzerMutate, CopyPart1) {
395 TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
396 }
TEST(FuzzerMutate,CopyPart2)397 TEST(FuzzerMutate, CopyPart2) {
398 TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
399 }
TEST(FuzzerMutate,CopyPartNoInsertAtMaxSize)400 TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) {
401 // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an
402 // insert on an input of size `MaxSize`. Performing an insert in this case
403 // will lead to the mutation failing.
404 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
405 fuzzer::EF = t.get();
406 Random Rand(0);
407 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
408 uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
409 size_t MaxSize = sizeof(Data);
410 for (int count = 0; count < (1 << 18); ++count) {
411 size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize);
412 ASSERT_EQ(NewSize, MaxSize);
413 }
414 }
415
TestAddWordFromDictionary(Mutator M,int NumIter)416 void TestAddWordFromDictionary(Mutator M, int NumIter) {
417 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
418 fuzzer::EF = t.get();
419 Random Rand(0);
420 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
421 uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
422 uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
423 MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
424 MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
425 int FoundMask = 0;
426 uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
427 uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
428 uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
429 uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
430 uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
431 uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
432 uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
433 uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
434 for (int i = 0; i < NumIter; i++) {
435 uint8_t T[7] = {0x00, 0x11, 0x22};
436 size_t NewSize = (*MD.*M)(T, 3, 7);
437 if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
438 if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
439 if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
440 if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
441 if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
442 if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
443 if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
444 if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
445 }
446 EXPECT_EQ(FoundMask, 255);
447 }
448
TEST(FuzzerMutate,AddWordFromDictionary1)449 TEST(FuzzerMutate, AddWordFromDictionary1) {
450 TestAddWordFromDictionary(
451 &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
452 }
453
TEST(FuzzerMutate,AddWordFromDictionary2)454 TEST(FuzzerMutate, AddWordFromDictionary2) {
455 TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
456 }
457
TestChangeASCIIInteger(Mutator M,int NumIter)458 void TestChangeASCIIInteger(Mutator M, int NumIter) {
459 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
460 fuzzer::EF = t.get();
461 Random Rand(0);
462 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
463
464 uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
465 uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
466 uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
467 uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
468 int FoundMask = 0;
469 for (int i = 0; i < NumIter; i++) {
470 uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
471 size_t NewSize = (*MD.*M)(T, 8, 8);
472 /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
473 else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
474 else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
475 else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
476 else if (NewSize == 8) FoundMask |= 1 << 4;
477 }
478 EXPECT_EQ(FoundMask, 31);
479 }
480
TEST(FuzzerMutate,ChangeASCIIInteger1)481 TEST(FuzzerMutate, ChangeASCIIInteger1) {
482 TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
483 1 << 15);
484 }
485
TEST(FuzzerMutate,ChangeASCIIInteger2)486 TEST(FuzzerMutate, ChangeASCIIInteger2) {
487 TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
488 }
489
TestChangeBinaryInteger(Mutator M,int NumIter)490 void TestChangeBinaryInteger(Mutator M, int NumIter) {
491 std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
492 fuzzer::EF = t.get();
493 Random Rand(0);
494 std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
495
496 uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
497 uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
498 uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
499 uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
500 uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
501 uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
502 uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
503 uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
504
505 int FoundMask = 0;
506 for (int i = 0; i < NumIter; i++) {
507 uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
508 size_t NewSize = (*MD.*M)(T, 8, 8);
509 /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
510 else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
511 else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
512 else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
513 else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
514 else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
515 else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
516 else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
517 }
518 EXPECT_EQ(FoundMask, 255);
519 }
520
TEST(FuzzerMutate,ChangeBinaryInteger1)521 TEST(FuzzerMutate, ChangeBinaryInteger1) {
522 TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
523 1 << 12);
524 }
525
TEST(FuzzerMutate,ChangeBinaryInteger2)526 TEST(FuzzerMutate, ChangeBinaryInteger2) {
527 TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
528 }
529
530
TEST(FuzzerDictionary,ParseOneDictionaryEntry)531 TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
532 Unit U;
533 EXPECT_FALSE(ParseOneDictionaryEntry("", &U));
534 EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U));
535 EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U));
536 EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U));
537 EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U));
538 EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U));
539 EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U));
540 EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U));
541 EXPECT_EQ(U, Unit({'a'}));
542 EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U));
543 EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
544 EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U));
545 EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
546 EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U));
547 EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U));
548 EXPECT_EQ(U, Unit({'\\'}));
549 EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U));
550 EXPECT_EQ(U, Unit({0xAB}));
551 EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U));
552 EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE}));
553 EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U));
554 EXPECT_EQ(U, Unit({'#'}));
555 EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U));
556 EXPECT_EQ(U, Unit({'"'}));
557 }
558
TEST(FuzzerDictionary,ParseDictionaryFile)559 TEST(FuzzerDictionary, ParseDictionaryFile) {
560 Vector<Unit> Units;
561 EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units));
562 EXPECT_FALSE(ParseDictionaryFile("", &Units));
563 EXPECT_TRUE(ParseDictionaryFile("\n", &Units));
564 EXPECT_EQ(Units.size(), 0U);
565 EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units));
566 EXPECT_EQ(Units.size(), 0U);
567 EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
568 EXPECT_EQ(Units.size(), 0U);
569 EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
570 EXPECT_EQ(Units.size(), 0U);
571 EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units));
572 EXPECT_EQ(Units, Vector<Unit>({Unit({'a', 'a'})}));
573 EXPECT_TRUE(
574 ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units));
575 EXPECT_EQ(Units,
576 Vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})}));
577 }
578
TEST(FuzzerUtil,Base64)579 TEST(FuzzerUtil, Base64) {
580 EXPECT_EQ("", Base64({}));
581 EXPECT_EQ("YQ==", Base64({'a'}));
582 EXPECT_EQ("eA==", Base64({'x'}));
583 EXPECT_EQ("YWI=", Base64({'a', 'b'}));
584 EXPECT_EQ("eHk=", Base64({'x', 'y'}));
585 EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'}));
586 EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'}));
587 EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'}));
588 EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'}));
589 EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'}));
590 }
591
TEST(Corpus,Distribution)592 TEST(Corpus, Distribution) {
593 DataFlowTrace DFT;
594 Random Rand(0);
595 struct EntropicOptions Entropic = {false, 0xFF, 100, false};
596 std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
597 size_t N = 10;
598 size_t TriesPerUnit = 1<<16;
599 for (size_t i = 0; i < N; i++)
600 C->AddToCorpus(Unit{static_cast<uint8_t>(i)}, /*NumFeatures*/ 1,
601 /*MayDeleteFile*/ false, /*HasFocusFunction*/ false,
602 /*ForceAddToCorpus*/ false,
603 /*TimeOfUnit*/ std::chrono::microseconds(0),
604 /*FeatureSet*/ {}, DFT,
605 /*BaseII*/ nullptr);
606
607 Vector<size_t> Hist(N);
608 for (size_t i = 0; i < N * TriesPerUnit; i++) {
609 Hist[C->ChooseUnitIdxToMutate(Rand)]++;
610 }
611 for (size_t i = 0; i < N; i++) {
612 // A weak sanity check that every unit gets invoked.
613 EXPECT_GT(Hist[i], TriesPerUnit / N / 3);
614 }
615 }
616
EQ(const Vector<T> & A,const Vector<T> & B)617 template <typename T> void EQ(const Vector<T> &A, const Vector<T> &B) {
618 EXPECT_EQ(A, B);
619 }
620
EQ(const Set<T> & A,const Vector<T> & B)621 template <typename T> void EQ(const Set<T> &A, const Vector<T> &B) {
622 EXPECT_EQ(A, Set<T>(B.begin(), B.end()));
623 }
624
EQ(const Vector<MergeFileInfo> & A,const Vector<std::string> & B)625 void EQ(const Vector<MergeFileInfo> &A, const Vector<std::string> &B) {
626 Set<std::string> a;
627 for (const auto &File : A)
628 a.insert(File.Name);
629 Set<std::string> b(B.begin(), B.end());
630 EXPECT_EQ(a, b);
631 }
632
633 #define TRACED_EQ(A, ...) \
634 { \
635 SCOPED_TRACE(#A); \
636 EQ(A, __VA_ARGS__); \
637 }
638
TEST(Merger,Parse)639 TEST(Merger, Parse) {
640 Merger M;
641
642 const char *kInvalidInputs[] = {
643 // Bad file numbers
644 "",
645 "x",
646 "0\n0",
647 "3\nx",
648 "2\n3",
649 "2\n2",
650 // Bad file names
651 "2\n2\nA\n",
652 "2\n2\nA\nB\nC\n",
653 // Unknown markers
654 "2\n1\nA\nSTARTED 0\nBAD 0 0x0",
655 // Bad file IDs
656 "1\n1\nA\nSTARTED 1",
657 "2\n1\nA\nSTARTED 0\nFT 1 0x0",
658 };
659 for (auto S : kInvalidInputs) {
660 SCOPED_TRACE(S);
661 EXPECT_FALSE(M.Parse(S, false));
662 }
663
664 // Parse initial control file
665 EXPECT_TRUE(M.Parse("1\n0\nAA\n", false));
666 ASSERT_EQ(M.Files.size(), 1U);
667 EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
668 EXPECT_EQ(M.Files[0].Name, "AA");
669 EXPECT_TRUE(M.LastFailure.empty());
670 EXPECT_EQ(M.FirstNotProcessedFile, 0U);
671
672 // Parse control file that failed on first attempt
673 EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false));
674 ASSERT_EQ(M.Files.size(), 2U);
675 EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
676 EXPECT_EQ(M.Files[0].Name, "AA");
677 EXPECT_EQ(M.Files[1].Name, "BB");
678 EXPECT_EQ(M.LastFailure, "AA");
679 EXPECT_EQ(M.FirstNotProcessedFile, 1U);
680
681 // Parse control file that failed on later attempt
682 EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
683 "STARTED 0 1000\n"
684 "FT 0 1 2 3\n"
685 "STARTED 1 1001\n"
686 "FT 1 4 5 6 \n"
687 "STARTED 2 1002\n"
688 "",
689 true));
690 ASSERT_EQ(M.Files.size(), 3U);
691 EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
692 EXPECT_EQ(M.Files[0].Name, "AA");
693 EXPECT_EQ(M.Files[0].Size, 1000U);
694 EXPECT_EQ(M.Files[1].Name, "BB");
695 EXPECT_EQ(M.Files[1].Size, 1001U);
696 EXPECT_EQ(M.Files[2].Name, "C");
697 EXPECT_EQ(M.Files[2].Size, 1002U);
698 EXPECT_EQ(M.LastFailure, "C");
699 EXPECT_EQ(M.FirstNotProcessedFile, 3U);
700 TRACED_EQ(M.Files[0].Features, {1, 2, 3});
701 TRACED_EQ(M.Files[1].Features, {4, 5, 6});
702
703 // Parse control file without features or PCs
704 EXPECT_TRUE(M.Parse("2\n0\nAA\nBB\n"
705 "STARTED 0 1000\n"
706 "FT 0\n"
707 "COV 0\n"
708 "STARTED 1 1001\n"
709 "FT 1\n"
710 "COV 1\n"
711 "",
712 true));
713 ASSERT_EQ(M.Files.size(), 2U);
714 EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
715 EXPECT_TRUE(M.LastFailure.empty());
716 EXPECT_EQ(M.FirstNotProcessedFile, 2U);
717 EXPECT_TRUE(M.Files[0].Features.empty());
718 EXPECT_TRUE(M.Files[0].Cov.empty());
719 EXPECT_TRUE(M.Files[1].Features.empty());
720 EXPECT_TRUE(M.Files[1].Cov.empty());
721
722 // Parse features and PCs
723 EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
724 "STARTED 0 1000\n"
725 "FT 0 1 2 3\n"
726 "COV 0 11 12 13\n"
727 "STARTED 1 1001\n"
728 "FT 1 4 5 6\n"
729 "COV 1 7 8 9\n"
730 "STARTED 2 1002\n"
731 "FT 2 6 1 3\n"
732 "COV 2 16 11 13\n"
733 "",
734 true));
735 ASSERT_EQ(M.Files.size(), 3U);
736 EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
737 EXPECT_TRUE(M.LastFailure.empty());
738 EXPECT_EQ(M.FirstNotProcessedFile, 3U);
739 TRACED_EQ(M.Files[0].Features, {1, 2, 3});
740 TRACED_EQ(M.Files[0].Cov, {11, 12, 13});
741 TRACED_EQ(M.Files[1].Features, {4, 5, 6});
742 TRACED_EQ(M.Files[1].Cov, {7, 8, 9});
743 TRACED_EQ(M.Files[2].Features, {1, 3, 6});
744 TRACED_EQ(M.Files[2].Cov, {16});
745 }
746
TEST(Merger,Merge)747 TEST(Merger, Merge) {
748 Merger M;
749 Set<uint32_t> Features, NewFeatures;
750 Set<uint32_t> Cov, NewCov;
751 Vector<std::string> NewFiles;
752
753 // Adds new files and features
754 EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
755 "STARTED 0 1000\n"
756 "FT 0 1 2 3\n"
757 "STARTED 1 1001\n"
758 "FT 1 4 5 6 \n"
759 "STARTED 2 1002\n"
760 "FT 2 6 1 3\n"
761 "",
762 true));
763 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
764 TRACED_EQ(M.Files, {"A", "B", "C"});
765 TRACED_EQ(NewFiles, {"A", "B"});
766 TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
767
768 // Doesn't return features or files in the initial corpus.
769 EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
770 "STARTED 0 1000\n"
771 "FT 0 1 2 3\n"
772 "STARTED 1 1001\n"
773 "FT 1 4 5 6 \n"
774 "STARTED 2 1002\n"
775 "FT 2 6 1 3\n"
776 "",
777 true));
778 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
779 TRACED_EQ(M.Files, {"A", "B", "C"});
780 TRACED_EQ(NewFiles, {"B"});
781 TRACED_EQ(NewFeatures, {4, 5, 6});
782
783 // No new features, so no new files
784 EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n"
785 "STARTED 0 1000\n"
786 "FT 0 1 2 3\n"
787 "STARTED 1 1001\n"
788 "FT 1 4 5 6 \n"
789 "STARTED 2 1002\n"
790 "FT 2 6 1 3\n"
791 "",
792 true));
793 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 0U);
794 TRACED_EQ(M.Files, {"A", "B", "C"});
795 TRACED_EQ(NewFiles, {});
796 TRACED_EQ(NewFeatures, {});
797
798 // Can pass initial features and coverage.
799 Features = {1, 2, 3};
800 Cov = {};
801 EXPECT_TRUE(M.Parse("2\n0\nA\nB\n"
802 "STARTED 0 1000\n"
803 "FT 0 1 2 3\n"
804 "STARTED 1 1001\n"
805 "FT 1 4 5 6\n"
806 "",
807 true));
808 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
809 TRACED_EQ(M.Files, {"A", "B"});
810 TRACED_EQ(NewFiles, {"B"});
811 TRACED_EQ(NewFeatures, {4, 5, 6});
812 Features.clear();
813 Cov.clear();
814
815 // Parse smaller files first
816 EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
817 "STARTED 0 2000\n"
818 "FT 0 1 2 3\n"
819 "STARTED 1 1001\n"
820 "FT 1 4 5 6 \n"
821 "STARTED 2 1002\n"
822 "FT 2 6 1 3 \n"
823 "",
824 true));
825 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
826 TRACED_EQ(M.Files, {"B", "C", "A"});
827 TRACED_EQ(NewFiles, {"B", "C", "A"});
828 TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
829
830 EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n"
831 "STARTED 0 2000\n"
832 "FT 0 1 2 3\n"
833 "STARTED 1 1101\n"
834 "FT 1 4 5 6 \n"
835 "STARTED 2 1102\n"
836 "FT 2 6 1 3 100 \n"
837 "STARTED 3 1000\n"
838 "FT 3 1 \n"
839 "",
840 true));
841 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 7U);
842 TRACED_EQ(M.Files, {"A", "B", "C", "D"});
843 TRACED_EQ(NewFiles, {"D", "B", "C", "A"});
844 TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6, 100});
845
846 // For same sized file, parse more features first
847 EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n"
848 "STARTED 0 2000\n"
849 "FT 0 4 5 6 7 8\n"
850 "STARTED 1 1100\n"
851 "FT 1 1 2 3 \n"
852 "STARTED 2 1100\n"
853 "FT 2 2 3 \n"
854 "STARTED 3 1000\n"
855 "FT 3 1 \n"
856 "",
857 true));
858 EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
859 TRACED_EQ(M.Files, {"A", "B", "C", "D"});
860 TRACED_EQ(NewFiles, {"D", "B"});
861 TRACED_EQ(NewFeatures, {1, 2, 3});
862 }
863
864 #undef TRACED_EQ
865
TEST(DFT,BlockCoverage)866 TEST(DFT, BlockCoverage) {
867 BlockCoverage Cov;
868 // Assuming C0 has 5 instrumented blocks,
869 // C1: 7 blocks, C2: 4, C3: 9, C4 never covered, C5: 15,
870
871 // Add C0
872 EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
873 EXPECT_EQ(Cov.GetCounter(0, 0), 1U);
874 EXPECT_EQ(Cov.GetCounter(0, 1), 0U); // not seen this BB yet.
875 EXPECT_EQ(Cov.GetCounter(0, 5), 0U); // BB ID out of bounds.
876 EXPECT_EQ(Cov.GetCounter(1, 0), 0U); // not seen this function yet.
877
878 EXPECT_EQ(Cov.GetNumberOfBlocks(0), 5U);
879 EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 1U);
880 EXPECT_EQ(Cov.GetNumberOfBlocks(1), 0U);
881
882 // Various errors.
883 EXPECT_FALSE(Cov.AppendCoverage("C0\n")); // No total number.
884 EXPECT_FALSE(Cov.AppendCoverage("C0 7\n")); // No total number.
885 EXPECT_FALSE(Cov.AppendCoverage("CZ\n")); // Wrong function number.
886 EXPECT_FALSE(Cov.AppendCoverage("C1 7 7")); // BB ID is too big.
887 EXPECT_FALSE(Cov.AppendCoverage("C1 100 7")); // BB ID is too big.
888
889 // Add C0 more times.
890 EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
891 EXPECT_EQ(Cov.GetCounter(0, 0), 2U);
892 EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 5\n"));
893 EXPECT_EQ(Cov.GetCounter(0, 0), 3U);
894 EXPECT_EQ(Cov.GetCounter(0, 1), 1U);
895 EXPECT_EQ(Cov.GetCounter(0, 2), 1U);
896 EXPECT_EQ(Cov.GetCounter(0, 3), 0U);
897 EXPECT_EQ(Cov.GetCounter(0, 4), 0U);
898 EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 3U);
899 EXPECT_TRUE(Cov.AppendCoverage("C0 1 3 4 5\n"));
900 EXPECT_EQ(Cov.GetCounter(0, 0), 4U);
901 EXPECT_EQ(Cov.GetCounter(0, 1), 2U);
902 EXPECT_EQ(Cov.GetCounter(0, 2), 1U);
903 EXPECT_EQ(Cov.GetCounter(0, 3), 1U);
904 EXPECT_EQ(Cov.GetCounter(0, 4), 1U);
905 EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 5U);
906
907 EXPECT_TRUE(Cov.AppendCoverage("C1 7\nC2 4\nC3 9\nC5 15\nC0 5\n"));
908 EXPECT_EQ(Cov.GetCounter(0, 0), 5U);
909 EXPECT_EQ(Cov.GetCounter(1, 0), 1U);
910 EXPECT_EQ(Cov.GetCounter(2, 0), 1U);
911 EXPECT_EQ(Cov.GetCounter(3, 0), 1U);
912 EXPECT_EQ(Cov.GetCounter(4, 0), 0U);
913 EXPECT_EQ(Cov.GetCounter(5, 0), 1U);
914
915 EXPECT_TRUE(Cov.AppendCoverage("C3 4 5 9\nC5 11 12 15"));
916 EXPECT_EQ(Cov.GetCounter(0, 0), 5U);
917 EXPECT_EQ(Cov.GetCounter(1, 0), 1U);
918 EXPECT_EQ(Cov.GetCounter(2, 0), 1U);
919 EXPECT_EQ(Cov.GetCounter(3, 0), 2U);
920 EXPECT_EQ(Cov.GetCounter(3, 4), 1U);
921 EXPECT_EQ(Cov.GetCounter(3, 5), 1U);
922 EXPECT_EQ(Cov.GetCounter(3, 6), 0U);
923 EXPECT_EQ(Cov.GetCounter(4, 0), 0U);
924 EXPECT_EQ(Cov.GetCounter(5, 0), 2U);
925 EXPECT_EQ(Cov.GetCounter(5, 10), 0U);
926 EXPECT_EQ(Cov.GetCounter(5, 11), 1U);
927 EXPECT_EQ(Cov.GetCounter(5, 12), 1U);
928 }
929
TEST(DFT,FunctionWeights)930 TEST(DFT, FunctionWeights) {
931 BlockCoverage Cov;
932 // unused function gets zero weight.
933 EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
934 auto Weights = Cov.FunctionWeights(2);
935 EXPECT_GT(Weights[0], 0.);
936 EXPECT_EQ(Weights[1], 0.);
937
938 // Less frequently used function gets less weight.
939 Cov.clear();
940 EXPECT_TRUE(Cov.AppendCoverage("C0 5\nC1 5\nC1 5\n"));
941 Weights = Cov.FunctionWeights(2);
942 EXPECT_GT(Weights[0], Weights[1]);
943
944 // A function with more uncovered blocks gets more weight.
945 Cov.clear();
946 EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 3 5\nC1 2 4\n"));
947 Weights = Cov.FunctionWeights(2);
948 EXPECT_GT(Weights[1], Weights[0]);
949
950 // A function with DFT gets more weight than the function w/o DFT.
951 Cov.clear();
952 EXPECT_TRUE(Cov.AppendCoverage("F1 111\nC0 3\nC1 1 2 3\n"));
953 Weights = Cov.FunctionWeights(2);
954 EXPECT_GT(Weights[1], Weights[0]);
955 }
956
957
TEST(Fuzzer,ForEachNonZeroByte)958 TEST(Fuzzer, ForEachNonZeroByte) {
959 const size_t N = 64;
960 alignas(64) uint8_t Ar[N + 8] = {
961 0, 0, 0, 0, 0, 0, 0, 0,
962 1, 2, 0, 0, 0, 0, 0, 0,
963 0, 0, 3, 0, 4, 0, 0, 0,
964 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 5, 0, 6, 0, 0,
966 0, 0, 0, 0, 0, 0, 7, 0,
967 0, 0, 0, 0, 0, 0, 0, 0,
968 0, 0, 0, 0, 0, 0, 0, 8,
969 9, 9, 9, 9, 9, 9, 9, 9,
970 };
971 typedef Vector<std::pair<size_t, uint8_t> > Vec;
972 Vec Res, Expected;
973 auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) {
974 Res.push_back({FirstFeature + Idx, V});
975 };
976 ForEachNonZeroByte(Ar, Ar + N, 100, CB);
977 Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4},
978 {135, 5}, {137, 6}, {146, 7}, {163, 8}};
979 EXPECT_EQ(Res, Expected);
980
981 Res.clear();
982 ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB);
983 Expected = { {109, 2}, {118, 3}, {120, 4},
984 {135, 5}, {137, 6}, {146, 7}, {163, 8}};
985 EXPECT_EQ(Res, Expected);
986
987 Res.clear();
988 ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB);
989 Expected = { {109, 2}, {118, 3}, {120, 4},
990 {135, 5}, {137, 6}, {146, 7}};
991 EXPECT_EQ(Res, Expected);
992 }
993
994 // FuzzerCommand unit tests. The arguments in the two helper methods below must
995 // match.
makeCommandArgs(Vector<std::string> * ArgsToAdd)996 static void makeCommandArgs(Vector<std::string> *ArgsToAdd) {
997 assert(ArgsToAdd);
998 ArgsToAdd->clear();
999 ArgsToAdd->push_back("foo");
1000 ArgsToAdd->push_back("-bar=baz");
1001 ArgsToAdd->push_back("qux");
1002 ArgsToAdd->push_back(Command::ignoreRemainingArgs());
1003 ArgsToAdd->push_back("quux");
1004 ArgsToAdd->push_back("-grault=garply");
1005 }
1006
makeCmdLine(const char * separator,const char * suffix)1007 static std::string makeCmdLine(const char *separator, const char *suffix) {
1008 std::string CmdLine("foo -bar=baz qux ");
1009 if (strlen(separator) != 0) {
1010 CmdLine += separator;
1011 CmdLine += " ";
1012 }
1013 CmdLine += Command::ignoreRemainingArgs();
1014 CmdLine += " quux -grault=garply";
1015 if (strlen(suffix) != 0) {
1016 CmdLine += " ";
1017 CmdLine += suffix;
1018 }
1019 return CmdLine;
1020 }
1021
TEST(FuzzerCommand,Create)1022 TEST(FuzzerCommand, Create) {
1023 std::string CmdLine;
1024
1025 // Default constructor
1026 Command DefaultCmd;
1027
1028 CmdLine = DefaultCmd.toString();
1029 EXPECT_EQ(CmdLine, "");
1030
1031 // Explicit constructor
1032 Vector<std::string> ArgsToAdd;
1033 makeCommandArgs(&ArgsToAdd);
1034 Command InitializedCmd(ArgsToAdd);
1035
1036 CmdLine = InitializedCmd.toString();
1037 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1038
1039 // Compare each argument
1040 auto InitializedArgs = InitializedCmd.getArguments();
1041 auto i = ArgsToAdd.begin();
1042 auto j = InitializedArgs.begin();
1043 while (i != ArgsToAdd.end() && j != InitializedArgs.end()) {
1044 EXPECT_EQ(*i++, *j++);
1045 }
1046 EXPECT_EQ(i, ArgsToAdd.end());
1047 EXPECT_EQ(j, InitializedArgs.end());
1048
1049 // Copy constructor
1050 Command CopiedCmd(InitializedCmd);
1051
1052 CmdLine = CopiedCmd.toString();
1053 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1054
1055 // Assignment operator
1056 Command AssignedCmd;
1057 AssignedCmd = CopiedCmd;
1058
1059 CmdLine = AssignedCmd.toString();
1060 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1061 }
1062
TEST(FuzzerCommand,ModifyArguments)1063 TEST(FuzzerCommand, ModifyArguments) {
1064 Vector<std::string> ArgsToAdd;
1065 makeCommandArgs(&ArgsToAdd);
1066 Command Cmd;
1067 std::string CmdLine;
1068
1069 Cmd.addArguments(ArgsToAdd);
1070 CmdLine = Cmd.toString();
1071 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1072
1073 Cmd.addArgument("waldo");
1074 EXPECT_TRUE(Cmd.hasArgument("waldo"));
1075
1076 CmdLine = Cmd.toString();
1077 EXPECT_EQ(CmdLine, makeCmdLine("waldo", ""));
1078
1079 Cmd.removeArgument("waldo");
1080 EXPECT_FALSE(Cmd.hasArgument("waldo"));
1081
1082 CmdLine = Cmd.toString();
1083 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1084 }
1085
TEST(FuzzerCommand,ModifyFlags)1086 TEST(FuzzerCommand, ModifyFlags) {
1087 Vector<std::string> ArgsToAdd;
1088 makeCommandArgs(&ArgsToAdd);
1089 Command Cmd(ArgsToAdd);
1090 std::string Value, CmdLine;
1091 ASSERT_FALSE(Cmd.hasFlag("fred"));
1092
1093 Value = Cmd.getFlagValue("fred");
1094 EXPECT_EQ(Value, "");
1095
1096 CmdLine = Cmd.toString();
1097 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1098
1099 Cmd.addFlag("fred", "plugh");
1100 EXPECT_TRUE(Cmd.hasFlag("fred"));
1101
1102 Value = Cmd.getFlagValue("fred");
1103 EXPECT_EQ(Value, "plugh");
1104
1105 CmdLine = Cmd.toString();
1106 EXPECT_EQ(CmdLine, makeCmdLine("-fred=plugh", ""));
1107
1108 Cmd.removeFlag("fred");
1109 EXPECT_FALSE(Cmd.hasFlag("fred"));
1110
1111 Value = Cmd.getFlagValue("fred");
1112 EXPECT_EQ(Value, "");
1113
1114 CmdLine = Cmd.toString();
1115 EXPECT_EQ(CmdLine, makeCmdLine("", ""));
1116 }
1117
TEST(FuzzerCommand,SetOutput)1118 TEST(FuzzerCommand, SetOutput) {
1119 Vector<std::string> ArgsToAdd;
1120 makeCommandArgs(&ArgsToAdd);
1121 Command Cmd(ArgsToAdd);
1122 std::string CmdLine;
1123 ASSERT_FALSE(Cmd.hasOutputFile());
1124 ASSERT_FALSE(Cmd.isOutAndErrCombined());
1125
1126 Cmd.combineOutAndErr(true);
1127 EXPECT_TRUE(Cmd.isOutAndErrCombined());
1128
1129 CmdLine = Cmd.toString();
1130 EXPECT_EQ(CmdLine, makeCmdLine("", "2>&1"));
1131
1132 Cmd.combineOutAndErr(false);
1133 EXPECT_FALSE(Cmd.isOutAndErrCombined());
1134
1135 Cmd.setOutputFile("xyzzy");
1136 EXPECT_TRUE(Cmd.hasOutputFile());
1137
1138 CmdLine = Cmd.toString();
1139 EXPECT_EQ(CmdLine, makeCmdLine("", ">xyzzy"));
1140
1141 Cmd.setOutputFile("thud");
1142 EXPECT_TRUE(Cmd.hasOutputFile());
1143
1144 CmdLine = Cmd.toString();
1145 EXPECT_EQ(CmdLine, makeCmdLine("", ">thud"));
1146
1147 Cmd.combineOutAndErr();
1148 EXPECT_TRUE(Cmd.isOutAndErrCombined());
1149
1150 CmdLine = Cmd.toString();
1151 EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1"));
1152 }
1153
TEST(Entropic,UpdateFrequency)1154 TEST(Entropic, UpdateFrequency) {
1155 const size_t One = 1, Two = 2;
1156 const size_t FeatIdx1 = 0, FeatIdx2 = 42, FeatIdx3 = 12, FeatIdx4 = 26;
1157 size_t Index;
1158 // Create input corpus with default entropic configuration
1159 struct EntropicOptions Entropic = {true, 0xFF, 100, false};
1160 std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
1161 std::unique_ptr<InputInfo> II(new InputInfo());
1162
1163 C->AddRareFeature(FeatIdx1);
1164 C->UpdateFeatureFrequency(II.get(), FeatIdx1);
1165 EXPECT_EQ(II->FeatureFreqs.size(), One);
1166 C->AddRareFeature(FeatIdx2);
1167 C->UpdateFeatureFrequency(II.get(), FeatIdx1);
1168 C->UpdateFeatureFrequency(II.get(), FeatIdx2);
1169 EXPECT_EQ(II->FeatureFreqs.size(), Two);
1170 EXPECT_EQ(II->FeatureFreqs[0].second, 2);
1171 EXPECT_EQ(II->FeatureFreqs[1].second, 1);
1172
1173 C->AddRareFeature(FeatIdx3);
1174 C->AddRareFeature(FeatIdx4);
1175 C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1176 C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1177 C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1178 C->UpdateFeatureFrequency(II.get(), FeatIdx4);
1179
1180 for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
1181 EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first);
1182
1183 II->DeleteFeatureFreq(FeatIdx3);
1184 for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
1185 EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first);
1186 }
1187
SubAndSquare(double X,double Y)1188 double SubAndSquare(double X, double Y) {
1189 double R = X - Y;
1190 R = R * R;
1191 return R;
1192 }
1193
TEST(Entropic,ComputeEnergy)1194 TEST(Entropic, ComputeEnergy) {
1195 const double Precision = 0.01;
1196 struct EntropicOptions Entropic = {true, 0xFF, 100, false};
1197 std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
1198 std::unique_ptr<InputInfo> II(new InputInfo());
1199 Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs = {{1, 3}, {2, 3}, {3, 3}};
1200 II->FeatureFreqs = FeatureFreqs;
1201 II->NumExecutedMutations = 0;
1202 II->UpdateEnergy(4, false, std::chrono::microseconds(0));
1203 EXPECT_LT(SubAndSquare(II->Energy, 1.450805), Precision);
1204
1205 II->NumExecutedMutations = 9;
1206 II->UpdateEnergy(5, false, std::chrono::microseconds(0));
1207 EXPECT_LT(SubAndSquare(II->Energy, 1.525496), Precision);
1208
1209 II->FeatureFreqs[0].second++;
1210 II->FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(42, 6));
1211 II->NumExecutedMutations = 20;
1212 II->UpdateEnergy(10, false, std::chrono::microseconds(0));
1213 EXPECT_LT(SubAndSquare(II->Energy, 1.792831), Precision);
1214 }
1215
main(int argc,char ** argv)1216 int main(int argc, char **argv) {
1217 testing::InitGoogleTest(&argc, argv);
1218 return RUN_ALL_TESTS();
1219 }
1220