12946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 22946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 32946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 410ab2aceSGeorge Karpenkov 510ab2aceSGeorge Karpenkov // Make sure the fuzzer eventually finds all possible values of a variable 610ab2aceSGeorge Karpenkov // within a range. 710ab2aceSGeorge Karpenkov #include <cassert> 810ab2aceSGeorge Karpenkov #include <cstdint> 910ab2aceSGeorge Karpenkov #include <cstdio> 1010ab2aceSGeorge Karpenkov #include <cstdlib> 1110ab2aceSGeorge Karpenkov #include <cstring> 1210ab2aceSGeorge Karpenkov #include <set> 1310ab2aceSGeorge Karpenkov 1410ab2aceSGeorge Karpenkov const size_t N = 1 << 12; 1510ab2aceSGeorge Karpenkov 1610ab2aceSGeorge Karpenkov // Define an array of counters that will be understood by libFuzzer 1710ab2aceSGeorge Karpenkov // as extra coverage signal. The array must be: 1810ab2aceSGeorge Karpenkov // * uint8_t 1910ab2aceSGeorge Karpenkov // * in the section named __libfuzzer_extra_counters. 2010ab2aceSGeorge Karpenkov // The target code may declare more than one such array. 2110ab2aceSGeorge Karpenkov // 2210ab2aceSGeorge Karpenkov // Use either `Counters[Idx] = 1` or `Counters[Idx]++;` 2310ab2aceSGeorge Karpenkov // depending on whether multiple occurrences of the event 'Idx' 2410ab2aceSGeorge Karpenkov // is important to distinguish from one occurrence. 25*95141aa9SAndrew Turner #if defined(__linux__) || defined(__FreeBSD__) 2610ab2aceSGeorge Karpenkov __attribute__((section("__libfuzzer_extra_counters"))) 2710ab2aceSGeorge Karpenkov #endif 28881faf41SMatt Morehouse #ifdef _WIN32 29881faf41SMatt Morehouse # pragma section(".data$__libfuzzer_extra_counters") 30881faf41SMatt Morehouse __declspec(allocate(".data$__libfuzzer_extra_counters")) 31881faf41SMatt Morehouse #endif 3210ab2aceSGeorge Karpenkov static uint8_t Counters[N]; 3310ab2aceSGeorge Karpenkov LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)3410ab2aceSGeorge Karpenkovextern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 3510ab2aceSGeorge Karpenkov static std::set<uint16_t> SeenIdx; 3610ab2aceSGeorge Karpenkov if (Size != 4) return 0; 3710ab2aceSGeorge Karpenkov uint32_t Idx; 3810ab2aceSGeorge Karpenkov memcpy(&Idx, Data, 4); 3910ab2aceSGeorge Karpenkov Idx %= N; 4010ab2aceSGeorge Karpenkov assert(Counters[Idx] == 0); // libFuzzer should reset these between the runs. 4110ab2aceSGeorge Karpenkov // Or Counters[Idx]=1 if we don't care how many times this happened. 4210ab2aceSGeorge Karpenkov Counters[Idx]++; 4310ab2aceSGeorge Karpenkov SeenIdx.insert(Idx); 4410ab2aceSGeorge Karpenkov if (SeenIdx.size() == N) { 4510ab2aceSGeorge Karpenkov fprintf(stderr, "BINGO: found all values\n"); 4610ab2aceSGeorge Karpenkov abort(); 4710ab2aceSGeorge Karpenkov } 4810ab2aceSGeorge Karpenkov return 0; 4910ab2aceSGeorge Karpenkov } 50