xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/fuzzer/tests/FuzzerUnittest.cpp (revision a7c257b03e4462df2b1020128fb82716512d7856)
1 // This file is distributed under the University of Illinois Open Source
2 // License. See LICENSE.TXT for details.
3 
4 // Avoid ODR violations (LibFuzzer is built without ASan and this test is built
5 // with ASan) involving C++ standard library types when using libcxx.
6 #define _LIBCPP_HAS_NO_ASAN
7 
8 // Do not attempt to use LLVM ostream from gtest.
9 #define GTEST_NO_LLVM_RAW_OSTREAM 1
10 
11 #include "FuzzerCorpus.h"
12 #include "FuzzerDictionary.h"
13 #include "FuzzerInternal.h"
14 #include "FuzzerMerge.h"
15 #include "FuzzerMutate.h"
16 #include "FuzzerRandom.h"
17 #include "FuzzerTracePC.h"
18 #include "gtest/gtest.h"
19 #include <memory>
20 #include <set>
21 #include <sstream>
22 
23 using namespace fuzzer;
24 
25 // For now, have LLVMFuzzerTestOneInput just to make it link.
26 // Later we may want to make unittests that actually call LLVMFuzzerTestOneInput.
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)27 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
28   abort();
29 }
30 
TEST(Fuzzer,Basename)31 TEST(Fuzzer, Basename) {
32   EXPECT_EQ(Basename("foo/bar"), "bar");
33   EXPECT_EQ(Basename("bar"), "bar");
34   EXPECT_EQ(Basename("/bar"), "bar");
35   EXPECT_EQ(Basename("foo/x"), "x");
36   EXPECT_EQ(Basename("foo/"), "");
37 #if LIBFUZZER_WINDOWS
38   EXPECT_EQ(Basename("foo\\bar"), "bar");
39   EXPECT_EQ(Basename("foo\\bar/baz"), "baz");
40   EXPECT_EQ(Basename("\\bar"), "bar");
41   EXPECT_EQ(Basename("foo\\x"), "x");
42   EXPECT_EQ(Basename("foo\\"), "");
43 #endif
44 }
45 
TEST(Fuzzer,CrossOver)46 TEST(Fuzzer, CrossOver) {
47   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
48   fuzzer::EF = t.get();
49   Random Rand(0);
50   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
51   Unit A({0, 1, 2}), B({5, 6, 7});
52   Unit C;
53   Unit Expected[] = {
54        { 0 },
55        { 0, 1 },
56        { 0, 5 },
57        { 0, 1, 2 },
58        { 0, 1, 5 },
59        { 0, 5, 1 },
60        { 0, 5, 6 },
61        { 0, 1, 2, 5 },
62        { 0, 1, 5, 2 },
63        { 0, 1, 5, 6 },
64        { 0, 5, 1, 2 },
65        { 0, 5, 1, 6 },
66        { 0, 5, 6, 1 },
67        { 0, 5, 6, 7 },
68        { 0, 1, 2, 5, 6 },
69        { 0, 1, 5, 2, 6 },
70        { 0, 1, 5, 6, 2 },
71        { 0, 1, 5, 6, 7 },
72        { 0, 5, 1, 2, 6 },
73        { 0, 5, 1, 6, 2 },
74        { 0, 5, 1, 6, 7 },
75        { 0, 5, 6, 1, 2 },
76        { 0, 5, 6, 1, 7 },
77        { 0, 5, 6, 7, 1 },
78        { 0, 1, 2, 5, 6, 7 },
79        { 0, 1, 5, 2, 6, 7 },
80        { 0, 1, 5, 6, 2, 7 },
81        { 0, 1, 5, 6, 7, 2 },
82        { 0, 5, 1, 2, 6, 7 },
83        { 0, 5, 1, 6, 2, 7 },
84        { 0, 5, 1, 6, 7, 2 },
85        { 0, 5, 6, 1, 2, 7 },
86        { 0, 5, 6, 1, 7, 2 },
87        { 0, 5, 6, 7, 1, 2 }
88   };
89   for (size_t Len = 1; Len < 8; Len++) {
90     Set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
91     for (int Iter = 0; Iter < 3000; Iter++) {
92       C.resize(Len);
93       size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(),
94                                      C.data(), C.size());
95       C.resize(NewSize);
96       FoundUnits.insert(C);
97     }
98     for (const Unit &U : Expected)
99       if (U.size() <= Len)
100         ExpectedUnitsWitThisLength.insert(U);
101     EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
102   }
103 }
104 
TEST(Fuzzer,Hash)105 TEST(Fuzzer, Hash) {
106   uint8_t A[] = {'a', 'b', 'c'};
107   fuzzer::Unit U(A, A + sizeof(A));
108   EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U));
109   U.push_back('d');
110   EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
111 }
112 
113 typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
114                                               size_t MaxSize);
115 
TestEraseBytes(Mutator M,int NumIter)116 void TestEraseBytes(Mutator M, int NumIter) {
117   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
118   fuzzer::EF = t.get();
119   uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
120   uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
121   uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
122   uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
123   uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
124   uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
125   uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
126   uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
127 
128   uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
129   uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
130   uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
131 
132   uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
133   uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
134   uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
135 
136 
137   Random Rand(0);
138   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
139   int FoundMask = 0;
140   for (int i = 0; i < NumIter; i++) {
141     uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
142     size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T));
143     if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
144     if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
145     if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
146     if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
147     if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
148     if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
149     if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
150     if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
151 
152     if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
153     if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
154     if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
155 
156     if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
157     if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
158     if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
159   }
160   EXPECT_EQ(FoundMask, (1 << 14) - 1);
161 }
162 
TEST(FuzzerMutate,EraseBytes1)163 TEST(FuzzerMutate, EraseBytes1) {
164   TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
165 }
TEST(FuzzerMutate,EraseBytes2)166 TEST(FuzzerMutate, EraseBytes2) {
167   TestEraseBytes(&MutationDispatcher::Mutate, 2000);
168 }
169 
TestInsertByte(Mutator M,int NumIter)170 void TestInsertByte(Mutator M, int NumIter) {
171   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
172   fuzzer::EF = t.get();
173   Random Rand(0);
174   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
175   int FoundMask = 0;
176   uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
177   uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
178   uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
179   uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
180   uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
181   uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
182   uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
183   uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
184   for (int i = 0; i < NumIter; i++) {
185     uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
186     size_t NewSize = (*MD.*M)(T, 7, 8);
187     if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0;
188     if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1;
189     if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2;
190     if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3;
191     if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4;
192     if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
193     if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
194     if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
195   }
196   EXPECT_EQ(FoundMask, 255);
197 }
198 
TEST(FuzzerMutate,InsertByte1)199 TEST(FuzzerMutate, InsertByte1) {
200   TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
201 }
TEST(FuzzerMutate,InsertByte2)202 TEST(FuzzerMutate, InsertByte2) {
203   TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
204 }
205 
TestInsertRepeatedBytes(Mutator M,int NumIter)206 void TestInsertRepeatedBytes(Mutator M, int NumIter) {
207   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
208   fuzzer::EF = t.get();
209   Random Rand(0);
210   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
211   int FoundMask = 0;
212   uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
213   uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
214   uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
215   uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
216   uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
217 
218   uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
219   uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
220   uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
221   uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
222   uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
223 
224   for (int i = 0; i < NumIter; i++) {
225     uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
226     size_t NewSize = (*MD.*M)(T, 4, 8);
227     if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
228     if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
229     if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
230     if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
231     if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
232 
233     if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
234     if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
235     if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
236     if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
237     if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
238 
239   }
240   EXPECT_EQ(FoundMask, (1 << 10) - 1);
241 }
242 
TEST(FuzzerMutate,InsertRepeatedBytes1)243 TEST(FuzzerMutate, InsertRepeatedBytes1) {
244   TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
245 }
TEST(FuzzerMutate,InsertRepeatedBytes2)246 TEST(FuzzerMutate, InsertRepeatedBytes2) {
247   TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
248 }
249 
TestChangeByte(Mutator M,int NumIter)250 void TestChangeByte(Mutator M, int NumIter) {
251   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
252   fuzzer::EF = t.get();
253   Random Rand(0);
254   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
255   int FoundMask = 0;
256   uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
257   uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
258   uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
259   uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
260   uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
261   uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
262   uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
263   uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
264   for (int i = 0; i < NumIter; i++) {
265     uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
266     size_t NewSize = (*MD.*M)(T, 8, 9);
267     if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
268     if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
269     if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
270     if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
271     if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
272     if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
273     if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
274     if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
275   }
276   EXPECT_EQ(FoundMask, 255);
277 }
278 
TEST(FuzzerMutate,ChangeByte1)279 TEST(FuzzerMutate, ChangeByte1) {
280   TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
281 }
TEST(FuzzerMutate,ChangeByte2)282 TEST(FuzzerMutate, ChangeByte2) {
283   TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
284 }
285 
TestChangeBit(Mutator M,int NumIter)286 void TestChangeBit(Mutator M, int NumIter) {
287   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
288   fuzzer::EF = t.get();
289   Random Rand(0);
290   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
291   int FoundMask = 0;
292   uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
293   uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
294   uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
295   uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
296   uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
297   uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
298   uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
299   uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
300   for (int i = 0; i < NumIter; i++) {
301     uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
302     size_t NewSize = (*MD.*M)(T, 8, 9);
303     if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
304     if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
305     if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
306     if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
307     if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
308     if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
309     if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
310     if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
311   }
312   EXPECT_EQ(FoundMask, 255);
313 }
314 
TEST(FuzzerMutate,ChangeBit1)315 TEST(FuzzerMutate, ChangeBit1) {
316   TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
317 }
TEST(FuzzerMutate,ChangeBit2)318 TEST(FuzzerMutate, ChangeBit2) {
319   TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
320 }
321 
TestShuffleBytes(Mutator M,int NumIter)322 void TestShuffleBytes(Mutator M, int NumIter) {
323   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
324   fuzzer::EF = t.get();
325   Random Rand(0);
326   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
327   int FoundMask = 0;
328   uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
329   uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
330   uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
331   uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
332   uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
333   for (int i = 0; i < NumIter; i++) {
334     uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
335     size_t NewSize = (*MD.*M)(T, 7, 7);
336     if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
337     if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
338     if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
339     if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
340     if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
341   }
342   EXPECT_EQ(FoundMask, 31);
343 }
344 
TEST(FuzzerMutate,ShuffleBytes1)345 TEST(FuzzerMutate, ShuffleBytes1) {
346   TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17);
347 }
TEST(FuzzerMutate,ShuffleBytes2)348 TEST(FuzzerMutate, ShuffleBytes2) {
349   TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
350 }
351 
TestCopyPart(Mutator M,int NumIter)352 void TestCopyPart(Mutator M, int NumIter) {
353   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
354   fuzzer::EF = t.get();
355   Random Rand(0);
356   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
357   int FoundMask = 0;
358   uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
359   uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
360   uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
361   uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
362   uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
363 
364   for (int i = 0; i < NumIter; i++) {
365     uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
366     size_t NewSize = (*MD.*M)(T, 7, 7);
367     if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
368     if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
369     if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
370     if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
371     if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
372   }
373 
374   uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
375   uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
376   uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
377   uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
378   uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
379 
380   for (int i = 0; i < NumIter; i++) {
381     uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
382     size_t NewSize = (*MD.*M)(T, 5, 8);
383     if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
384     if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
385     if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
386     if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
387     if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
388   }
389 
390   EXPECT_EQ(FoundMask, 1023);
391 }
392 
TEST(FuzzerMutate,CopyPart1)393 TEST(FuzzerMutate, CopyPart1) {
394   TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
395 }
TEST(FuzzerMutate,CopyPart2)396 TEST(FuzzerMutate, CopyPart2) {
397   TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
398 }
TEST(FuzzerMutate,CopyPartNoInsertAtMaxSize)399 TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) {
400   // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an
401   // insert on an input of size `MaxSize`.  Performing an insert in this case
402   // will lead to the mutation failing.
403   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
404   fuzzer::EF = t.get();
405   Random Rand(0);
406   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
407   uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
408   size_t MaxSize = sizeof(Data);
409   for (int count = 0; count < (1 << 18); ++count) {
410     size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize);
411     ASSERT_EQ(NewSize, MaxSize);
412   }
413 }
414 
TestAddWordFromDictionary(Mutator M,int NumIter)415 void TestAddWordFromDictionary(Mutator M, int NumIter) {
416   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
417   fuzzer::EF = t.get();
418   Random Rand(0);
419   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
420   uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
421   uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
422   MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
423   MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
424   int FoundMask = 0;
425   uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
426   uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
427   uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
428   uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
429   uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
430   uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
431   uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
432   uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
433   for (int i = 0; i < NumIter; i++) {
434     uint8_t T[7] = {0x00, 0x11, 0x22};
435     size_t NewSize = (*MD.*M)(T, 3, 7);
436     if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
437     if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
438     if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
439     if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
440     if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
441     if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
442     if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
443     if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
444   }
445   EXPECT_EQ(FoundMask, 255);
446 }
447 
TEST(FuzzerMutate,AddWordFromDictionary1)448 TEST(FuzzerMutate, AddWordFromDictionary1) {
449   TestAddWordFromDictionary(
450       &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
451 }
452 
TEST(FuzzerMutate,AddWordFromDictionary2)453 TEST(FuzzerMutate, AddWordFromDictionary2) {
454   TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
455 }
456 
TestChangeASCIIInteger(Mutator M,int NumIter)457 void TestChangeASCIIInteger(Mutator M, int NumIter) {
458   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
459   fuzzer::EF = t.get();
460   Random Rand(0);
461   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
462 
463   uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
464   uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
465   uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
466   uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
467   int FoundMask = 0;
468   for (int i = 0; i < NumIter; i++) {
469     uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
470     size_t NewSize = (*MD.*M)(T, 8, 8);
471     /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
472     else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
473     else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
474     else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
475     else if (NewSize == 8)                       FoundMask |= 1 << 4;
476   }
477   EXPECT_EQ(FoundMask, 31);
478 }
479 
TEST(FuzzerMutate,ChangeASCIIInteger1)480 TEST(FuzzerMutate, ChangeASCIIInteger1) {
481   TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
482                          1 << 15);
483 }
484 
TEST(FuzzerMutate,ChangeASCIIInteger2)485 TEST(FuzzerMutate, ChangeASCIIInteger2) {
486   TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
487 }
488 
TestChangeBinaryInteger(Mutator M,int NumIter)489 void TestChangeBinaryInteger(Mutator M, int NumIter) {
490   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
491   fuzzer::EF = t.get();
492   Random Rand(0);
493   std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
494 
495   uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
496   uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
497   uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
498   uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
499   uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
500   uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
501   uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
502   uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
503 
504   int FoundMask = 0;
505   for (int i = 0; i < NumIter; i++) {
506     uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
507     size_t NewSize = (*MD.*M)(T, 8, 8);
508     /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
509     else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
510     else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
511     else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
512     else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
513     else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
514     else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
515     else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
516   }
517   EXPECT_EQ(FoundMask, 255);
518 }
519 
TEST(FuzzerMutate,ChangeBinaryInteger1)520 TEST(FuzzerMutate, ChangeBinaryInteger1) {
521   TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
522                          1 << 12);
523 }
524 
TEST(FuzzerMutate,ChangeBinaryInteger2)525 TEST(FuzzerMutate, ChangeBinaryInteger2) {
526   TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
527 }
528 
529 
TEST(FuzzerDictionary,ParseOneDictionaryEntry)530 TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
531   Unit U;
532   EXPECT_FALSE(ParseOneDictionaryEntry("", &U));
533   EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U));
534   EXPECT_FALSE(ParseOneDictionaryEntry("\t  ", &U));
535   EXPECT_FALSE(ParseOneDictionaryEntry("  \" ", &U));
536   EXPECT_FALSE(ParseOneDictionaryEntry("  zz\" ", &U));
537   EXPECT_FALSE(ParseOneDictionaryEntry("  \"zz ", &U));
538   EXPECT_FALSE(ParseOneDictionaryEntry("  \"\" ", &U));
539   EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U));
540   EXPECT_EQ(U, Unit({'a'}));
541   EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U));
542   EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
543   EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U));
544   EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
545   EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U));
546   EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U));
547   EXPECT_EQ(U, Unit({'\\'}));
548   EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U));
549   EXPECT_EQ(U, Unit({0xAB}));
550   EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U));
551   EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE}));
552   EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U));
553   EXPECT_EQ(U, Unit({'#'}));
554   EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U));
555   EXPECT_EQ(U, Unit({'"'}));
556 }
557 
TEST(FuzzerDictionary,ParseDictionaryFile)558 TEST(FuzzerDictionary, ParseDictionaryFile) {
559   Vector<Unit> Units;
560   EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units));
561   EXPECT_FALSE(ParseDictionaryFile("", &Units));
562   EXPECT_TRUE(ParseDictionaryFile("\n", &Units));
563   EXPECT_EQ(Units.size(), 0U);
564   EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units));
565   EXPECT_EQ(Units.size(), 0U);
566   EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
567   EXPECT_EQ(Units.size(), 0U);
568   EXPECT_TRUE(ParseDictionaryFile("  #zzzz\n", &Units));
569   EXPECT_EQ(Units.size(), 0U);
570   EXPECT_TRUE(ParseDictionaryFile("  #zzzz\naaa=\"aa\"", &Units));
571   EXPECT_EQ(Units, Vector<Unit>({Unit({'a', 'a'})}));
572   EXPECT_TRUE(
573       ParseDictionaryFile("  #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units));
574   EXPECT_EQ(Units,
575             Vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})}));
576 }
577 
TEST(FuzzerUtil,Base64)578 TEST(FuzzerUtil, Base64) {
579   EXPECT_EQ("", Base64({}));
580   EXPECT_EQ("YQ==", Base64({'a'}));
581   EXPECT_EQ("eA==", Base64({'x'}));
582   EXPECT_EQ("YWI=", Base64({'a', 'b'}));
583   EXPECT_EQ("eHk=", Base64({'x', 'y'}));
584   EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'}));
585   EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'}));
586   EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'}));
587   EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'}));
588   EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'}));
589 }
590 
TEST(Corpus,Distribution)591 TEST(Corpus, Distribution) {
592   DataFlowTrace DFT;
593   Random Rand(0);
594   std::unique_ptr<InputCorpus> C(new InputCorpus(""));
595   size_t N = 10;
596   size_t TriesPerUnit = 1<<16;
597   for (size_t i = 0; i < N; i++)
598     C->AddToCorpus(Unit{static_cast<uint8_t>(i)}, 1, false, false, {}, DFT,
599                    nullptr);
600 
601   Vector<size_t> Hist(N);
602   for (size_t i = 0; i < N * TriesPerUnit; i++) {
603     Hist[C->ChooseUnitIdxToMutate(Rand)]++;
604   }
605   for (size_t i = 0; i < N; i++) {
606     // A weak sanity check that every unit gets invoked.
607     EXPECT_GT(Hist[i], TriesPerUnit / N / 3);
608   }
609 }
610 
TEST(Merge,Bad)611 TEST(Merge, Bad) {
612   const char *kInvalidInputs[] = {
613     "",
614     "x",
615     "3\nx",
616     "2\n3",
617     "2\n2",
618     "2\n2\nA\n",
619     "2\n2\nA\nB\nC\n",
620     "0\n0\n",
621     "1\n1\nA\nDONE 0",
622     "1\n1\nA\nSTARTED 1",
623   };
624   Merger M;
625   for (auto S : kInvalidInputs) {
626     // fprintf(stderr, "TESTING:\n%s\n", S);
627     EXPECT_FALSE(M.Parse(S, false));
628   }
629 }
630 
EQ(const Vector<uint32_t> & A,const Vector<uint32_t> & B)631 void EQ(const Vector<uint32_t> &A, const Vector<uint32_t> &B) {
632   EXPECT_EQ(A, B);
633 }
634 
EQ(const Vector<std::string> & A,const Vector<std::string> & B)635 void EQ(const Vector<std::string> &A, const Vector<std::string> &B) {
636   Set<std::string> a(A.begin(), A.end());
637   Set<std::string> b(B.begin(), B.end());
638   EXPECT_EQ(a, b);
639 }
640 
Merge(const std::string & Input,const Vector<std::string> Result,size_t NumNewFeatures)641 static void Merge(const std::string &Input,
642                   const Vector<std::string> Result,
643                   size_t NumNewFeatures) {
644   Merger M;
645   Vector<std::string> NewFiles;
646   EXPECT_TRUE(M.Parse(Input, true));
647   std::stringstream SS;
648   M.PrintSummary(SS);
649   EXPECT_EQ(NumNewFeatures, M.Merge(&NewFiles));
650   EXPECT_EQ(M.AllFeatures(), M.ParseSummary(SS));
651   EQ(NewFiles, Result);
652 }
653 
TEST(Merge,Good)654 TEST(Merge, Good) {
655   Merger M;
656 
657   EXPECT_TRUE(M.Parse("1\n0\nAA\n", false));
658   EXPECT_EQ(M.Files.size(), 1U);
659   EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
660   EXPECT_EQ(M.Files[0].Name, "AA");
661   EXPECT_TRUE(M.LastFailure.empty());
662   EXPECT_EQ(M.FirstNotProcessedFile, 0U);
663 
664   EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false));
665   EXPECT_EQ(M.Files.size(), 2U);
666   EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
667   EXPECT_EQ(M.Files[0].Name, "AA");
668   EXPECT_EQ(M.Files[1].Name, "BB");
669   EXPECT_EQ(M.LastFailure, "AA");
670   EXPECT_EQ(M.FirstNotProcessedFile, 1U);
671 
672   EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
673                         "STARTED 0 1000\n"
674                         "DONE 0 1 2 3\n"
675                         "STARTED 1 1001\n"
676                         "DONE 1 4 5 6 \n"
677                         "STARTED 2 1002\n"
678                         "", true));
679   EXPECT_EQ(M.Files.size(), 3U);
680   EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
681   EXPECT_EQ(M.Files[0].Name, "AA");
682   EXPECT_EQ(M.Files[0].Size, 1000U);
683   EXPECT_EQ(M.Files[1].Name, "BB");
684   EXPECT_EQ(M.Files[1].Size, 1001U);
685   EXPECT_EQ(M.Files[2].Name, "C");
686   EXPECT_EQ(M.Files[2].Size, 1002U);
687   EXPECT_EQ(M.LastFailure, "C");
688   EXPECT_EQ(M.FirstNotProcessedFile, 3U);
689   EQ(M.Files[0].Features, {1, 2, 3});
690   EQ(M.Files[1].Features, {4, 5, 6});
691 
692 
693   Vector<std::string> NewFiles;
694 
695   EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
696                         "STARTED 0 1000\nDONE 0 1 2 3\n"
697                         "STARTED 1 1001\nDONE 1 4 5 6 \n"
698                         "STARTED 2 1002\nDONE 2 6 1 3 \n"
699                         "", true));
700   EXPECT_EQ(M.Files.size(), 3U);
701   EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
702   EXPECT_TRUE(M.LastFailure.empty());
703   EXPECT_EQ(M.FirstNotProcessedFile, 3U);
704   EQ(M.Files[0].Features, {1, 2, 3});
705   EQ(M.Files[1].Features, {4, 5, 6});
706   EQ(M.Files[2].Features, {1, 3, 6});
707   EXPECT_EQ(0U, M.Merge(&NewFiles));
708   EQ(NewFiles, {});
709 
710   EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
711                         "STARTED 0 1000\nDONE 0 1 2 3\n"
712                         "STARTED 1 1001\nDONE 1 4 5 6 \n"
713                         "STARTED 2 1002\nDONE 2 6 1 3\n"
714                         "", true));
715   EQ(M.Files[0].Features, {1, 2, 3});
716   EQ(M.Files[1].Features, {4, 5, 6});
717   EQ(M.Files[2].Features, {1, 3, 6});
718   EXPECT_EQ(3U, M.Merge(&NewFiles));
719   EQ(NewFiles, {"B"});
720 
721   // Same as the above, but with InitialFeatures.
722   EXPECT_TRUE(M.Parse("2\n0\nB\nC\n"
723                         "STARTED 0 1001\nDONE 0 4 5 6 \n"
724                         "STARTED 1 1002\nDONE 1 6 1 3\n"
725                         "", true));
726   EQ(M.Files[0].Features, {4, 5, 6});
727   EQ(M.Files[1].Features, {1, 3, 6});
728   Set<uint32_t> InitialFeatures;
729   InitialFeatures.insert(1);
730   InitialFeatures.insert(2);
731   InitialFeatures.insert(3);
732   EXPECT_EQ(3U, M.Merge(InitialFeatures, &NewFiles));
733   EQ(NewFiles, {"B"});
734 }
735 
TEST(Merge,Merge)736 TEST(Merge, Merge) {
737 
738   Merge("3\n1\nA\nB\nC\n"
739         "STARTED 0 1000\nDONE 0 1 2 3\n"
740         "STARTED 1 1001\nDONE 1 4 5 6 \n"
741         "STARTED 2 1002\nDONE 2 6 1 3 \n",
742         {"B"}, 3);
743 
744   Merge("3\n0\nA\nB\nC\n"
745         "STARTED 0 2000\nDONE 0 1 2 3\n"
746         "STARTED 1 1001\nDONE 1 4 5 6 \n"
747         "STARTED 2 1002\nDONE 2 6 1 3 \n",
748         {"A", "B", "C"}, 6);
749 
750   Merge("4\n0\nA\nB\nC\nD\n"
751         "STARTED 0 2000\nDONE 0 1 2 3\n"
752         "STARTED 1 1101\nDONE 1 4 5 6 \n"
753         "STARTED 2 1102\nDONE 2 6 1 3 100 \n"
754         "STARTED 3 1000\nDONE 3 1  \n",
755         {"A", "B", "C", "D"}, 7);
756 
757   Merge("4\n1\nA\nB\nC\nD\n"
758         "STARTED 0 2000\nDONE 0 4 5 6 7 8\n"
759         "STARTED 1 1100\nDONE 1 1 2 3 \n"
760         "STARTED 2 1100\nDONE 2 2 3 \n"
761         "STARTED 3 1000\nDONE 3 1  \n",
762         {"B", "D"}, 3);
763 }
764 
TEST(Fuzzer,ForEachNonZeroByte)765 TEST(Fuzzer, ForEachNonZeroByte) {
766   const size_t N = 64;
767   alignas(64) uint8_t Ar[N + 8] = {
768     0, 0, 0, 0, 0, 0, 0, 0,
769     1, 2, 0, 0, 0, 0, 0, 0,
770     0, 0, 3, 0, 4, 0, 0, 0,
771     0, 0, 0, 0, 0, 0, 0, 0,
772     0, 0, 0, 5, 0, 6, 0, 0,
773     0, 0, 0, 0, 0, 0, 7, 0,
774     0, 0, 0, 0, 0, 0, 0, 0,
775     0, 0, 0, 0, 0, 0, 0, 8,
776     9, 9, 9, 9, 9, 9, 9, 9,
777   };
778   typedef Vector<std::pair<size_t, uint8_t> > Vec;
779   Vec Res, Expected;
780   auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) {
781     Res.push_back({FirstFeature + Idx, V});
782   };
783   ForEachNonZeroByte(Ar, Ar + N, 100, CB);
784   Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4},
785               {135, 5}, {137, 6}, {146, 7}, {163, 8}};
786   EXPECT_EQ(Res, Expected);
787 
788   Res.clear();
789   ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB);
790   Expected = {          {109, 2}, {118, 3}, {120, 4},
791               {135, 5}, {137, 6}, {146, 7}, {163, 8}};
792   EXPECT_EQ(Res, Expected);
793 
794   Res.clear();
795   ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB);
796   Expected = {          {109, 2}, {118, 3}, {120, 4},
797               {135, 5}, {137, 6}, {146, 7}};
798   EXPECT_EQ(Res, Expected);
799 }
800 
801 // FuzzerCommand unit tests. The arguments in the two helper methods below must
802 // match.
makeCommandArgs(Vector<std::string> * ArgsToAdd)803 static void makeCommandArgs(Vector<std::string> *ArgsToAdd) {
804   assert(ArgsToAdd);
805   ArgsToAdd->clear();
806   ArgsToAdd->push_back("foo");
807   ArgsToAdd->push_back("-bar=baz");
808   ArgsToAdd->push_back("qux");
809   ArgsToAdd->push_back(Command::ignoreRemainingArgs());
810   ArgsToAdd->push_back("quux");
811   ArgsToAdd->push_back("-grault=garply");
812 }
813 
makeCmdLine(const char * separator,const char * suffix)814 static std::string makeCmdLine(const char *separator, const char *suffix) {
815   std::string CmdLine("foo -bar=baz qux ");
816   if (strlen(separator) != 0) {
817     CmdLine += separator;
818     CmdLine += " ";
819   }
820   CmdLine += Command::ignoreRemainingArgs();
821   CmdLine += " quux -grault=garply";
822   if (strlen(suffix) != 0) {
823     CmdLine += " ";
824     CmdLine += suffix;
825   }
826   return CmdLine;
827 }
828 
TEST(FuzzerCommand,Create)829 TEST(FuzzerCommand, Create) {
830   std::string CmdLine;
831 
832   // Default constructor
833   Command DefaultCmd;
834 
835   CmdLine = DefaultCmd.toString();
836   EXPECT_EQ(CmdLine, "");
837 
838   // Explicit constructor
839   Vector<std::string> ArgsToAdd;
840   makeCommandArgs(&ArgsToAdd);
841   Command InitializedCmd(ArgsToAdd);
842 
843   CmdLine = InitializedCmd.toString();
844   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
845 
846   // Compare each argument
847   auto InitializedArgs = InitializedCmd.getArguments();
848   auto i = ArgsToAdd.begin();
849   auto j = InitializedArgs.begin();
850   while (i != ArgsToAdd.end() && j != InitializedArgs.end()) {
851     EXPECT_EQ(*i++, *j++);
852   }
853   EXPECT_EQ(i, ArgsToAdd.end());
854   EXPECT_EQ(j, InitializedArgs.end());
855 
856   // Copy constructor
857   Command CopiedCmd(InitializedCmd);
858 
859   CmdLine = CopiedCmd.toString();
860   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
861 
862   // Assignment operator
863   Command AssignedCmd;
864   AssignedCmd = CopiedCmd;
865 
866   CmdLine = AssignedCmd.toString();
867   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
868 }
869 
TEST(FuzzerCommand,ModifyArguments)870 TEST(FuzzerCommand, ModifyArguments) {
871   Vector<std::string> ArgsToAdd;
872   makeCommandArgs(&ArgsToAdd);
873   Command Cmd;
874   std::string CmdLine;
875 
876   Cmd.addArguments(ArgsToAdd);
877   CmdLine = Cmd.toString();
878   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
879 
880   Cmd.addArgument("waldo");
881   EXPECT_TRUE(Cmd.hasArgument("waldo"));
882 
883   CmdLine = Cmd.toString();
884   EXPECT_EQ(CmdLine, makeCmdLine("waldo", ""));
885 
886   Cmd.removeArgument("waldo");
887   EXPECT_FALSE(Cmd.hasArgument("waldo"));
888 
889   CmdLine = Cmd.toString();
890   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
891 }
892 
TEST(FuzzerCommand,ModifyFlags)893 TEST(FuzzerCommand, ModifyFlags) {
894   Vector<std::string> ArgsToAdd;
895   makeCommandArgs(&ArgsToAdd);
896   Command Cmd(ArgsToAdd);
897   std::string Value, CmdLine;
898   ASSERT_FALSE(Cmd.hasFlag("fred"));
899 
900   Value = Cmd.getFlagValue("fred");
901   EXPECT_EQ(Value, "");
902 
903   CmdLine = Cmd.toString();
904   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
905 
906   Cmd.addFlag("fred", "plugh");
907   EXPECT_TRUE(Cmd.hasFlag("fred"));
908 
909   Value = Cmd.getFlagValue("fred");
910   EXPECT_EQ(Value, "plugh");
911 
912   CmdLine = Cmd.toString();
913   EXPECT_EQ(CmdLine, makeCmdLine("-fred=plugh", ""));
914 
915   Cmd.removeFlag("fred");
916   EXPECT_FALSE(Cmd.hasFlag("fred"));
917 
918   Value = Cmd.getFlagValue("fred");
919   EXPECT_EQ(Value, "");
920 
921   CmdLine = Cmd.toString();
922   EXPECT_EQ(CmdLine, makeCmdLine("", ""));
923 }
924 
TEST(FuzzerCommand,SetOutput)925 TEST(FuzzerCommand, SetOutput) {
926   Vector<std::string> ArgsToAdd;
927   makeCommandArgs(&ArgsToAdd);
928   Command Cmd(ArgsToAdd);
929   std::string CmdLine;
930   ASSERT_FALSE(Cmd.hasOutputFile());
931   ASSERT_FALSE(Cmd.isOutAndErrCombined());
932 
933   Cmd.combineOutAndErr(true);
934   EXPECT_TRUE(Cmd.isOutAndErrCombined());
935 
936   CmdLine = Cmd.toString();
937   EXPECT_EQ(CmdLine, makeCmdLine("", "2>&1"));
938 
939   Cmd.combineOutAndErr(false);
940   EXPECT_FALSE(Cmd.isOutAndErrCombined());
941 
942   Cmd.setOutputFile("xyzzy");
943   EXPECT_TRUE(Cmd.hasOutputFile());
944 
945   CmdLine = Cmd.toString();
946   EXPECT_EQ(CmdLine, makeCmdLine("", ">xyzzy"));
947 
948   Cmd.setOutputFile("thud");
949   EXPECT_TRUE(Cmd.hasOutputFile());
950 
951   CmdLine = Cmd.toString();
952   EXPECT_EQ(CmdLine, makeCmdLine("", ">thud"));
953 
954   Cmd.combineOutAndErr();
955   EXPECT_TRUE(Cmd.isOutAndErrCombined());
956 
957   CmdLine = Cmd.toString();
958   EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1"));
959 }
960 
main(int argc,char ** argv)961 int main(int argc, char **argv) {
962   testing::InitGoogleTest(&argc, argv);
963   return RUN_ALL_TESTS();
964 }
965