diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2017-08-21 23:25:50 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2017-08-21 23:25:50 +0000 |
commit | 0c8339c8aab25f1156558e9e2082b4b124dc2327 (patch) | |
tree | 4f04d28abce4cbaa73fbba2b64f56af353e0f08b /test/fuzzer | |
parent | 1a32c939c5eece22f3ca6cf70bd05a1527bc0970 (diff) |
Move libFuzzer to compiler_rt.
Resulting library binaries will be named libclang_rt.fuzzer*, and will
be placed in Clang toolchain, allowing redistribution.
Differential Revision: https://reviews.llvm.org/D36908
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@311407 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/fuzzer')
146 files changed, 2748 insertions, 0 deletions
diff --git a/test/fuzzer/AFLDriverTest.cpp b/test/fuzzer/AFLDriverTest.cpp new file mode 100644 index 000000000..b949adc7d --- /dev/null +++ b/test/fuzzer/AFLDriverTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Contains dummy functions used to avoid dependency on AFL. +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +extern "C" void __afl_manual_init() {} + +extern "C" int __afl_persistent_loop(unsigned int N) { + static int Count = N; + fprintf(stderr, "__afl_persistent_loop calle, Count = %d\n", Count); + if (Count--) return 1; + return 0; +} + +// This declaration exists to prevent the Darwin linker +// from complaining about this being a missing weak symbol. +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + fprintf(stderr, "LLVMFuzzerInitialize called\n"); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + fprintf(stderr, "LLVMFuzzerTestOneInput called; Size = %zd\n", Size); + return 0; +} diff --git a/test/fuzzer/AbsNegAndConstant64Test.cpp b/test/fuzzer/AbsNegAndConstant64Test.cpp new file mode 100644 index 000000000..abeb784e9 --- /dev/null +++ b/test/fuzzer/AbsNegAndConstant64Test.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// abs(x) < 0 and y == Const puzzle, 64-bit variant. +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 16) return 0; + int64_t x; + uint64_t y; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + sizeof(x), sizeof(y)); + if (llabs(x) < 0 && y == 0xbaddcafedeadbeefULL) { + printf("BINGO; Found the target, exiting; x = 0x%lx y 0x%lx\n", x, y); + fflush(stdout); + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/AbsNegAndConstantTest.cpp b/test/fuzzer/AbsNegAndConstantTest.cpp new file mode 100644 index 000000000..049db0a60 --- /dev/null +++ b/test/fuzzer/AbsNegAndConstantTest.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// abs(x) < 0 and y == Const puzzle. +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + int x; + unsigned y; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + sizeof(x), sizeof(y)); + if (abs(x) < 0 && y == 0xbaddcafe) { + printf("BINGO; Found the target, exiting; x = 0x%x y 0x%x\n", x, y); + fflush(stdout); + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/AccumulateAllocationsTest.cpp b/test/fuzzer/AccumulateAllocationsTest.cpp new file mode 100644 index 000000000..e9acd7ccb --- /dev/null +++ b/test/fuzzer/AccumulateAllocationsTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a more mallocs than frees, but no leak. +#include <cstddef> +#include <cstdint> + +const int kAllocatedPointersSize = 10000; +int NumAllocatedPointers = 0; +int *AllocatedPointers[kAllocatedPointersSize]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (NumAllocatedPointers < kAllocatedPointersSize) + AllocatedPointers[NumAllocatedPointers++] = new int; + return 0; +} + diff --git a/test/fuzzer/BadStrcmpTest.cpp b/test/fuzzer/BadStrcmpTest.cpp new file mode 100644 index 000000000..ba2b068f7 --- /dev/null +++ b/test/fuzzer/BadStrcmpTest.cpp @@ -0,0 +1,19 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we don't creash in case of bad strcmp params. +#include <cstddef> +#include <cstdint> +#include <cstring> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size != 10) return 0; + // Data is not zero-terminated, so this call is bad. + // Still, there are cases when such calles appear, see e.g. + // https://bugs.llvm.org/show_bug.cgi?id=32357 + Sink = strcmp(reinterpret_cast<const char*>(Data), "123456789"); + return 0; +} + diff --git a/test/fuzzer/BogusInitializeTest.cpp b/test/fuzzer/BogusInitializeTest.cpp new file mode 100644 index 000000000..c7e81a547 --- /dev/null +++ b/test/fuzzer/BogusInitializeTest.cpp @@ -0,0 +1,15 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Make sure LLVMFuzzerInitialize does not change argv[0]. +#include <stddef.h> +#include <stdint.h> + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + ***argv = 'X'; + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} diff --git a/test/fuzzer/BufferOverflowOnInput.cpp b/test/fuzzer/BufferOverflowOnInput.cpp new file mode 100644 index 000000000..159da92d4 --- /dev/null +++ b/test/fuzzer/BufferOverflowOnInput.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <ostream> + +static volatile bool SeedLargeBuffer; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size >= 4) + SeedLargeBuffer = true; + if (Size == 3 && SeedLargeBuffer && Data[3]) { + std::cout << "Woops, reading Data[3] w/o crashing\n" << std::flush; + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/CMakeLists.txt b/test/fuzzer/CMakeLists.txt new file mode 100644 index 000000000..339978a82 --- /dev/null +++ b/test/fuzzer/CMakeLists.txt @@ -0,0 +1,40 @@ +set(LIBFUZZER_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +if (NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND LIBFUZZER_TEST_DEPS fuzzer asan) +endif() + +if(COMPILER_RT_INCLUDE_TESTS) + list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests) +endif() + +set(LIBFUZZER_TESTSUITES) + + +if(COMPILER_RT_INCLUDE_TESTS) + # libFuzzer unit tests. + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg) + list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit) +endif() + +foreach(arch ${FUZZER_SUPPORTED_ARCH}) + set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) + get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS) + + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + + # LIT-based libFuzzer tests. + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg + ) + list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + +endforeach() + +add_lit_testsuite(check-fuzzer "Running Fuzzer tests" + ${LIBFUZZER_TESTSUITES} + DEPENDS ${LIBFUZZER_TEST_DEPS}) +set_target_properties(check-fuzzer PROPERTIES FOLDER "Compiler-RT Tests") diff --git a/test/fuzzer/CallerCalleeTest.cpp b/test/fuzzer/CallerCalleeTest.cpp new file mode 100644 index 000000000..ed9f37cc1 --- /dev/null +++ b/test/fuzzer/CallerCalleeTest.cpp @@ -0,0 +1,59 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. +// Try to find the target using the indirect caller-callee pairs. +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> + +typedef void (*F)(); +static F t[256]; + +void f34() { + std::cerr << "BINGO\n"; + exit(1); +} +void f23() { t[(unsigned)'d'] = f34;} +void f12() { t[(unsigned)'c'] = f23;} +void f01() { t[(unsigned)'b'] = f12;} +void f00() {} + +static F t0[256] = { + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + // Spoof the counters. + for (int i = 0; i < 200; i++) { + f23(); + f12(); + f01(); + } + memcpy(t, t0, sizeof(t)); + t[(unsigned)'a'] = f01; + t[Data[0]](); + t[Data[1]](); + t[Data[2]](); + t[Data[3]](); + return 0; +} + diff --git a/test/fuzzer/CleanseTest.cpp b/test/fuzzer/CleanseTest.cpp new file mode 100644 index 000000000..ee1845701 --- /dev/null +++ b/test/fuzzer/CleanseTest.cpp @@ -0,0 +1,16 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test the the fuzzer is able to 'cleanse' the reproducer +// by replacing all irrelevant bytes with garbage. +#include <cstddef> +#include <cstdint> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 20 && Data[1] == '1' && Data[5] == '5' && Data[10] == 'A' && + Data[19] == 'Z') + abort(); + return 0; +} + diff --git a/test/fuzzer/CounterTest.cpp b/test/fuzzer/CounterTest.cpp new file mode 100644 index 000000000..4917934c6 --- /dev/null +++ b/test/fuzzer/CounterTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test for a fuzzer: must find the case where a particular basic block is +// executed many times. +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Num = 0; + for (size_t i = 0; i < Size; i++) + if (Data[i] == 'A' + i) + Num++; + if (Num >= 4) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} diff --git a/test/fuzzer/CustomCrossOverAndMutateTest.cpp b/test/fuzzer/CustomCrossOverAndMutateTest.cpp new file mode 100644 index 000000000..74fc93953 --- /dev/null +++ b/test/fuzzer/CustomCrossOverAndMutateTest.cpp @@ -0,0 +1,34 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that libFuzzer does not crash when LLVMFuzzerMutate called from +// LLVMFuzzerCustomCrossOver. +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <string.h> +#include <string> +#include <vector> + +#include "FuzzerInterface.h" + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + std::string Str(reinterpret_cast<const char *>(Data), Size); + if (Size && Data[0] == '0') + sink++; + return 0; +} + +extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize, + unsigned int Seed) { + std::vector<uint8_t> Buffer(MaxOutSize * 10); + LLVMFuzzerMutate(Buffer.data(), Buffer.size(), Buffer.size()); + size_t Size = std::min(Size1, MaxOutSize); + memcpy(Out, Data1, Size); + return Size; +} diff --git a/test/fuzzer/CustomCrossOverTest.cpp b/test/fuzzer/CustomCrossOverTest.cpp new file mode 100644 index 000000000..58059c9c1 --- /dev/null +++ b/test/fuzzer/CustomCrossOverTest.cpp @@ -0,0 +1,64 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a cutom mutator. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <ostream> +#include <random> +#include <string.h> + +#include "FuzzerInterface.h" + +static const char *Separator = "-_^_-"; +static const char *Target = "012-_^_-abc"; + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + std::string Str(reinterpret_cast<const char *>(Data), Size); + + // Ensure that two different elements exist in the corpus. + if (Size && Data[0] == '0') sink++; + if (Size && Data[0] == 'a') sink--; + + if (Str.find(Target) != std::string::npos) { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + exit(1); + } + return 0; +} + +extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize, + unsigned int Seed) { + static bool Printed; + static size_t SeparatorLen = strlen(Separator); + + if (!Printed) { + std::cerr << "In LLVMFuzzerCustomCrossover\n"; + Printed = true; + } + + std::mt19937 R(Seed); + + size_t Offset1 = 0; + size_t Len1 = R() % (Size1 - Offset1); + size_t Offset2 = 0; + size_t Len2 = R() % (Size2 - Offset2); + size_t Size = Len1 + Len2 + SeparatorLen; + + if (Size > MaxOutSize) + return 0; + + memcpy(Out, Data1 + Offset1, Len1); + memcpy(Out + Len1, Separator, SeparatorLen); + memcpy(Out + Len1 + SeparatorLen, Data2 + Offset2, Len2); + + return Len1 + Len2 + SeparatorLen; +} diff --git a/test/fuzzer/CustomMutatorTest.cpp b/test/fuzzer/CustomMutatorTest.cpp new file mode 100644 index 000000000..b2adb9408 --- /dev/null +++ b/test/fuzzer/CustomMutatorTest.cpp @@ -0,0 +1,39 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a cutom mutator. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <ostream> + +#include "FuzzerInterface.h" + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + exit(1); + } + } + } + return 0; +} + +extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, + size_t MaxSize, unsigned int Seed) { + static bool Printed; + if (!Printed) { + std::cerr << "In LLVMFuzzerCustomMutator\n"; + Printed = true; + } + return LLVMFuzzerMutate(Data, Size, MaxSize); +} diff --git a/test/fuzzer/CxxStringEqTest.cpp b/test/fuzzer/CxxStringEqTest.cpp new file mode 100644 index 000000000..924851c5a --- /dev/null +++ b/test/fuzzer/CxxStringEqTest.cpp @@ -0,0 +1,25 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. Must find a specific string +// used in std::string operator ==. +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <string> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + std::string Str((const char*)Data, Size); + bool Eq = Str == "FooBar"; + Sink = Str == "123456"; // Try to confuse the fuzzer + if (Eq) { + std::cout << "BINGO; Found the target, exiting\n"; + std::cout.flush(); + abort(); + } + return 0; +} + diff --git a/test/fuzzer/DSO1.cpp b/test/fuzzer/DSO1.cpp new file mode 100644 index 000000000..72a5ec4a0 --- /dev/null +++ b/test/fuzzer/DSO1.cpp @@ -0,0 +1,14 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. +#ifdef _WIN32 +__declspec( dllexport ) +#endif +int DSO1(int a) { + if (a < 123456) + return 0; + return 1; +} + +void Uncovered1() { } diff --git a/test/fuzzer/DSO2.cpp b/test/fuzzer/DSO2.cpp new file mode 100644 index 000000000..2967055dc --- /dev/null +++ b/test/fuzzer/DSO2.cpp @@ -0,0 +1,14 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. +#ifdef _WIN32 +__declspec( dllexport ) +#endif +int DSO2(int a) { + if (a < 3598235) + return 0; + return 1; +} + +void Uncovered2() {} diff --git a/test/fuzzer/DSOTestExtra.cpp b/test/fuzzer/DSOTestExtra.cpp new file mode 100644 index 000000000..a2274d070 --- /dev/null +++ b/test/fuzzer/DSOTestExtra.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +int DSOTestExtra(int a) { + if (a < 452345) + return 0; + return 1; +} + diff --git a/test/fuzzer/DSOTestMain.cpp b/test/fuzzer/DSOTestMain.cpp new file mode 100644 index 000000000..e0c857d4f --- /dev/null +++ b/test/fuzzer/DSOTestMain.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +extern int DSO1(int a); +extern int DSO2(int a); +extern int DSOTestExtra(int a); + +static volatile int *nil = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int x, y, z; + if (Size < sizeof(int) * 3) { + x = y = z = 0; + } else { + memcpy(&x, Data + 0 * sizeof(int), sizeof(int)); + memcpy(&y, Data + 1 * sizeof(int), sizeof(int)); + memcpy(&z, Data + 2 * sizeof(int), sizeof(int)); + } + int sum = DSO1(x) + DSO2(y) + (z ? DSOTestExtra(z) : 0); + if (sum == 3) { + fprintf(stderr, "BINGO %d %d %d\n", x, y, z); + *nil = 0; + } + return 0; +} diff --git a/test/fuzzer/DeepRecursionTest.cpp b/test/fuzzer/DeepRecursionTest.cpp new file mode 100644 index 000000000..bf4621d04 --- /dev/null +++ b/test/fuzzer/DeepRecursionTest.cpp @@ -0,0 +1,25 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the deep recursion. +// To generate a crashy input: +// for((i=0;i<110;i++)); do echo -n ABCDEFGHIJ >> INPUT; done +#include <cstddef> +#include <cstdint> +#include <cstdlib> + +static volatile int Sink; + +void Recursive(const uint8_t *Data, size_t Size, int Depth) { + if (Depth > 1000) abort(); + if (!Size) return; + if (*Data == ('A' + Depth % 10)) + Recursive(Data + 1, Size - 1, Depth + 1); + Sink++; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + Recursive(Data, Size, 0); + return 0; +} + diff --git a/test/fuzzer/DivTest.cpp b/test/fuzzer/DivTest.cpp new file mode 100644 index 000000000..bce13feb7 --- /dev/null +++ b/test/fuzzer/DivTest.cpp @@ -0,0 +1,20 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer: find the interesting argument for div. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + int a; + memcpy(&a, Data, 4); + Sink = 12345678 / (987654 - a); + return 0; +} + diff --git a/test/fuzzer/EmptyTest.cpp b/test/fuzzer/EmptyTest.cpp new file mode 100644 index 000000000..5e843308f --- /dev/null +++ b/test/fuzzer/EmptyTest.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// A fuzzer with empty target function. + +#include <cstdint> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} diff --git a/test/fuzzer/EquivalenceATest.cpp b/test/fuzzer/EquivalenceATest.cpp new file mode 100644 index 000000000..7d1ebb0f6 --- /dev/null +++ b/test/fuzzer/EquivalenceATest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +// Test for libFuzzer's "equivalence" fuzzing, part A. +extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // fprintf(stderr, "A %zd\n", Size); + uint8_t Result[50]; + if (Size > 50) Size = 50; + for (size_t i = 0; i < Size; i++) + Result[Size - i - 1] = Data[i]; + LLVMFuzzerAnnounceOutput(Result, Size); + return 0; +} diff --git a/test/fuzzer/EquivalenceBTest.cpp b/test/fuzzer/EquivalenceBTest.cpp new file mode 100644 index 000000000..b1de208b5 --- /dev/null +++ b/test/fuzzer/EquivalenceBTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +// Test for libFuzzer's "equivalence" fuzzing, part B. +extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // fprintf(stderr, "B %zd\n", Size); + uint8_t Result[50]; + if (Size > 50) Size = 50; + for (size_t i = 0; i < Size; i++) + Result[Size - i - 1] = Data[i]; + + // Be a bit different from EquivalenceATest + if (Size > 10 && Data[5] == 'B' && Data[6] == 'C' && Data[7] == 'D') { + static int c; + if (!c) + fprintf(stderr, "ZZZZZZZ\n"); + c = 1; + Result[2]++; + } + + LLVMFuzzerAnnounceOutput(Result, Size); + return 0; +} diff --git a/test/fuzzer/FlagsTest.cpp b/test/fuzzer/FlagsTest.cpp new file mode 100644 index 000000000..ac64b9d48 --- /dev/null +++ b/test/fuzzer/FlagsTest.cpp @@ -0,0 +1,32 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Parse some flags +#include <string> +#include <vector> + +static std::vector<std::string> Flags; + +extern "C" int LLVMFuzzerInitialize(int *Argc, char ***Argv) { + // Parse --flags and anything after -ignore_remaining_args=1 is passed. + int I = 1; + while (I < *Argc) { + std::string S((*Argv)[I++]); + if (S == "-ignore_remaining_args=1") + break; + if (S.substr(0, 2) == "--") + Flags.push_back(S); + } + while (I < *Argc) + Flags.push_back(std::string((*Argv)[I++])); + + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + fprintf(stderr, "BINGO "); + for (auto Flag : Flags) + fprintf(stderr, "%s ", Flag.c_str()); + fprintf(stderr, "\n"); + exit(0); +} diff --git a/test/fuzzer/FourIndependentBranchesTest.cpp b/test/fuzzer/FourIndependentBranchesTest.cpp new file mode 100644 index 000000000..bbf5ea235 --- /dev/null +++ b/test/fuzzer/FourIndependentBranchesTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "FUZZ". +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (bits == 15) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/FullCoverageSetTest.cpp b/test/fuzzer/FullCoverageSetTest.cpp new file mode 100644 index 000000000..6d7e48fe5 --- /dev/null +++ b/test/fuzzer/FullCoverageSetTest.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "FUZZER". +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (Size > 4 && Data[4] == 'E') bits |= 16; + if (Size > 5 && Data[5] == 'R') bits |= 32; + if (bits == 63) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/InitializeTest.cpp b/test/fuzzer/InitializeTest.cpp new file mode 100644 index 000000000..d640a8d10 --- /dev/null +++ b/test/fuzzer/InitializeTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Make sure LLVMFuzzerInitialize is called. +#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static char *argv0; + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + assert(*argc > 0); + argv0 = **argv; + fprintf(stderr, "LLVMFuzzerInitialize: %s\n", argv0); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == strlen(argv0) && + !memmem(Data, Size, argv0, Size)) { + fprintf(stderr, "BINGO %s\n", argv0); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/LargeTest.cpp b/test/fuzzer/LargeTest.cpp new file mode 100644 index 000000000..83ed61971 --- /dev/null +++ b/test/fuzzer/LargeTest.cpp @@ -0,0 +1,37 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// A fuzz target with lots of edges. +#include <cstdint> +#include <cstdlib> + +static inline void break_optimization(const void *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); +} + +#define A \ + do { \ + i++; \ + c++; \ + if (Data[(i + __LINE__) % Size] == (c % 256)) \ + break_optimization(Data); \ + else \ + break_optimization(0); \ + } while (0) + +// for (int i = 0, n = Data[(__LINE__ - 1) % Size] % 16; i < n; i++) + +#define B do{A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; }while(0) +#define C do{B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; }while(0) +#define D do{C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; }while(0) +#define E do{D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; }while(0) + +volatile int sink; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + int c = 0; + int i = 0; + D; + return 0; +} + diff --git a/test/fuzzer/LeakTest.cpp b/test/fuzzer/LeakTest.cpp new file mode 100644 index 000000000..ea89e3901 --- /dev/null +++ b/test/fuzzer/LeakTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a leak. +#include <cstddef> +#include <cstdint> + +static volatile void *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && *Data == 'H') { + Sink = new int; + Sink = nullptr; + } + return 0; +} + diff --git a/test/fuzzer/LeakTimeoutTest.cpp b/test/fuzzer/LeakTimeoutTest.cpp new file mode 100644 index 000000000..92526194a --- /dev/null +++ b/test/fuzzer/LeakTimeoutTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a leak. +#include <cstddef> +#include <cstdint> + +static volatile int *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + Sink = new int; + Sink = new int; + while (Sink) *Sink = 0; // Infinite loop. + return 0; +} + diff --git a/test/fuzzer/LoadTest.cpp b/test/fuzzer/LoadTest.cpp new file mode 100644 index 000000000..67a28c7cb --- /dev/null +++ b/test/fuzzer/LoadTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer: find interesting value of array index. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <iostream> + +static volatile int Sink; +const int kArraySize = 1234567; +int array[kArraySize]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + uint64_t a = 0; + memcpy(&a, Data, 8); + Sink = array[a % (kArraySize + 1)]; + return 0; +} + diff --git a/test/fuzzer/Memcmp64BytesTest.cpp b/test/fuzzer/Memcmp64BytesTest.cpp new file mode 100644 index 000000000..5b6cb7071 --- /dev/null +++ b/test/fuzzer/Memcmp64BytesTest.cpp @@ -0,0 +1,20 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cassert> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char kString64Bytes[] = + "123456789 123456789 123456789 123456789 123456789 123456789 1234"; + assert(sizeof(kString64Bytes) == 65); + if (Size >= 64 && memcmp(Data, kString64Bytes, 64) == 0) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/MemcmpTest.cpp b/test/fuzzer/MemcmpTest.cpp new file mode 100644 index 000000000..8dbb7d84f --- /dev/null +++ b/test/fuzzer/MemcmpTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) { + if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) { + if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) { + if (Size >= 17 && memcmp(Data + 14, "KLM", 3) == 0) { + if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){ + fprintf(stderr, "BINGO %zd\n", Size); + for (size_t i = 0; i < Size; i++) { + uint8_t C = Data[i]; + if (C >= 32 && C < 127) + fprintf(stderr, "%c", C); + } + fprintf(stderr, "\n"); + exit(1); + } + } + } + } + } + return 0; +} diff --git a/test/fuzzer/NotinstrumentedTest.cpp b/test/fuzzer/NotinstrumentedTest.cpp new file mode 100644 index 000000000..91418990b --- /dev/null +++ b/test/fuzzer/NotinstrumentedTest.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// This test should not be instrumented. +#include <cstddef> +#include <cstdint> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} + diff --git a/test/fuzzer/NthRunCrashTest.cpp b/test/fuzzer/NthRunCrashTest.cpp new file mode 100644 index 000000000..26cdc8f17 --- /dev/null +++ b/test/fuzzer/NthRunCrashTest.cpp @@ -0,0 +1,19 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Crash on the N-th execution. +#include <cstddef> +#include <cstdint> +#include <iostream> +#include <ostream> + +static int Counter; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Counter++ == 1000) { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/NullDerefOnEmptyTest.cpp b/test/fuzzer/NullDerefOnEmptyTest.cpp new file mode 100644 index 000000000..459db51f8 --- /dev/null +++ b/test/fuzzer/NullDerefOnEmptyTest.cpp @@ -0,0 +1,19 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the empty string. +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int *Null = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == 0) { + std::cout << "Found the target, dereferencing NULL\n"; + *Null = 1; + } + return 0; +} + diff --git a/test/fuzzer/NullDerefTest.cpp b/test/fuzzer/NullDerefTest.cpp new file mode 100644 index 000000000..1b44b682a --- /dev/null +++ b/test/fuzzer/NullDerefTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int Sink; +static volatile int *Null = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "Found the target, dereferencing NULL\n"; + *Null = 1; + } + } + } + return 0; +} + diff --git a/test/fuzzer/OneHugeAllocTest.cpp b/test/fuzzer/OneHugeAllocTest.cpp new file mode 100644 index 000000000..32a557871 --- /dev/null +++ b/test/fuzzer/OneHugeAllocTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling when there is a single large allocation. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + size_t kSize = (size_t)1 << 31; + char *p = new char[kSize]; + memset(p, 0, kSize); + SinkPtr = p; + delete [] p; + } + } + } + return 0; +} + diff --git a/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp b/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp new file mode 100644 index 000000000..a07795a08 --- /dev/null +++ b/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + size_t kSize = 0x20000000U; + char *p = new char[kSize]; + SinkPtr = p; + delete [] p; + } + } + } + return 0; +} + diff --git a/test/fuzzer/OutOfMemoryTest.cpp b/test/fuzzer/OutOfMemoryTest.cpp new file mode 100644 index 000000000..5e59bde09 --- /dev/null +++ b/test/fuzzer/OutOfMemoryTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <thread> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + while (true) { + size_t kSize = 1 << 28; + char *p = new char[kSize]; + memset(p, 0, kSize); + SinkPtr = p; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + } + return 0; +} + diff --git a/test/fuzzer/OverwriteInputTest.cpp b/test/fuzzer/OverwriteInputTest.cpp new file mode 100644 index 000000000..e68868234 --- /dev/null +++ b/test/fuzzer/OverwriteInputTest.cpp @@ -0,0 +1,13 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. Make sure we abort if Data is overwritten. +#include <cstdint> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size) + *const_cast<uint8_t*>(Data) = 1; + return 0; +} + diff --git a/test/fuzzer/RepeatedBytesTest.cpp b/test/fuzzer/RepeatedBytesTest.cpp new file mode 100644 index 000000000..31868cf8c --- /dev/null +++ b/test/fuzzer/RepeatedBytesTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find repeated bytes. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <ostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such. + size_t CurA = 0, MaxA = 0; + for (size_t i = 0; i < Size; i++) { + // Make sure there are no conditionals in the loop so that + // coverage can't help the fuzzer. + int EQ = Data[i] == 'A'; + CurA = EQ * (CurA + 1); + int GT = CurA > MaxA; + MaxA = GT * CurA + (!GT) * MaxA; + } + if (MaxA >= 20) { + std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n" + << std::flush; + exit(0); + } + return 0; +} + diff --git a/test/fuzzer/RepeatedMemcmp.cpp b/test/fuzzer/RepeatedMemcmp.cpp new file mode 100644 index 000000000..18369deac --- /dev/null +++ b/test/fuzzer/RepeatedMemcmp.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Matches1 = 0; + for (size_t i = 0; i + 2 < Size; i += 3) + if (!memcmp(Data + i, "foo", 3)) + Matches1++; + int Matches2 = 0; + for (size_t i = 0; i + 2 < Size; i += 3) + if (!memcmp(Data + i, "bar", 3)) + Matches2++; + + if (Matches1 > 10 && Matches2 > 10) { + fprintf(stderr, "BINGO!\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/ShrinkControlFlowSimpleTest.cpp b/test/fuzzer/ShrinkControlFlowSimpleTest.cpp new file mode 100644 index 000000000..0afd26df2 --- /dev/null +++ b/test/fuzzer/ShrinkControlFlowSimpleTest.cpp @@ -0,0 +1,19 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 2) return 0; + if (Data[0] == 'F' && Data[Size / 2] == 'U' && Data[Size - 1] == 'Z') + Sink++; + return 0; +} + diff --git a/test/fuzzer/ShrinkControlFlowTest.cpp b/test/fuzzer/ShrinkControlFlowTest.cpp new file mode 100644 index 000000000..1957c1f90 --- /dev/null +++ b/test/fuzzer/ShrinkControlFlowTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +static volatile int Sink; + +void Foo() { + Sink++; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int8_t Ids[256]; + memset(Ids, -1, sizeof(Ids)); + for (size_t i = 0; i < Size; i++) + if (Ids[Data[i]] == -1) + Ids[Data[i]] = i; + int F = Ids[(unsigned char)'F']; + int U = Ids[(unsigned char)'U']; + int Z = Ids[(unsigned char)'Z']; + if (F >= 0 && U > F && Z > U) { + Foo(); + } + return 0; +} + diff --git a/test/fuzzer/ShrinkValueProfileTest.cpp b/test/fuzzer/ShrinkValueProfileTest.cpp new file mode 100644 index 000000000..86e4e3cb0 --- /dev/null +++ b/test/fuzzer/ShrinkValueProfileTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +static volatile uint32_t Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < sizeof(uint32_t)) return 0; + uint32_t X, Y; + size_t Offset = Size < 8 ? 0 : Size / 2; + memcpy(&X, Data + Offset, sizeof(uint32_t)); + memcpy(&Y, "FUZZ", sizeof(uint32_t)); + Sink = X == Y; + return 0; +} + diff --git a/test/fuzzer/SignedIntOverflowTest.cpp b/test/fuzzer/SignedIntOverflowTest.cpp new file mode 100644 index 000000000..d80060207 --- /dev/null +++ b/test/fuzzer/SignedIntOverflowTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test for signed-integer-overflow. +#include <assert.h> +#include <climits> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int Sink; +static int Large = INT_MAX; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + Large++; // int overflow. + } + } + } + return 0; +} + diff --git a/test/fuzzer/SimpleCmpTest.cpp b/test/fuzzer/SimpleCmpTest.cpp new file mode 100644 index 000000000..8acad4ac7 --- /dev/null +++ b/test/fuzzer/SimpleCmpTest.cpp @@ -0,0 +1,47 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find several narrow ranges. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern int AllLines[]; + +bool PrintOnce(int Line) { + if (!AllLines[Line]) + fprintf(stderr, "Seen line %d\n", Line); + AllLines[Line] = 1; + return true; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size != 22) return 0; + uint64_t x = 0; + int64_t y = 0; + int32_t z = 0; + uint16_t a = 0; + memcpy(&x, Data, 8); // 8 + memcpy(&y, Data + 8, 8); // 16 + memcpy(&z, Data + 16, sizeof(z)); // 20 + memcpy(&a, Data + 20, sizeof(a)); // 22 + const bool k32bit = sizeof(void*) == 4; + + if ((k32bit || x > 1234567890) && PrintOnce(__LINE__) && + (k32bit || x < 1234567895) && PrintOnce(__LINE__) && + a == 0x4242 && PrintOnce(__LINE__) && + (k32bit || y >= 987654321) && PrintOnce(__LINE__) && + (k32bit || y <= 987654325) && PrintOnce(__LINE__) && + z < -10000 && PrintOnce(__LINE__) && + z >= -10005 && PrintOnce(__LINE__) && + z != -10003 && PrintOnce(__LINE__) && + true) { + fprintf(stderr, "BINGO; Found the target: size %zd (%zd, %zd, %d, %d), exiting.\n", + Size, x, y, z, a); + exit(1); + } + return 0; +} + +int AllLines[__LINE__ + 1]; // Must be the last line. diff --git a/test/fuzzer/SimpleDictionaryTest.cpp b/test/fuzzer/SimpleDictionaryTest.cpp new file mode 100644 index 000000000..ffa2e4137 --- /dev/null +++ b/test/fuzzer/SimpleDictionaryTest.cpp @@ -0,0 +1,30 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. +// The fuzzer must find a string based on dictionary words: +// "Elvis" +// "Presley" +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <ostream> + +static volatile int Zero = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *Expected = "ElvisPresley"; + if (Size < strlen(Expected)) return 0; + size_t Match = 0; + for (size_t i = 0; Expected[i]; i++) + if (Expected[i] + Zero == Data[i]) + Match++; + if (Match == strlen(Expected)) { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/SimpleHashTest.cpp b/test/fuzzer/SimpleHashTest.cpp new file mode 100644 index 000000000..99e96cb25 --- /dev/null +++ b/test/fuzzer/SimpleHashTest.cpp @@ -0,0 +1,40 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// This test computes a checksum of the data (all but the last 4 bytes), +// and then compares the last 4 bytes with the computed value. +// A fuzzer with cmp traces is expected to defeat this check. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +// A modified jenkins_one_at_a_time_hash initialized by non-zero, +// so that simple_hash(0) != 0. See also +// https://en.wikipedia.org/wiki/Jenkins_hash_function +static uint32_t simple_hash(const uint8_t *Data, size_t Size) { + uint32_t Hash = 0x12039854; + for (uint32_t i = 0; i < Size; i++) { + Hash += Data[i]; + Hash += (Hash << 10); + Hash ^= (Hash >> 6); + } + Hash += (Hash << 3); + Hash ^= (Hash >> 11); + Hash += (Hash << 15); + return Hash; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) + return 0; + + uint32_t Hash = simple_hash(&Data[0], Size - 4); + uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0]; + if (Hash != Want) + return 0; + fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash, + (unsigned int)Want); + exit(1); + return 0; +} diff --git a/test/fuzzer/SimpleTest.cpp b/test/fuzzer/SimpleTest.cpp new file mode 100644 index 000000000..3882a842b --- /dev/null +++ b/test/fuzzer/SimpleTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <ostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + exit(0); + } + } + } + return 0; +} + diff --git a/test/fuzzer/SimpleThreadedTest.cpp b/test/fuzzer/SimpleThreadedTest.cpp new file mode 100644 index 000000000..deeae756a --- /dev/null +++ b/test/fuzzer/SimpleThreadedTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Threaded test for a fuzzer. The fuzzer should find "H" +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <iostream> +#include <ostream> +#include <thread> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + auto C = [&] { + if (Size >= 2 && Data[0] == 'H') { + std::cout << "BINGO; Found the target, exiting\n" << std::flush; + abort(); + } + }; + std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), + std::thread(C), std::thread(C), std::thread(C)}; + for (auto &X : T) + X.join(); + return 0; +} + diff --git a/test/fuzzer/SingleByteInputTest.cpp b/test/fuzzer/SingleByteInputTest.cpp new file mode 100644 index 000000000..72b58ba91 --- /dev/null +++ b/test/fuzzer/SingleByteInputTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer, need just one byte to crash. +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[Size/2] == 42) { + fprintf(stderr, "BINGO\n"); + abort(); + } + return 0; +} + diff --git a/test/fuzzer/SingleMemcmpTest.cpp b/test/fuzzer/SingleMemcmpTest.cpp new file mode 100644 index 000000000..19781ba4c --- /dev/null +++ b/test/fuzzer/SingleMemcmpTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *S = (const char*)Data; + if (Size >= 6 && !memcmp(S, "qwerty", 6)) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/SingleStrcmpTest.cpp b/test/fuzzer/SingleStrcmpTest.cpp new file mode 100644 index 000000000..149073444 --- /dev/null +++ b/test/fuzzer/SingleStrcmpTest.cpp @@ -0,0 +1,21 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 7) { + char Copy[7]; + memcpy(Copy, Data, 6); + Copy[6] = 0; + if (!strcmp(Copy, "qwerty")) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + } + return 0; +} diff --git a/test/fuzzer/SingleStrncmpTest.cpp b/test/fuzzer/SingleStrncmpTest.cpp new file mode 100644 index 000000000..47298763f --- /dev/null +++ b/test/fuzzer/SingleStrncmpTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *S = (const char*)Data; + volatile auto Strncmp = &(strncmp); // Make sure strncmp is not inlined. + if (Size >= 6 && !Strncmp(S, "qwerty", 6)) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/SpamyTest.cpp b/test/fuzzer/SpamyTest.cpp new file mode 100644 index 000000000..721134e18 --- /dev/null +++ b/test/fuzzer/SpamyTest.cpp @@ -0,0 +1,21 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The test spams to stderr and stdout. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + printf("PRINTF_STDOUT\n"); + fflush(stdout); + fprintf(stderr, "PRINTF_STDERR\n"); + std::cout << "STREAM_COUT\n"; + std::cout.flush(); + std::cerr << "STREAM_CERR\n"; + return 0; +} + diff --git a/test/fuzzer/StrcmpTest.cpp b/test/fuzzer/StrcmpTest.cpp new file mode 100644 index 000000000..81f041d91 --- /dev/null +++ b/test/fuzzer/StrcmpTest.cpp @@ -0,0 +1,32 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Break through a series of strcmp. +#include <cassert> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +bool Eq(const uint8_t *Data, size_t Size, const char *Str) { + char Buff[1024]; + size_t Len = strlen(Str); + if (Size < Len) return false; + if (Len >= sizeof(Buff)) return false; + memcpy(Buff, (const char*)Data, Len); + Buff[Len] = 0; + int res = strcmp(Buff, Str); + return res == 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Eq(Data, Size, "ABC") && + Size >= 3 && Eq(Data + 3, Size - 3, "QWER") && + Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") && + Size >= 14 && Data[13] == 42 + ) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/StrncmpOOBTest.cpp b/test/fuzzer/StrncmpOOBTest.cpp new file mode 100644 index 000000000..4ed71d9d0 --- /dev/null +++ b/test/fuzzer/StrncmpOOBTest.cpp @@ -0,0 +1,21 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that libFuzzer itself does not read out of bounds. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 5) return 0; + const char *Ch = reinterpret_cast<const char *>(Data); + if (Ch[Size - 3] == 'a') + Sink = strncmp(Ch + Size - 3, "abcdefg", 6); + return 0; +} + diff --git a/test/fuzzer/StrncmpTest.cpp b/test/fuzzer/StrncmpTest.cpp new file mode 100644 index 000000000..a40e05690 --- /dev/null +++ b/test/fuzzer/StrncmpTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + const char *S = (const char*)Data; + if (Size >= 8 && strncmp(S, "123", 8)) + sink = 1; + if (Size >= 8 && strncmp(S, "01234567", 8) == 0) { + if (Size >= 12 && strncmp(S + 8, "ABCD", 4) == 0) { + if (Size >= 14 && strncmp(S + 12, "XY", 2) == 0) { + if (Size >= 17 && strncmp(S + 14, "KLM", 3) == 0) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + } + } + } + return 0; +} diff --git a/test/fuzzer/StrstrTest.cpp b/test/fuzzer/StrstrTest.cpp new file mode 100644 index 000000000..a3ea4e03b --- /dev/null +++ b/test/fuzzer/StrstrTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test strstr and strcasestr hooks. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <string.h> +#include <string> + +// Windows does not have strcasestr and memmem, so we are not testing them. +#ifdef _WIN32 +#define strcasestr strstr +#define memmem(a, b, c, d) true +#endif + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + std::string s(reinterpret_cast<const char*>(Data), Size); + if (strstr(s.c_str(), "FUZZ") && + strcasestr(s.c_str(), "aBcD") && + memmem(s.data(), s.size(), "kuku", 4) + ) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzzer/SwapCmpTest.cpp b/test/fuzzer/SwapCmpTest.cpp new file mode 100644 index 000000000..bbfbefe6a --- /dev/null +++ b/test/fuzzer/SwapCmpTest.cpp @@ -0,0 +1,35 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The fuzzer must find several constants with swapped bytes. +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) return 0; + uint64_t x = 0; + uint32_t y = 0; + uint16_t z = 0; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + Size / 2, sizeof(y)); + memcpy(&z, Data + Size - sizeof(z), sizeof(z)); + + x = __builtin_bswap64(x); + y = __builtin_bswap32(y); + z = __builtin_bswap16(z); + const bool k32bit = sizeof(void*) == 4; + + if ((k32bit || x == 0x46555A5A5A5A5546ULL) && + z == 0x4F4B && + y == 0x66757A7A && + true + ) { + if (Data[Size - 3] == 'z') { + fprintf(stderr, "BINGO; Found the target\n"); + exit(1); + } + } + return 0; +} diff --git a/test/fuzzer/Switch2Test.cpp b/test/fuzzer/Switch2Test.cpp new file mode 100644 index 000000000..5f66ac8b4 --- /dev/null +++ b/test/fuzzer/Switch2Test.cpp @@ -0,0 +1,35 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the interesting switch value. +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +int Switch(int a) { + switch(a) { + case 100001: return 1; + case 100002: return 2; + case 100003: return 4; + } + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const int N = 3; + if (Size < N * sizeof(int)) return 0; + int Res = 0; + for (int i = 0; i < N; i++) { + int X; + memcpy(&X, Data + i * sizeof(int), sizeof(int)); + Res += Switch(X); + } + if (Res == 5 || Res == 3 || Res == 6 || Res == 7) { + fprintf(stderr, "BINGO; Found the target, exiting; Res=%d\n", Res); + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/SwitchTest.cpp b/test/fuzzer/SwitchTest.cpp new file mode 100644 index 000000000..86944cad2 --- /dev/null +++ b/test/fuzzer/SwitchTest.cpp @@ -0,0 +1,58 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the interesting switch value. +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +static volatile int Sink; + +template<class T> +bool Switch(const uint8_t *Data, size_t Size) { + T X; + if (Size < sizeof(X)) return false; + memcpy(&X, Data, sizeof(X)); + switch (X) { + case 1: Sink = __LINE__; break; + case 101: Sink = __LINE__; break; + case 1001: Sink = __LINE__; break; + case 10001: Sink = __LINE__; break; + case 100001: Sink = __LINE__; break; + case 1000001: Sink = __LINE__; break; + case 10000001: Sink = __LINE__; break; + case 100000001: return true; + } + return false; +} + +bool ShortSwitch(const uint8_t *Data, size_t Size) { + short X; + if (Size < sizeof(short)) return false; + memcpy(&X, Data, sizeof(short)); + switch(X) { + case 42: Sink = __LINE__; break; + case 402: Sink = __LINE__; break; + case 4002: Sink = __LINE__; break; + case 5002: Sink = __LINE__; break; + case 7002: Sink = __LINE__; break; + case 9002: Sink = __LINE__; break; + case 14002: Sink = __LINE__; break; + case 21402: return true; + } + return false; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 4 && Switch<int>(Data, Size) && + Size >= 12 && Switch<uint64_t>(Data + 4, Size - 4) && + Size >= 14 && ShortSwitch(Data + 12, 2) + ) { + fprintf(stderr, "BINGO; Found the target, exiting\n"); + exit(1); + } + return 0; +} + diff --git a/test/fuzzer/TableLookupTest.cpp b/test/fuzzer/TableLookupTest.cpp new file mode 100644 index 000000000..4d8ab0611 --- /dev/null +++ b/test/fuzzer/TableLookupTest.cpp @@ -0,0 +1,44 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Make sure the fuzzer eventually finds all possible values of a variable +// within a range. +#include <cassert> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <set> + +const size_t N = 1 << 12; + +// Define an array of counters that will be understood by libFuzzer +// as extra coverage signal. The array must be: +// * uint8_t +// * in the section named __libfuzzer_extra_counters. +// The target code may declare more than one such array. +// +// Use either `Counters[Idx] = 1` or `Counters[Idx]++;` +// depending on whether multiple occurrences of the event 'Idx' +// is important to distinguish from one occurrence. +#ifdef __linux__ +__attribute__((section("__libfuzzer_extra_counters"))) +#endif +static uint8_t Counters[N]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static std::set<uint16_t> SeenIdx; + if (Size != 4) return 0; + uint32_t Idx; + memcpy(&Idx, Data, 4); + Idx %= N; + assert(Counters[Idx] == 0); // libFuzzer should reset these between the runs. + // Or Counters[Idx]=1 if we don't care how many times this happened. + Counters[Idx]++; + SeenIdx.insert(Idx); + if (SeenIdx.size() == N) { + fprintf(stderr, "BINGO: found all values\n"); + abort(); + } + return 0; +} diff --git a/test/fuzzer/ThreadedLeakTest.cpp b/test/fuzzer/ThreadedLeakTest.cpp new file mode 100644 index 000000000..538d3b434 --- /dev/null +++ b/test/fuzzer/ThreadedLeakTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The fuzzer should find a leak in a non-main thread. +#include <cstddef> +#include <cstdint> +#include <thread> + +static volatile int *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == 0) return 0; + if (Data[0] != 'F') return 0; + std::thread T([&] { Sink = new int; }); + T.join(); + return 0; +} + diff --git a/test/fuzzer/ThreadedTest.cpp b/test/fuzzer/ThreadedTest.cpp new file mode 100644 index 000000000..bb51ba764 --- /dev/null +++ b/test/fuzzer/ThreadedTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Threaded test for a fuzzer. The fuzzer should not crash. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <thread> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + assert(Data); + auto C = [&] { + size_t Res = 0; + for (size_t i = 0; i < Size / 2; i++) + Res += memcmp(Data, Data + Size / 2, 4); + return Res; + }; + std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), + std::thread(C), std::thread(C), std::thread(C)}; + for (auto &X : T) + X.join(); + return 0; +} + diff --git a/test/fuzzer/TimeoutEmptyTest.cpp b/test/fuzzer/TimeoutEmptyTest.cpp new file mode 100644 index 000000000..1ddf1fa34 --- /dev/null +++ b/test/fuzzer/TimeoutEmptyTest.cpp @@ -0,0 +1,14 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the empty string. +#include <cstddef> +#include <cstdint> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static volatile int Zero = 0; + if (!Size) + while(!Zero) + ; + return 0; +} diff --git a/test/fuzzer/TimeoutTest.cpp b/test/fuzzer/TimeoutTest.cpp new file mode 100644 index 000000000..e3cdba3ee --- /dev/null +++ b/test/fuzzer/TimeoutTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + Sink = 2; + while (Sink) + ; + } + } + } + return 0; +} + diff --git a/test/fuzzer/TraceMallocTest.cpp b/test/fuzzer/TraceMallocTest.cpp new file mode 100644 index 000000000..af9975603 --- /dev/null +++ b/test/fuzzer/TraceMallocTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests -trace_malloc +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +int *Ptr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + if (*Data == 1) { + delete Ptr; + Ptr = nullptr; + } else if (*Data == 2) { + delete Ptr; + Ptr = new int; + } else if (*Data == 3) { + if (!Ptr) + Ptr = new int; + } + return 0; +} + diff --git a/test/fuzzer/TwoDifferentBugsTest.cpp b/test/fuzzer/TwoDifferentBugsTest.cpp new file mode 100644 index 000000000..77d2cb1a2 --- /dev/null +++ b/test/fuzzer/TwoDifferentBugsTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. This test may trigger two different bugs. +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int *Null = 0; + +void Foo() { Null[1] = 0; } +void Bar() { Null[2] = 0; } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 10 && Data[0] == 'H') + Foo(); + if (Size >= 10 && Data[0] == 'H') + Bar(); + return 0; +} + diff --git a/test/fuzzer/afl-driver-extra-stats.test b/test/fuzzer/afl-driver-extra-stats.test new file mode 100644 index 000000000..a6de53302 --- /dev/null +++ b/test/fuzzer/afl-driver-extra-stats.test @@ -0,0 +1,30 @@ +RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest + +; Test that not specifying an extra stats file isn't broken. +RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME +RUN: %t-AFLDriverTest + +; Test that specifying an invalid extra stats file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash %t-AFLDriverTest + +; Test that specifying a corrupted stats file causes a crash. +echo "peak_rss_mb :0" > %t +ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%t not --crash %t-AFLDriverTest + +; Test that specifying a valid nonexistent stats file works. +RUN: rm -f %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest +RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]] + +; Test that specifying a valid preexisting stats file works. +RUN: printf "peak_rss_mb : 0\nslowest_unit_time_sec: 0\n" > %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest +; Check that both lines were printed. +RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]] + +; Test that peak_rss_mb and slowest_unit_time_in_secs are only updated when necessary. +; Check that both lines have 9999 since there's no way we have exceeded that +; amount of time or virtual memory. +RUN: printf "peak_rss_mb : 9999\nslowest_unit_time_sec: 9999\n" > %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest +RUN: [[ $(grep "9999" %t | wc -l) -eq 2 ]] diff --git a/test/fuzzer/afl-driver-stderr.test b/test/fuzzer/afl-driver-stderr.test new file mode 100644 index 000000000..be0efaa8f --- /dev/null +++ b/test/fuzzer/afl-driver-stderr.test @@ -0,0 +1,12 @@ +RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest + +; Test that not specifying a stderr file isn't broken. +RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME +RUN: %t-AFLDriverTest + +; Test that specifying an invalid file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash %t-AFLDriverTest + +; Test that a file is created when specified as the duplicate stderr. +RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t %t-AFLDriverTest +RUN: stat %t diff --git a/test/fuzzer/afl-driver.test b/test/fuzzer/afl-driver.test new file mode 100644 index 000000000..32e7d03b4 --- /dev/null +++ b/test/fuzzer/afl-driver.test @@ -0,0 +1,29 @@ +REQUIRES: linux + +RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest + +RUN: echo -n "abc" > %t.file3 +RUN: echo -n "abcd" > %t.file4 + +RUN: %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK1 +CHECK1: __afl_persistent_loop calle, Count = 1000 +CHECK1: LLVMFuzzerTestOneInput called; Size = 3 + + +RUN: %t-AFLDriverTest < %t.file3 -42 2>&1 | FileCheck %s --check-prefix=CHECK2 +CHECK2: __afl_persistent_loop calle, Count = 42 +CHECK2: LLVMFuzzerTestOneInput called; Size = 3 + + +RUN: %t-AFLDriverTest < %t.file3 666 2>&1 | FileCheck %s --check-prefix=CHECK3 +CHECK3: WARNING: using the deprecated call style +CHECK3: __afl_persistent_loop calle, Count = 666 +CHECK3: LLVMFuzzerTestOneInput called; Size = 3 + + +RUN: %t-AFLDriverTest %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK4 +CHECK4: LLVMFuzzerTestOneInput called; Size = 3 + +RUN: %t-AFLDriverTest %t.file3 %t.file4 2>&1 | FileCheck %s --check-prefix=CHECK5 +CHECK5: LLVMFuzzerTestOneInput called; Size = 3 +CHECK5: LLVMFuzzerTestOneInput called; Size = 4 diff --git a/test/fuzzer/bad-strcmp.test b/test/fuzzer/bad-strcmp.test new file mode 100644 index 000000000..fd1621a4e --- /dev/null +++ b/test/fuzzer/bad-strcmp.test @@ -0,0 +1,2 @@ +RUN: %cpp_compiler %S/BadStrcmpTest.cpp -o %t-BadStrcmpTest +RUN: %t-BadStrcmpTest -runs=100000 diff --git a/test/fuzzer/caller-callee.test b/test/fuzzer/caller-callee.test new file mode 100644 index 000000000..e4eccdc30 --- /dev/null +++ b/test/fuzzer/caller-callee.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/CallerCalleeTest.cpp -o %t-CallerCalleeTest +CHECK: BINGO +RUN: not %t-CallerCalleeTest -use_value_profile=1 -cross_over=0 -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/cleanse.test b/test/fuzzer/cleanse.test new file mode 100644 index 000000000..8e45dc77d --- /dev/null +++ b/test/fuzzer/cleanse.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/CleanseTest.cpp -o %t-CleanseTest +RUN: echo -n 0123456789ABCDEFGHIZ > %t-in +RUN: %t-CleanseTest -cleanse_crash=1 %t-in -exact_artifact_path=%t-out +RUN: echo -n ' 1 5 A Z' | diff - %t-out diff --git a/test/fuzzer/coverage.test b/test/fuzzer/coverage.test new file mode 100644 index 000000000..9a2179d91 --- /dev/null +++ b/test/fuzzer/coverage.test @@ -0,0 +1,21 @@ +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest + +CHECK: COVERAGE: +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13 +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14 +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16 +RUN: not %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s + +RUN: %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO +DSO: COVERAGE: +DSO-DAG: COVERED:{{.*}}DSO1{{.*}}DSO1.cpp +DSO-DAG: COVERED:{{.*}}DSO2{{.*}}DSO2.cpp +DSO-DAG: COVERED:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain +DSO-DAG: UNCOVERED_LINE:{{.*}}DSO1{{.*}}DSO1.cpp +DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}DSO2.cpp +DSO-DAG: UNCOVERED_FUNC: in Uncovered1 +DSO-DAG: UNCOVERED_FUNC: in Uncovered2 +DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput diff --git a/test/fuzzer/cxxstring.test b/test/fuzzer/cxxstring.test new file mode 100644 index 000000000..7bb341ba2 --- /dev/null +++ b/test/fuzzer/cxxstring.test @@ -0,0 +1,6 @@ +UNSUPPORTED: windows + +RUN: %cpp_compiler %S/CxxStringEqTest.cpp -o %t-CxxStringEqTest + +RUN: not %t-CxxStringEqTest -seed=1 -runs=1000000 2>&1 | FileCheck %s +CHECK: BINGO diff --git a/test/fuzzer/dict1.txt b/test/fuzzer/dict1.txt new file mode 100644 index 000000000..520d0cc7b --- /dev/null +++ b/test/fuzzer/dict1.txt @@ -0,0 +1,4 @@ +# Dictionary for SimpleDictionaryTest + +a="Elvis" +b="Presley" diff --git a/test/fuzzer/disable-leaks.test b/test/fuzzer/disable-leaks.test new file mode 100644 index 000000000..bc120d98b --- /dev/null +++ b/test/fuzzer/disable-leaks.test @@ -0,0 +1,5 @@ +REQUIRES: lsan +RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest +RUN: %t-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS +ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation + diff --git a/test/fuzzer/dump_coverage.test b/test/fuzzer/dump_coverage.test new file mode 100644 index 000000000..a733355ee --- /dev/null +++ b/test/fuzzer/dump_coverage.test @@ -0,0 +1,20 @@ +RUN: %cpp_compiler %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so +RUN: %cpp_compiler %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so +RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest + +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest + +RUN: rm -rf %t_workdir && mkdir -p %t_workdir +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s +RUN: sancov -covered-functions %t-NullDerefTest* %t_workdir/*.sancov | FileCheck %s --check-prefix=SANCOV +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' %t-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV + +CHECK: SanitizerCoverage: {{.*}}NullDerefTest.{{.*}}.sancov: {{.*}} PCs written +SANCOV: LLVMFuzzerTestOneInput + +DSO: SanitizerCoverage: {{.*}}DSOTest.{{.*}}.sancov: {{.*}} PCs written +DSO-DAG: SanitizerCoverage: {{.*}}DSO1.{{.*}}.sancov: {{.*}} PCs written +DSO-DAG: SanitizerCoverage: {{.*}}DSO2.{{.*}}.sancov: {{.*}} PCs written + +NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written diff --git a/test/fuzzer/equivalence-signals.test b/test/fuzzer/equivalence-signals.test new file mode 100644 index 000000000..7951636e8 --- /dev/null +++ b/test/fuzzer/equivalence-signals.test @@ -0,0 +1,9 @@ +# Run EquivalenceATest against itself with a small timeout +# to stress the signal handling and ensure that shmem doesn't mind +# the signals. + +RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest +RUN: %t-EquivalenceATest -timeout=1 -run_equivalence_server=EQUIV_SIG_TEST & export APID=$! +RUN: sleep 3 +RUN: %t-EquivalenceATest -timeout=1 -use_equivalence_server=EQUIV_SIG_TEST -runs=500000 2>&1 +RUN: kill -9 $APID diff --git a/test/fuzzer/equivalence.test b/test/fuzzer/equivalence.test new file mode 100644 index 000000000..12964f478 --- /dev/null +++ b/test/fuzzer/equivalence.test @@ -0,0 +1,9 @@ +RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest +RUN: %cpp_compiler %S/EquivalenceBTest.cpp -o %t-EquivalenceBTest + +RUN: %t-EquivalenceATest -run_equivalence_server=EQUIV_TEST & export APID=$! +RUN: sleep 3 +RUN: not %t-EquivalenceBTest -use_equivalence_server=EQUIV_TEST -max_len=4096 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: equivalence-mismatch. Sizes: {{.*}}; offset 2 +CHECK: SUMMARY: libFuzzer: equivalence-mismatch +RUN: kill -9 $APID diff --git a/test/fuzzer/exit-report.test b/test/fuzzer/exit-report.test new file mode 100644 index 000000000..f754c1376 --- /dev/null +++ b/test/fuzzer/exit-report.test @@ -0,0 +1,6 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest +RUN: not %t-SimpleTest 2>&1 | FileCheck %s + +CHECK: ERROR: libFuzzer: fuzz target exited +CHECK: SUMMARY: libFuzzer: fuzz target exited +CHECK: Test unit written to diff --git a/test/fuzzer/exit_on_src_pos.test b/test/fuzzer/exit_on_src_pos.test new file mode 100644 index 000000000..6a42c7ae9 --- /dev/null +++ b/test/fuzzer/exit_on_src_pos.test @@ -0,0 +1,8 @@ +# Temporary use -mllvm -use-unknown-locations=Disable so that +# all instructions have debug info (file line numbers) attached. +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -mllvm -use-unknown-locations=Disable +RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest + +RUN: %t-SimpleTest -exit_on_src_pos=SimpleTest.cpp:18 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +RUN: %t-ShrinkControlFlowTest -exit_on_src_pos=Foo 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting. diff --git a/test/fuzzer/extra-counters.test b/test/fuzzer/extra-counters.test new file mode 100644 index 000000000..230f74a1b --- /dev/null +++ b/test/fuzzer/extra-counters.test @@ -0,0 +1,7 @@ +REQUIRES: linux + +RUN: %cpp_compiler %S/TableLookupTest.cpp -o %t-TableLookupTest +RUN: not %t-TableLookupTest -print_final_stats=1 2>&1 | FileCheck %s +CHECK: BINGO +// Expecting >= 4096 new_units_added +CHECK: stat::new_units_added:{{.*[4][0-9][0-9][0-9]}} diff --git a/test/fuzzer/fuzzer-customcrossover.test b/test/fuzzer/fuzzer-customcrossover.test new file mode 100644 index 000000000..8f74cd98f --- /dev/null +++ b/test/fuzzer/fuzzer-customcrossover.test @@ -0,0 +1,12 @@ +RUN: %cpp_compiler %S/CustomCrossOverTest.cpp -o %t-CustomCrossOverTest + +RUN: rm -rf %t/CustomCrossover +RUN: mkdir -p %t/CustomCrossover +RUN: echo "0123456789" > %t/CustomCrossover/digits +RUN: echo "abcdefghij" > %t/CustomCrossover/chars +RUN: not %t-CustomCrossOverTest -seed=1 -runs=100000 %t/CustomCrossover 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomCrossover +RUN: rm -rf %t/CustomCrossover + +LLVMFuzzerCustomCrossover: In LLVMFuzzerCustomCrossover +LLVMFuzzerCustomCrossover: BINGO + diff --git a/test/fuzzer/fuzzer-customcrossoverandmutate.test b/test/fuzzer/fuzzer-customcrossoverandmutate.test new file mode 100644 index 000000000..4a7dfba2a --- /dev/null +++ b/test/fuzzer/fuzzer-customcrossoverandmutate.test @@ -0,0 +1,2 @@ +RUN: %cpp_compiler %S/CustomCrossOverAndMutateTest.cpp -o %t-CustomCrossOverAndMutateTest +RUN: %t-CustomCrossOverAndMutateTest -seed=1 -runs=100000 diff --git a/test/fuzzer/fuzzer-custommutator.test b/test/fuzzer/fuzzer-custommutator.test new file mode 100644 index 000000000..7a693cd47 --- /dev/null +++ b/test/fuzzer/fuzzer-custommutator.test @@ -0,0 +1,5 @@ +RUN: %cpp_compiler %S/CustomMutatorTest.cpp -o %t-CustomMutatorTest +RUN: not %t-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: BINGO + diff --git a/test/fuzzer/fuzzer-dict.test b/test/fuzzer/fuzzer-dict.test new file mode 100644 index 000000000..48c91dc1d --- /dev/null +++ b/test/fuzzer/fuzzer-dict.test @@ -0,0 +1,8 @@ +RUN: %cpp_compiler %S/SimpleDictionaryTest.cpp -o %t-SimpleDictionaryTest + +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: not %t-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s +RUN: %t-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + diff --git a/test/fuzzer/fuzzer-dirs.test b/test/fuzzer/fuzzer-dirs.test new file mode 100644 index 000000000..ef0888f3b --- /dev/null +++ b/test/fuzzer/fuzzer-dirs.test @@ -0,0 +1,21 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest + +RUN: rm -rf %t/SUB1 +RUN: mkdir -p %t/SUB1/SUB2/SUB3 +RUN: echo a > %t/SUB1/a +RUN: echo b > %t/SUB1/SUB2/b +RUN: echo c > %t/SUB1/SUB2/SUB3/c +RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS +SUBDIRS: READ units: 3 +RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/f64 +RUN: cat %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 > %t/SUB1/f256 +RUN: cat %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 > %t/SUB1/f1024 +RUN: cat %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 > %t/SUB1/f4096 +RUN: cat %t/SUB1/f4096 %t/SUB1/f4096 > %t/SUB1/f8192 +RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG +LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes +RUN: rm -rf %t/SUB1 + +RUN: not %t-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR +NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting + diff --git a/test/fuzzer/fuzzer-fdmask.test b/test/fuzzer/fuzzer-fdmask.test new file mode 100644 index 000000000..3f04993b5 --- /dev/null +++ b/test/fuzzer/fuzzer-fdmask.test @@ -0,0 +1,32 @@ +RUN: %cpp_compiler %S/SpamyTest.cpp -o %t-SpamyTest + +RUN: %t-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: %t-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: %t-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1 +RUN: %t-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2 +RUN: %t-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3 + +FD_MASK_0: PRINTF_STDOUT +FD_MASK_0: PRINTF_STDERR +FD_MASK_0: STREAM_COUT +FD_MASK_0: STREAM_CERR +FD_MASK_0: INITED + +FD_MASK_1-NOT: PRINTF_STDOUT +FD_MASK_1: PRINTF_STDERR +FD_MASK_1-NOT: STREAM_COUT +FD_MASK_1: STREAM_CERR +FD_MASK_1: INITED + +FD_MASK_2: PRINTF_STDOUT +FD_MASK_2-NOT: PRINTF_STDERR +FD_MASK_2: STREAM_COUT +FD_MASK_2-NOTE: STREAM_CERR +FD_MASK_2: INITED + +FD_MASK_3-NOT: PRINTF_STDOUT +FD_MASK_3-NOT: PRINTF_STDERR +FD_MASK_3-NOT: STREAM_COUT +FD_MASK_3-NOT: STREAM_CERR +FD_MASK_3: INITED + diff --git a/test/fuzzer/fuzzer-finalstats.test b/test/fuzzer/fuzzer-finalstats.test new file mode 100644 index 000000000..4f983bea8 --- /dev/null +++ b/test/fuzzer/fuzzer-finalstats.test @@ -0,0 +1,12 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest +RUN: %t-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS +FINAL_STATS: stat::number_of_executed_units: 77 +FINAL_STATS: stat::average_exec_per_sec: 0 +FINAL_STATS: stat::new_units_added: +FINAL_STATS: stat::slowest_unit_time_sec: 0 +FINAL_STATS: stat::peak_rss_mb: + +RUN: %t-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1 +FINAL_STATS1: stat::number_of_executed_units: 33 +FINAL_STATS1: stat::peak_rss_mb: + diff --git a/test/fuzzer/fuzzer-flags.test b/test/fuzzer/fuzzer-flags.test new file mode 100644 index 000000000..2f9a31063 --- /dev/null +++ b/test/fuzzer/fuzzer-flags.test @@ -0,0 +1,19 @@ +RUN: %cpp_compiler %S/FlagsTest.cpp -o %t-FlagsTest +RUN: not %t-FlagsTest -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR +FOO_BAR: WARNING: unrecognized flag '-foo_bar=1'; use -help=1 to list all flags +FOO_BAR: BINGO + +RUN: not %t-FlagsTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH +DASH_DASH: WARNING: did you mean '-max_len=100' (single dash)? +DASH_DASH: INFO: A corpus is not provided, starting from an empty corpus + +RUN: %t-FlagsTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL +NO_INTERNAL-NOT: internal flag + +RUN: not %t-FlagsTest --foo-bar -runs=10 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU +PASSTHRU: BINGO --foo-bar --baz -help=1 test + +RUN: mkdir -p %t/T0 %t/T1 +RUN: touch %t/T1/empty +RUN: not %t-FlagsTest --foo-bar -merge=1 %t/T0 %t/T1 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU-MERGE +PASSTHRU-MERGE: BINGO --foo-bar --baz -help=1 test diff --git a/test/fuzzer/fuzzer-leak.test b/test/fuzzer/fuzzer-leak.test new file mode 100644 index 000000000..f8e99ce3f --- /dev/null +++ b/test/fuzzer/fuzzer-leak.test @@ -0,0 +1,37 @@ +REQUIRES: lsan +RUN: %cpp_compiler %S/LeakTest.cpp -o %t-LeakTest +RUN: %cpp_compiler %S/ThreadedLeakTest.cpp -o %t-ThreadedLeakTest +RUN: %cpp_compiler %S/LeakTimeoutTest.cpp -o %t-LeakTimeoutTest + +RUN: not %t-LeakTest -runs=100000 -detect_leaks=1 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks +LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from: +LEAK_DURING: INFO: to ignore leaks on libFuzzer side use -detect_leaks=0 +LEAK_DURING: Test unit written to ./leak- +LEAK_DURING-NOT: DONE +LEAK_DURING-NOT: Done + +RUN: not %t-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS +LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks +LEAK_IN_CORPUS: INFO: a leak has been found in the initial corpus. + +RUN: not %t-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK +MULTI_RUN_LEAK-NOT: pulse +MULTI_RUN_LEAK: LeakSanitizer: detected memory leaks + +RUN: not %t-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not %t-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not %t-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not %t-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +LEAK_AFTER: Done 100000 runs in +LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks + +RUN: not %t-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1 +MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829 + +RUN: not %t-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT +LEAK_TIMEOUT: ERROR: libFuzzer: timeout after +LEAK_TIMEOUT-NOT: LeakSanitizer + + +RUN: %t-LeakTest -error_exitcode=0 diff --git a/test/fuzzer/fuzzer-oom-with-profile.test b/test/fuzzer/fuzzer-oom-with-profile.test new file mode 100644 index 000000000..75cf48430 --- /dev/null +++ b/test/fuzzer/fuzzer-oom-with-profile.test @@ -0,0 +1,7 @@ +REQUIRES: linux +RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest +RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) +CHECK: Live Heap Allocations +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory diff --git a/test/fuzzer/fuzzer-oom.test b/test/fuzzer/fuzzer-oom.test new file mode 100644 index 000000000..9ef7c485d --- /dev/null +++ b/test/fuzzer/fuzzer-oom.test @@ -0,0 +1,20 @@ +RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest +RUN: %cpp_compiler %S/OutOfMemorySingleLargeMallocTest.cpp -o %t-OutOfMemorySingleLargeMallocTest +RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest + +RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s + +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory + +RUN: not %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC + +We used to check for "out-of-memory (malloc(53{{.*}}))", but that would fail +sometimes, so now we accept any OOM message. + +SINGLE_LARGE_MALLOC: libFuzzer: out-of-memory +SINGLE_LARGE_MALLOC: in LLVMFuzzerTestOneInput + +# Check that -rss_limit_mb=0 means no limit. +RUN: %t-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0 diff --git a/test/fuzzer/fuzzer-printcovpcs.test b/test/fuzzer/fuzzer-printcovpcs.test new file mode 100644 index 000000000..e55ce14aa --- /dev/null +++ b/test/fuzzer/fuzzer-printcovpcs.test @@ -0,0 +1,9 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest +RUN: not %t-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS +PCS-NOT: NEW_PC +PCS:INITED +PCS:NEW_PC: {{0x[a-f0-9]+}} +PCS:NEW_PC: {{0x[a-f0-9]+}} +PCS:NEW +PCS:BINGO + diff --git a/test/fuzzer/fuzzer-runs.test b/test/fuzzer/fuzzer-runs.test new file mode 100644 index 000000000..04987eee5 --- /dev/null +++ b/test/fuzzer/fuzzer-runs.test @@ -0,0 +1,9 @@ +RUN: mkdir -p %t +RUN: %cpp_compiler %S/NthRunCrashTest.cpp -o %t-NthRunCrashTest +RUN: echo abcd > %t/NthRunCrashTest.in +RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in +RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 +RUN: not %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s +RUN: rm %t/NthRunCrashTest.in +CHECK: BINGO + diff --git a/test/fuzzer/fuzzer-seed.test b/test/fuzzer/fuzzer-seed.test new file mode 100644 index 000000000..a69ea5432 --- /dev/null +++ b/test/fuzzer/fuzzer-seed.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-SimpleCmpTest +RUN: %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE +CHECK_SEED_MINUS_ONE: Seed: 4294967295 + diff --git a/test/fuzzer/fuzzer-segv.test b/test/fuzzer/fuzzer-segv.test new file mode 100644 index 000000000..4d3c7575f --- /dev/null +++ b/test/fuzzer/fuzzer-segv.test @@ -0,0 +1,8 @@ +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: env ASAN_OPTIONS=handle_segv=0 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER +LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal +LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal +LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash- + +RUN: env ASAN_OPTIONS=handle_segv=1 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_ASAN_SEGV_HANDLER +LIBFUZZER_ASAN_SEGV_HANDLER: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address diff --git a/test/fuzzer/fuzzer-singleinputs.test b/test/fuzzer/fuzzer-singleinputs.test new file mode 100644 index 000000000..468da5622 --- /dev/null +++ b/test/fuzzer/fuzzer-singleinputs.test @@ -0,0 +1,19 @@ +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest + +RUN: not %t-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput +SingleInput-NOT: Test unit written to ./crash- + +RUN: rm -rf %tmp/SINGLE_INPUTS +RUN: mkdir -p %tmp/SINGLE_INPUTS +RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa +RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb +RUN: %t-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: %t-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: rm -rf %tmp/SINGLE_INPUTS +SINGLE_INPUTS: SimpleTest{{.*}}: Running 2 inputs 1 time(s) each. +SINGLE_INPUTS: aaa in +SINGLE_INPUTS: bbb in +SINGLE_INPUTS: NOTE: fuzzing was not performed, you have only +SINGLE_INPUTS: executed the target code on a fixed set of inputs. + diff --git a/test/fuzzer/fuzzer-threaded.test b/test/fuzzer/fuzzer-threaded.test new file mode 100644 index 000000000..572ed5a35 --- /dev/null +++ b/test/fuzzer/fuzzer-threaded.test @@ -0,0 +1,8 @@ +CHECK: Done 1000 runs in +RUN: %cpp_compiler %S/ThreadedTest.cpp -o %t-ThreadedTest + +RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s + diff --git a/test/fuzzer/fuzzer-timeout.test b/test/fuzzer/fuzzer-timeout.test new file mode 100644 index 000000000..41f4ba364 --- /dev/null +++ b/test/fuzzer/fuzzer-timeout.test @@ -0,0 +1,21 @@ +RUN: %cpp_compiler %S/TimeoutTest.cpp -o %t-TimeoutTest +RUN: %cpp_compiler %S/TimeoutEmptyTest.cpp -o %t-TimeoutEmptyTest +RUN: not %t-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest +TimeoutTest: ALARM: working on the last Unit for +TimeoutTest: Test unit written to ./timeout- +TimeoutTest: == ERROR: libFuzzer: timeout after +TimeoutTest: #0 +TimeoutTest: #1 +TimeoutTest: #2 +TimeoutTest: SUMMARY: libFuzzer: timeout + +RUN: not %t-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest +SingleInputTimeoutTest: ALARM: working on the last Unit for {{[1-3]}} seconds +SingleInputTimeoutTest-NOT: Test unit written to ./timeout- + +RUN: %t-TimeoutTest -timeout=1 -timeout_exitcode=0 + +RUN: not %t-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest +TimeoutEmptyTest: ALARM: working on the last Unit for +TimeoutEmptyTest: == ERROR: libFuzzer: timeout after +TimeoutEmptyTest: SUMMARY: libFuzzer: timeout diff --git a/test/fuzzer/fuzzer-ubsan.test b/test/fuzzer/fuzzer-ubsan.test new file mode 100644 index 000000000..49c190cd0 --- /dev/null +++ b/test/fuzzer/fuzzer-ubsan.test @@ -0,0 +1,5 @@ +RUN: %cpp_compiler -fsanitize=undefined -fno-sanitize-recover=all %S/SignedIntOverflowTest.cpp -o %t-SignedIntOverflowTest-Ubsan +RUN: not %t-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s +CHECK: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' +CHECK: Test unit written to ./crash- + diff --git a/test/fuzzer/fuzzer.test b/test/fuzzer/fuzzer.test new file mode 100644 index 000000000..e506fcbee --- /dev/null +++ b/test/fuzzer/fuzzer.test @@ -0,0 +1,70 @@ +CHECK: BINGO +Done1000000: Done 1000000 runs in +RUN: %cpp_compiler %S/BogusInitializeTest.cpp -o %t-BogusInitializeTest +RUN: %cpp_compiler %S/BufferOverflowOnInput.cpp -o %t-BufferOverflowOnInput +RUN: %cpp_compiler %S/CounterTest.cpp -o %t-CounterTest +RUN: %cpp_compiler %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so +RUN: %cpp_compiler %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so +RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest +RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest +RUN: %cpp_compiler %S/InitializeTest.cpp -o %t-InitializeTest +RUN: %cpp_compiler %S/NotinstrumentedTest.cpp -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -o %t-NotinstrumentedTest-NoCoverage +RUN: %cpp_compiler %S/NullDerefOnEmptyTest.cpp -o %t-NullDerefOnEmptyTest +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest +RUN: %cpp_compiler %S/StrncmpOOBTest.cpp -o %t-StrncmpOOBTest + +RUN: not %t-SimpleTest 2>&1 | FileCheck %s + +# only_ascii mode. Will perform some minimal self-validation. +RUN: not %t-SimpleTest -only_ascii=1 2>&1 + +RUN: %t-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime +MaxTotalTime: Done {{.*}} runs in {{.}} second(s) + +RUN: not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest +RUN: not %t-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest +NullDerefTest: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address +NullDerefTest: Test unit written to ./crash- +RUN: not %t-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix +NullDerefTestPrefix: Test unit written to ZZZcrash- +RUN: not %t-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath +NullDerefTestExactPath: Test unit written to FOOBAR + +RUN: not %t-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY +NULL_DEREF_ON_EMPTY: stat::number_of_executed_units: + +#not %t-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s + +RUN: not %t-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS + +COUNTERS: INITED {{.*}} {{bits:|ft:}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: BINGO + +# Don't run UninstrumentedTest for now since we build libFuzzer itself with asan. +DISABLED: not %t-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED +UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting. + +RUN: not %t-NotinstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE +NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting + +RUN: not %t-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB +OOB: AddressSanitizer: heap-buffer-overflow +OOB: is located 0 bytes to the right of 3-byte region + +RUN: not %t-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s + +RUN: not %t-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO +DSO: INFO: Loaded 3 modules +DSO: BINGO + +RUN: env ASAN_OPTIONS=strict_string_checks=1 not %t-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP +STRNCMP: AddressSanitizer: heap-buffer-overflow +STRNCMP-NOT: __sanitizer_weak_hook_strncmp +STRNCMP: in LLVMFuzzerTestOneInput + +RUN: not %t-BogusInitializeTest 2>&1 | FileCheck %s --check-prefix=BOGUS_INITIALIZE +BOGUS_INITIALIZE: argv[0] has been modified in LLVMFuzzerInitialize diff --git a/test/fuzzer/hi.txt b/test/fuzzer/hi.txt new file mode 100644 index 000000000..2f9031f0e --- /dev/null +++ b/test/fuzzer/hi.txt @@ -0,0 +1 @@ +Hi!
\ No newline at end of file diff --git a/test/fuzzer/inline-8bit-counters.test b/test/fuzzer/inline-8bit-counters.test new file mode 100644 index 000000000..5723c70b1 --- /dev/null +++ b/test/fuzzer/inline-8bit-counters.test @@ -0,0 +1,5 @@ +REQUIRES: linux +RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=trace-pc-guard -fsanitize-coverage=inline-8bit-counters -o %t-SimpleTest-Inline8bitCounters +CHECK: INFO: Loaded 1 modules ({{.*}} inline 8-bit counters) +CHECK: BINGO +RUN: not %t-SimpleTest-Inline8bitCounters -runs=1000000 -seed=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/lit.cfg b/test/fuzzer/lit.cfg new file mode 100644 index 000000000..a82ca23b9 --- /dev/null +++ b/test/fuzzer/lit.cfg @@ -0,0 +1,80 @@ +import lit.formats +import sys +import os + +config.name = "LLVMFuzzer" +config.test_format = lit.formats.ShTest(True) +config.suffixes = ['.test'] +config.test_source_root = os.path.dirname(__file__) + +# Choose between lit's internal shell pipeline runner and a real shell. If +# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. +use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") +if use_lit_shell: + # 0 is external, "" is default, and everything else is internal. + execute_external = (use_lit_shell == "0") +else: + # Otherwise we default to internal on Windows and external elsewhere, as + # bash on Windows is usually very slow. + execute_external = (not sys.platform in ['win32']) + +# testFormat: The test format to use to interpret tests. +# +# For now we require '&&' between commands, until they get globally killed and +# the test runner updated. +config.test_format = lit.formats.ShTest(execute_external) + +# LeakSanitizer is not supported on OSX right now. +if sys.platform.startswith('darwin'): + lit_config.note('lsan feature unavailable') +else: + lit_config.note('lsan feature available') + config.available_features.add('lsan') + +if sys.platform.startswith('win') or sys.platform.startswith('cygwin'): + config.available_features.add('windows') + +if sys.platform.startswith('darwin'): + config.available_features.add('darwin') + +if sys.platform.startswith('linux'): + # Note the value of ``sys.platform`` is not consistent + # between python 2 and 3, hence the use of ``.startswith()``. + lit_config.note('linux feature available') + config.available_features.add('linux') +else: + lit_config.note('linux feature unavailable') + +config.substitutions.append(('%build_dir', config.cmake_binary_dir)) +libfuzzer_src_root = os.path.join(config.compiler_rt_src_root, "lib", "fuzzer") +config.substitutions.append(('%libfuzzer_src', libfuzzer_src_root)) + +def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True): + compiler_cmd = config.c_compiler + link_cmd = '-lc++' if 'darwin' in config.target_triple else '-lstdc++' + std_cmd = '-std=c++11' if is_cpp else '' + sanitizers = ['address'] + if fuzzer_enabled: + sanitizers.append('fuzzer') + sanitizers_cmd = ('-fsanitize=%s' % ','.join(sanitizers)) + isysroot_cmd = ('-isysroot %s' % config.osx_sysroot + ) if 'darwin' in config.target_triple else '' + include_cmd = '-I%s' % libfuzzer_src_root + return '%s %s %s -gline-tables-only %s %s %s' % ( + compiler_cmd, std_cmd, link_cmd, isysroot_cmd, sanitizers_cmd, include_cmd) + +config.substitutions.append(('%cpp_compiler', + generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True) + )) + +config.substitutions.append(('%c_compiler', + generate_compiler_cmd(is_cpp=False, fuzzer_enabled=True) + )) + +config.substitutions.append(('%no_fuzzer_cpp_compiler', + generate_compiler_cmd(is_cpp=True, fuzzer_enabled=False) + )) + +config.substitutions.append(('%no_fuzzer_c_compiler', + generate_compiler_cmd(is_cpp=False, fuzzer_enabled=False) + )) diff --git a/test/fuzzer/lit.site.cfg.in b/test/fuzzer/lit.site.cfg.in new file mode 100644 index 000000000..3f1957511 --- /dev/null +++ b/test/fuzzer/lit.site.cfg.in @@ -0,0 +1,17 @@ +@LIT_SITE_CFG_IN_HEADER@ + +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" + +config.cpp_compiler = "@LIBFUZZER_TEST_COMPILER@" +config.target_flags = "@LIBFUZZER_TEST_FLAGS@" +config.c_compiler = "@LIBFUZZER_TEST_COMPILER@" + +config.osx_sysroot = "@CMAKE_OSX_SYSROOT@" +config.cmake_binary_dir = "@CMAKE_BINARY_DIR@" +config.target_triple = "@TARGET_TRIPLE@" + +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, + "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/fuzzer/memcmp.test b/test/fuzzer/memcmp.test new file mode 100644 index 000000000..3431a524c --- /dev/null +++ b/test/fuzzer/memcmp.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/MemcmpTest.cpp -o %t-MemcmpTest +RUN: not %t-MemcmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s +CHECK: BINGO diff --git a/test/fuzzer/memcmp64.test b/test/fuzzer/memcmp64.test new file mode 100644 index 000000000..223c3bd42 --- /dev/null +++ b/test/fuzzer/memcmp64.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/Memcmp64BytesTest.cpp -o %t-Memcmp64BytesTest +RUN: not %t-Memcmp64BytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s +CHECK: BINGO diff --git a/test/fuzzer/merge-posix.test b/test/fuzzer/merge-posix.test new file mode 100644 index 000000000..e34e3a325 --- /dev/null +++ b/test/fuzzer/merge-posix.test @@ -0,0 +1,23 @@ +RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest + +RUN: rm -rf %tmp/T1 %tmp/T2 +RUN: mkdir -p %tmp/T1 %tmp/T2 + +RUN: echo F..... > %tmp/T1/1 +RUN: echo .U.... > %tmp/T1/2 +RUN: echo ..Z... > %tmp/T1/3 + +RUN: echo .....F > %tmp/T2/1 +RUN: echo ....U. > %tmp/T2/2 +RUN: echo ...Z.. > %tmp/T2/3 +RUN: echo ...Z.. > %tmp/T2/4 +RUN: echo ....E. > %tmp/T2/5 +RUN: echo .....R > %tmp/T2/6 + +# Check that we can report an error if file size exceeded +RUN: (ulimit -f 1; not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=SIGXFSZ) +SIGXFSZ: ERROR: libFuzzer: file size exceeded + +# Check that we honor TMPDIR +RUN: TMPDIR=DIR_DOES_NOT_EXIST not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=TMPDIR +TMPDIR: MERGE-OUTER: failed to write to the control file: DIR_DOES_NOT_EXIST/libFuzzerTemp diff --git a/test/fuzzer/merge-summary.test b/test/fuzzer/merge-summary.test new file mode 100644 index 000000000..3e21c23ef --- /dev/null +++ b/test/fuzzer/merge-summary.test @@ -0,0 +1,17 @@ +RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest + +RUN: rm -rf %t/T1 %t/T2 +RUN: mkdir -p %t/T0 %t/T1 %t/T2 +RUN: echo ...Z.. > %t/T2/1 +RUN: echo ....E. > %t/T2/2 +RUN: echo .....R > %t/T2/3 +RUN: echo F..... > %t/T2/a +RUN: echo .U.... > %t/T2/b +RUN: echo ..Z... > %t/T2/c + +RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY +SAVE_SUMMARY: MERGE-OUTER: writing coverage summary for 6 files to {{.*}}SUMMARY +RUN: rm %t/T1/* +RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY +LOAD_SUMMARY: MERGE-OUTER: coverage summary loaded from {{.*}}SUMMAR +LOAD_SUMMARY: MERGE-OUTER: 0 new files with 0 new features added diff --git a/test/fuzzer/merge.test b/test/fuzzer/merge.test new file mode 100644 index 000000000..30e27b8d2 --- /dev/null +++ b/test/fuzzer/merge.test @@ -0,0 +1,55 @@ +CHECK: BINGO + +RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest + +RUN: rm -rf %tmp/T0 %tmp/T1 %tmp/T2 +RUN: mkdir -p %tmp/T0 %tmp/T1 %tmp/T2 +RUN: echo F..... > %tmp/T0/1 +RUN: echo .U.... > %tmp/T0/2 +RUN: echo ..Z... > %tmp/T0/3 + +# T1 has 3 elements, T2 is empty. +RUN: cp %tmp/T0/* %tmp/T1/ +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK1 +CHECK1: MERGE-OUTER: 3 files, 3 in the initial corpus +CHECK1: MERGE-OUTER: 0 new files with 0 new features added + +RUN: echo ...Z.. > %tmp/T2/1 +RUN: echo ....E. > %tmp/T2/2 +RUN: echo .....R > %tmp/T2/3 +RUN: echo F..... > %tmp/T2/a +RUN: echo .U.... > %tmp/T2/b +RUN: echo ..Z... > %tmp/T2/c + +# T1 has 3 elements, T2 has 6 elements, only 3 are new. +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK2 +CHECK2: MERGE-OUTER: 9 files, 3 in the initial corpus +CHECK2: MERGE-OUTER: 3 new files with 3 new features added + +# Now, T1 has 6 units and T2 has no new interesting units. +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK3 +CHECK3: MERGE-OUTER: 12 files, 6 in the initial corpus +CHECK3: MERGE-OUTER: 0 new files with 0 new features added + +# Check that we respect max_len during the merge and don't crash. +RUN: rm %tmp/T1/* +RUN: cp %tmp/T0/* %tmp/T1/ +RUN: echo looooooooong > %tmp/T2/looooooooong +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN +MAX_LEN: MERGE-OUTER: 3 new files + +# Check that merge tolerates failures. +RUN: rm %tmp/T1/* +RUN: cp %tmp/T0/* %tmp/T1/ +RUN: echo 'FUZZER' > %tmp/T2/FUZZER +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH +MERGE_WITH_CRASH: MERGE-OUTER: succesfull in 2 attempt(s) +MERGE_WITH_CRASH: MERGE-OUTER: 3 new files + +# Check that we actually limit the size with max_len +RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5 +MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s) + +RUN: rm -rf %tmp/T1/* %tmp/T2/* +RUN: not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=EMPTY +EMPTY: MERGE-OUTER: zero succesfull attempts, exiting diff --git a/test/fuzzer/minimize_crash.test b/test/fuzzer/minimize_crash.test new file mode 100644 index 000000000..77ab370fa --- /dev/null +++ b/test/fuzzer/minimize_crash.test @@ -0,0 +1,16 @@ +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: %cpp_compiler %S/SingleByteInputTest.cpp -o %t-SingleByteInputTest + +RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash +RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s +CHECK: CRASH_MIN: failed to minimize beyond ./minimized-from-{{.*}} (3 bytes), exiting +RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT +CHECK_EXACT: CRASH_MIN: failed to minimize beyond exact_minimized_path (3 bytes), exiting +RUN: rm not_minimal_crash minimized-from-* exact_minimized_path + +RUN: echo -n 'abcd*xyz' > not_minimal_crash +RUN: %t-SingleByteInputTest -minimize_crash=1 not_minimal_crash -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=MIN1 +MIN1: Test unit written to exact_minimized_path +MIN1: Test unit written to exact_minimized_path +MIN1: INFO: The input is small enough, exiting +MIN1: CRASH_MIN: failed to minimize beyond exact_minimized_path (1 bytes), exiting diff --git a/test/fuzzer/minimize_two_crashes.test b/test/fuzzer/minimize_two_crashes.test new file mode 100644 index 000000000..e6ff9990f --- /dev/null +++ b/test/fuzzer/minimize_two_crashes.test @@ -0,0 +1,18 @@ +# Test that the minimizer stops when it sees a differe bug. + +RUN: %cpp_compiler %S/TwoDifferentBugsTest.cpp -o %t-TwoDifferentBugsTest + +RUN: rm -rf %t && mkdir %t +RUN: echo H12345678901234667888090 > %t/long_crash +RUN: env ASAN_OPTIONS=dedup_token_length=3 %t-TwoDifferentBugsTest -seed=1 -minimize_crash=1 %t/long_crash -exact_artifact_path=%t/result 2>&1 | FileCheck %s + +CHECK: DedupToken1: DEDUP_TOKEN: Bar +CHECK: DedupToken2: DEDUP_TOKEN: Bar +CHECK: DedupToken1: DEDUP_TOKEN: Bar +CHECK: DedupToken2: DEDUP_TOKEN: Foo +CHECK: CRASH_MIN: mismatch in dedup tokens + +RUN: not %t-TwoDifferentBugsTest %t/result 2>&1 | FileCheck %s --check-prefix=VERIFY + +VERIFY: ERROR: AddressSanitizer: +VERIFY: in Bar diff --git a/test/fuzzer/overwrite-input.test b/test/fuzzer/overwrite-input.test new file mode 100644 index 000000000..3695622d0 --- /dev/null +++ b/test/fuzzer/overwrite-input.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/OverwriteInputTest.cpp -o %t-OverwriteInputTest +RUN: not %t-OverwriteInputTest 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: fuzz target overwrites it's const input diff --git a/test/fuzzer/recommended-dictionary.test b/test/fuzzer/recommended-dictionary.test new file mode 100644 index 000000000..41b62c924 --- /dev/null +++ b/test/fuzzer/recommended-dictionary.test @@ -0,0 +1,6 @@ +RUN: %cpp_compiler %S/RepeatedMemcmp.cpp -o %t-RepeatedMemcmp +RUN: %t-RepeatedMemcmp -seed=11 -runs=100000 -max_len=20 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT +RECOMMENDED_DICT:###### Recommended dictionary. ###### +RECOMMENDED_DICT-DAG: "foo" +RECOMMENDED_DICT-DAG: "bar" +RECOMMENDED_DICT:###### End of recommended dictionary. ###### diff --git a/test/fuzzer/reduce_inputs.test b/test/fuzzer/reduce_inputs.test new file mode 100644 index 000000000..02e090ebd --- /dev/null +++ b/test/fuzzer/reduce_inputs.test @@ -0,0 +1,16 @@ +# Test -reduce_inputs=1 + +RUN: rm -rf %t/C +RUN: mkdir -p %t/C +RUN: %cpp_compiler %S/ShrinkControlFlowSimpleTest.cpp -o %t-ShrinkControlFlowSimpleTest +RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest +RUN: %t-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 %t/C 2>&1 | FileCheck %s +CHECK: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60' + +# Test that reduce_inputs deletes redundant files in the corpus. +RUN: %t-ShrinkControlFlowSimpleTest -runs=0 %t/C 2>&1 | FileCheck %s --check-prefix=COUNT +COUNT: READ units: 4 + +# a bit longer test +RUN: %t-ShrinkControlFlowTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -seed=1 -runs=1000000 2>&1 | FileCheck %s + diff --git a/test/fuzzer/repeated-bytes.test b/test/fuzzer/repeated-bytes.test new file mode 100644 index 000000000..0bba2a916 --- /dev/null +++ b/test/fuzzer/repeated-bytes.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/RepeatedBytesTest.cpp -o %t-RepeatedBytesTest +CHECK: BINGO +RUN: not %t-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/shrink.test b/test/fuzzer/shrink.test new file mode 100644 index 000000000..2988d4bbb --- /dev/null +++ b/test/fuzzer/shrink.test @@ -0,0 +1,10 @@ +RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest +RUN: %cpp_compiler %S/ShrinkValueProfileTest.cpp -o %t-ShrinkValueProfileTest +RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 -reduce_inputs=0 2>&1 | FileCheck %s --check-prefix=SHRINK1 +# Limit max_len to run this negative test faster. +RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 -reduce_inputs=0 -max_len=64 2>&1 | FileCheck %s --check-prefix=SHRINK0 +RUN: %t-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -reduce_inputs=0 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP + +SHRINK0: Done 1000000 runs in +SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting. +SHRINK1_VP: INFO: found item with checksum 'aea2e3923af219a8956f626558ef32f30a914ebc', exiting diff --git a/test/fuzzer/simple-cmp.test b/test/fuzzer/simple-cmp.test new file mode 100644 index 000000000..08123ed3a --- /dev/null +++ b/test/fuzzer/simple-cmp.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest +CHECK: BINGO +RUN: not %t-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/standalone.test b/test/fuzzer/standalone.test new file mode 100644 index 000000000..e6483703f --- /dev/null +++ b/test/fuzzer/standalone.test @@ -0,0 +1,8 @@ +RUN: %no_fuzzer_c_compiler %libfuzzer_src/standalone/StandaloneFuzzTargetMain.c -c -o %t_1.o +RUN: %no_fuzzer_cpp_compiler %S/InitializeTest.cpp -c -o %t_2.o + +RUN: %no_fuzzer_cpp_compiler %t_1.o %t_2.o -o %t-StandaloneInitializeTest +RUN: %t-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s +CHECK: StandaloneFuzzTargetMain: running 2 inputs +CHECK: Done: {{.*}}hi.txt: (3 bytes) +CHECK: Done: {{.*}}dict1.txt: (61 bytes) diff --git a/test/fuzzer/strcmp.test b/test/fuzzer/strcmp.test new file mode 100644 index 000000000..47ad8f9ba --- /dev/null +++ b/test/fuzzer/strcmp.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/StrcmpTest.cpp -o %t-StrcmpTest +RUN: not %t-StrcmpTest -seed=1 -runs=2000000 2>&1 | FileCheck %s +CHECK: BINGO + diff --git a/test/fuzzer/strncmp.test b/test/fuzzer/strncmp.test new file mode 100644 index 000000000..49693c8de --- /dev/null +++ b/test/fuzzer/strncmp.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/StrncmpTest.cpp -o %t-StrncmpTest +RUN: not %t-StrncmpTest -seed=2 -runs=10000000 2>&1 | FileCheck %s +CHECK: BINGO + diff --git a/test/fuzzer/strstr.test b/test/fuzzer/strstr.test new file mode 100644 index 000000000..c39d5801a --- /dev/null +++ b/test/fuzzer/strstr.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/StrstrTest.cpp -o %t-StrstrTest +RUN: not %t-StrstrTest -seed=1 -runs=2000000 2>&1 | FileCheck %s +CHECK: BINGO + diff --git a/test/fuzzer/swap-cmp.test b/test/fuzzer/swap-cmp.test new file mode 100644 index 000000000..5c2379cde --- /dev/null +++ b/test/fuzzer/swap-cmp.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/SwapCmpTest.cpp -o %t-SwapCmpTest +CHECK: BINGO +RUN: not %t-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/trace-malloc-2.test b/test/fuzzer/trace-malloc-2.test new file mode 100644 index 000000000..56f16d786 --- /dev/null +++ b/test/fuzzer/trace-malloc-2.test @@ -0,0 +1,10 @@ +// FIXME: This test infinite loops on darwin because it crashes +// printing a stack trace repeatedly +UNSUPPORTED: darwin + +RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest + +RUN: %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2 +TRACE2-DAG: FREE[0] +TRACE2-DAG: MALLOC[0] +TRACE2-DAG: in LLVMFuzzerTestOneInput diff --git a/test/fuzzer/trace-malloc.test b/test/fuzzer/trace-malloc.test new file mode 100644 index 000000000..979be99b7 --- /dev/null +++ b/test/fuzzer/trace-malloc.test @@ -0,0 +1,7 @@ +RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest + +RUN: %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s +CHECK-DAG: MallocFreeTracer: STOP 0 0 (same) +CHECK-DAG: MallocFreeTracer: STOP 0 1 (DIFFERENT) +CHECK-DAG: MallocFreeTracer: STOP 1 0 (DIFFERENT) +CHECK-DAG: MallocFreeTracer: STOP 1 1 (same) diff --git a/test/fuzzer/trace-pc.test b/test/fuzzer/trace-pc.test new file mode 100644 index 000000000..eaa0cb08a --- /dev/null +++ b/test/fuzzer/trace-pc.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc -o %t-SimpleTest-TracePC +CHECK: BINGO +RUN: not %t-SimpleTest-TracePC -runs=1000000 -seed=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/ulimit.test b/test/fuzzer/ulimit.test new file mode 100644 index 000000000..8772caa2d --- /dev/null +++ b/test/fuzzer/ulimit.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest +RUN: ulimit -s 1000 +RUN: not %t-SimpleTest diff --git a/test/fuzzer/unit/lit.site.cfg.in b/test/fuzzer/unit/lit.site.cfg.in new file mode 100644 index 000000000..bab2824e4 --- /dev/null +++ b/test/fuzzer/unit/lit.site.cfg.in @@ -0,0 +1,9 @@ +@LIT_SITE_CFG_IN_HEADER@ + +config.name = "LLVMFuzzer-Unittest" +# Load common config for all compiler-rt unit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured") + +config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@", + "lib", "fuzzer", "tests") +config.test_source_root = config.test_exec_root diff --git a/test/fuzzer/value-profile-cmp.test b/test/fuzzer/value-profile-cmp.test new file mode 100644 index 000000000..64244297c --- /dev/null +++ b/test/fuzzer/value-profile-cmp.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest +RUN: not %t-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp2.test b/test/fuzzer/value-profile-cmp2.test new file mode 100644 index 000000000..43dd8f9dd --- /dev/null +++ b/test/fuzzer/value-profile-cmp2.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SimpleHashTest.cpp -o %t-SimpleHashTest +RUN: not %t-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 -max_len=64 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp3.test b/test/fuzzer/value-profile-cmp3.test new file mode 100644 index 000000000..d2284750b --- /dev/null +++ b/test/fuzzer/value-profile-cmp3.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/AbsNegAndConstantTest.cpp -o %t-AbsNegAndConstantTest +RUN: not %t-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp4.test b/test/fuzzer/value-profile-cmp4.test new file mode 100644 index 000000000..bcbc67b18 --- /dev/null +++ b/test/fuzzer/value-profile-cmp4.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/AbsNegAndConstant64Test.cpp -o %t-AbsNegAndConstant64Test +RUN: not %t-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-div.test b/test/fuzzer/value-profile-div.test new file mode 100644 index 000000000..8711a2546 --- /dev/null +++ b/test/fuzzer/value-profile-div.test @@ -0,0 +1,4 @@ +CHECK: AddressSanitizer: {{FPE|int-divide-by-zero}} +RUN: %cpp_compiler %S/DivTest.cpp -fsanitize-coverage=trace-div -o %t-DivTest +RUN: not %t-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s + diff --git a/test/fuzzer/value-profile-load.test b/test/fuzzer/value-profile-load.test new file mode 100644 index 000000000..3bf2a658a --- /dev/null +++ b/test/fuzzer/value-profile-load.test @@ -0,0 +1,3 @@ +CHECK: AddressSanitizer: global-buffer-overflow +RUN: %cpp_compiler %S/LoadTest.cpp -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-gep,trace-div,trace-cmp -o %t-LoadTest +RUN: not %t-LoadTest -seed=2 -use_cmp=0 -use_value_profile=1 -runs=20000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-mem.test b/test/fuzzer/value-profile-mem.test new file mode 100644 index 000000000..0b0c21d68 --- /dev/null +++ b/test/fuzzer/value-profile-mem.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SingleMemcmpTest.cpp -o %t-SingleMemcmpTest +RUN: not %t-SingleMemcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-set.test b/test/fuzzer/value-profile-set.test new file mode 100644 index 000000000..e2e3fb47f --- /dev/null +++ b/test/fuzzer/value-profile-set.test @@ -0,0 +1,4 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/FourIndependentBranchesTest.cpp -o %t-FourIndependentBranchesTest +RUN: not %t-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s + diff --git a/test/fuzzer/value-profile-strcmp.test b/test/fuzzer/value-profile-strcmp.test new file mode 100644 index 000000000..f5c766a65 --- /dev/null +++ b/test/fuzzer/value-profile-strcmp.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SingleStrcmpTest.cpp -o %t-SingleStrcmpTest +RUN: not %t-SingleStrcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-strncmp.test b/test/fuzzer/value-profile-strncmp.test new file mode 100644 index 000000000..2dfe43c4a --- /dev/null +++ b/test/fuzzer/value-profile-strncmp.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SingleStrncmpTest.cpp -o %t-SingleStrncmpTest +RUN: not %t-SingleStrncmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-switch.test b/test/fuzzer/value-profile-switch.test new file mode 100644 index 000000000..7edb312a0 --- /dev/null +++ b/test/fuzzer/value-profile-switch.test @@ -0,0 +1,5 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest +RUN: %cpp_compiler %S/Switch2Test.cpp -o %t-Switch2Test +RUN: not %t-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s +RUN: not %t-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s |