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

source code of compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp