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 | // Make sure the fuzzer eventually finds all possible values of a variable |
6 | // within a range. |
7 | #include <cassert> |
8 | #include <cstdint> |
9 | #include <cstdio> |
10 | #include <cstdlib> |
11 | #include <cstring> |
12 | #include <set> |
13 | |
14 | const size_t N = 1 << 12; |
15 | |
16 | // Define an array of counters that will be understood by libFuzzer |
17 | // as extra coverage signal. The array must be: |
18 | // * uint8_t |
19 | // * in the section named __libfuzzer_extra_counters. |
20 | // The target code may declare more than one such array. |
21 | // |
22 | // Use either `Counters[Idx] = 1` or `Counters[Idx]++;` |
23 | // depending on whether multiple occurrences of the event 'Idx' |
24 | // is important to distinguish from one occurrence. |
25 | #if defined(__linux__) || defined(__FreeBSD__) |
26 | __attribute__((section("__libfuzzer_extra_counters" ))) |
27 | #endif |
28 | #ifdef _WIN32 |
29 | # pragma section(".data$__libfuzzer_extra_counters") |
30 | __declspec(allocate(".data$__libfuzzer_extra_counters" )) |
31 | #endif |
32 | static uint8_t Counters[N]; |
33 | |
34 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
35 | static std::set<uint16_t> SeenIdx; |
36 | if (Size != 4) return 0; |
37 | uint32_t Idx; |
38 | memcpy(dest: &Idx, src: Data, n: 4); |
39 | Idx %= N; |
40 | assert(Counters[Idx] == 0); // libFuzzer should reset these between the runs. |
41 | // Or Counters[Idx]=1 if we don't care how many times this happened. |
42 | Counters[Idx]++; |
43 | SeenIdx.insert(x: Idx); |
44 | if (SeenIdx.size() == N) { |
45 | fprintf(stderr, format: "BINGO: found all values\n" ); |
46 | abort(); |
47 | } |
48 | return 0; |
49 | } |
50 | |