diff options
Diffstat (limited to 'lib/Fuzzer/test')
75 files changed, 1240 insertions, 204 deletions
diff --git a/lib/Fuzzer/test/AFLDriverTest.cpp b/lib/Fuzzer/test/AFLDriverTest.cpp new file mode 100644 index 0000000000000..3dd0b61173057 --- /dev/null +++ b/lib/Fuzzer/test/AFLDriverTest.cpp @@ -0,0 +1,22 @@ +// 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 <stdlib.h> + +extern "C" void __afl_manual_init() {} + +extern "C" int __afl_persistent_loop(unsigned int) { + 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) { + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} diff --git a/lib/Fuzzer/test/AccumulateAllocationsTest.cpp b/lib/Fuzzer/test/AccumulateAllocationsTest.cpp new file mode 100644 index 0000000000000..604d8fa299aeb --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstddef> + +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/lib/Fuzzer/test/BufferOverflowOnInput.cpp b/lib/Fuzzer/test/BufferOverflowOnInput.cpp new file mode 100644 index 0000000000000..b9d14052aee47 --- /dev/null +++ b/lib/Fuzzer/test/BufferOverflowOnInput.cpp @@ -0,0 +1,23 @@ +// 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 <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +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"; + exit(1); + } + return 0; +} + diff --git a/lib/Fuzzer/test/CMakeLists.txt b/lib/Fuzzer/test/CMakeLists.txt index cd0b167eb3887..cbc983e9e4173 100644 --- a/lib/Fuzzer/test/CMakeLists.txt +++ b/lib/Fuzzer/test/CMakeLists.txt @@ -1,115 +1,190 @@ # Build all these tests with -O0, otherwise optimizations may merge some # basic blocks and we'll fail to discover the targets. -# Also enable the coverage instrumentation back (it is disabled -# for the Fuzzer lib) -set(CMAKE_CXX_FLAGS_RELEASE "${LIBFUZZER_FLAGS_BASE} -O0 -fsanitize-coverage=edge,indirect-calls") - -set(DFSanTests - MemcmpTest - SimpleCmpTest - StrcmpTest - StrncmpTest - SwitchTest +# We change the flags for every build type because we might be doing +# a multi-configuration build (e.g. Xcode) where CMAKE_BUILD_TYPE doesn't +# mean anything. +set(variables_to_filter + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL + LIBFUZZER_FLAGS_BASE ) +foreach (VARNAME ${variables_to_filter}) + string(REPLACE " " ";" BUILD_FLAGS_AS_LIST "${${VARNAME}}") + set(new_flags "") + foreach (flag ${BUILD_FLAGS_AS_LIST}) + # NOTE: Use of XX here is to avoid a CMake warning due to CMP0054 + if (NOT ("XX${flag}" MATCHES "XX-O[0123s]")) + set(new_flags "${new_flags} ${flag}") + else() + set(new_flags "${new_flags} -O0") + endif() + endforeach() + set(${VARNAME} "${new_flags}") +endforeach() + +# Enable the coverage instrumentation (it is disabled for the Fuzzer lib). +set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fsanitize-coverage=edge,indirect-calls") + +# add_libfuzzer_test(<name> +# SOURCES source0.cpp [source1.cpp ...] +# ) +# +# Declares a LibFuzzer test executable with target name LLVMFuzzer-<name>. +# +# One or more source files to be compiled into the binary must be declared +# after the SOURCES keyword. +function(add_libfuzzer_test name) + set(multi_arg_options "SOURCES") + cmake_parse_arguments( + "add_libfuzzer_test" "" "" "${multi_arg_options}" ${ARGN}) + if ("${add_libfuzzer_test_SOURCES}" STREQUAL "") + message(FATAL_ERROR "Source files must be specified") + endif() + add_executable(LLVMFuzzer-${name} + ${add_libfuzzer_test_SOURCES} + ) + target_link_libraries(LLVMFuzzer-${name} LLVMFuzzer) + # Place binary where llvm-lit expects to find it + set_target_properties(LLVMFuzzer-${name} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/test" + ) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${name} PARENT_SCOPE) +endfunction() + +# Variable to keep track of all test targets +set(TestBinaries) + +############################################################################### +# Basic tests +############################################################################### set(Tests + AccumulateAllocationsTest + BufferOverflowOnInput CallerCalleeTest CounterTest + CustomCrossOverTest + CustomMutatorTest + EmptyTest FourIndependentBranchesTest FullCoverageSetTest + InitializeTest MemcmpTest + LeakTest + LeakTimeoutTest NullDerefTest + NullDerefOnEmptyTest + NthRunCrashTest + OneHugeAllocTest + OutOfMemoryTest + RepeatedMemcmp SimpleCmpTest SimpleDictionaryTest + SimpleFnAdapterTest SimpleHashTest SimpleTest + SimpleThreadedTest + SpamyTest StrcmpTest StrncmpTest + StrstrTest SwitchTest + ThreadedLeakTest ThreadedTest TimeoutTest ) -set(CustomMainTests - UserSuppliedFuzzerTest - ) - -set(UninstrumentedTests - UninstrumentedTest - ) - -set(TraceBBTests - SimpleTest - ) - -set(TestBinaries) +if(APPLE) + # LeakSanitizer is not supported on OSX right now + set(HAS_LSAN 0) + message(WARNING "LeakSanitizer is not supported on Apple platforms." + " Building and running LibFuzzer LeakSanitizer tests is disabled." + ) +else() + set(HAS_LSAN 1) +endif() foreach(Test ${Tests}) - add_executable(LLVMFuzzer-${Test} - ${Test}.cpp - ) - target_link_libraries(LLVMFuzzer-${Test} - LLVMFuzzer - ) - set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}) + add_libfuzzer_test(${Test} SOURCES ${Test}.cpp) endforeach() -foreach(Test ${CustomMainTests}) - add_executable(LLVMFuzzer-${Test} - ${Test}.cpp - ) - target_link_libraries(LLVMFuzzer-${Test} - LLVMFuzzerNoMain - ) - set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}) -endforeach() +############################################################################### +# AFL Driver test +############################################################################### +add_executable(AFLDriverTest + AFLDriverTest.cpp ../afl/afl_driver.cpp) -configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg - ) - -configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg - ) +set_target_properties(AFLDriverTest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/test" + ) +set(TestBinaries ${TestBinaries} AFLDriverTest) -include_directories(..) -include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) +############################################################################### +# Unit tests +############################################################################### add_executable(LLVMFuzzer-Unittest FuzzerUnittest.cpp - $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects> + FuzzerFnAdapterUnittest.cpp ) target_link_libraries(LLVMFuzzer-Unittest gtest gtest_main + LLVMFuzzerNoMain + ) + +target_include_directories(LLVMFuzzer-Unittest PRIVATE + "${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include" ) set(TestBinaries ${TestBinaries} LLVMFuzzer-Unittest) +set_target_properties(LLVMFuzzer-Unittest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}" +) +############################################################################### +# Additional tests +############################################################################### -add_subdirectory(dfsan) +include_directories(..) -foreach(Test ${DFSanTests}) - set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-DFSan) -endforeach() +if(APPLE) + message(WARNING "DataflowSanitizer is not supported on Apple platforms." + " Building and running LibFuzzer DataflowSanitizer tests is disabled." + ) + set(HAS_DFSAN 0) +else() + set(HAS_DFSAN 1) + add_subdirectory(dfsan) +endif() add_subdirectory(uninstrumented) - -foreach(Test ${UninstrumentedTests}) - set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-Uninstrumented) -endforeach() - +add_subdirectory(no-coverage) +add_subdirectory(ubsan) add_subdirectory(trace-bb) +add_subdirectory(trace-pc) -foreach(Test ${TraceBBTests}) - set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-TraceBB) -endforeach() +############################################################################### +# Configure lit to run the tests +# +# Note this is done after declaring all tests so we can inform lit if any tests +# need to be disabled. +############################################################################### -set_target_properties(${TestBinaries} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg ) add_lit_testsuite(check-fuzzer "Running Fuzzer tests" diff --git a/lib/Fuzzer/test/CallerCalleeTest.cpp b/lib/Fuzzer/test/CallerCalleeTest.cpp index 150b2fc040586..3ec025d02301d 100644 --- a/lib/Fuzzer/test/CallerCalleeTest.cpp +++ b/lib/Fuzzer/test/CallerCalleeTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> diff --git a/lib/Fuzzer/test/CounterTest.cpp b/lib/Fuzzer/test/CounterTest.cpp index b61f419c4991f..4917934c62e53 100644 --- a/lib/Fuzzer/test/CounterTest.cpp +++ b/lib/Fuzzer/test/CounterTest.cpp @@ -1,3 +1,6 @@ +// 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> diff --git a/lib/Fuzzer/test/CustomCrossOverTest.cpp b/lib/Fuzzer/test/CustomCrossOverTest.cpp new file mode 100644 index 0000000000000..2ab5781155f0c --- /dev/null +++ b/lib/Fuzzer/test/CustomCrossOverTest.cpp @@ -0,0 +1,57 @@ +// 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 <random> +#include <string.h> + +#include "FuzzerInterface.h" + +static const char *Separator = "-_^_-"; +static const char *Target = "012-_^_-abc"; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + std::string Str(reinterpret_cast<const char *>(Data), Size); + + if (Str.find(Target) != std::string::npos) { + std::cout << "BINGO; Found the target, exiting\n"; + 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/lib/Fuzzer/test/CustomMutatorTest.cpp b/lib/Fuzzer/test/CustomMutatorTest.cpp new file mode 100644 index 0000000000000..4f84519a90e64 --- /dev/null +++ b/lib/Fuzzer/test/CustomMutatorTest.cpp @@ -0,0 +1,38 @@ +// 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 <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +#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"; + 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/lib/Fuzzer/test/EmptyTest.cpp b/lib/Fuzzer/test/EmptyTest.cpp new file mode 100644 index 0000000000000..5e843308fa570 --- /dev/null +++ b/lib/Fuzzer/test/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/lib/Fuzzer/test/FourIndependentBranchesTest.cpp b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp index 6007dd4a027b4..62b3be76e3aa5 100644 --- a/lib/Fuzzer/test/FourIndependentBranchesTest.cpp +++ b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> #include <cstdlib> diff --git a/lib/Fuzzer/test/FullCoverageSetTest.cpp b/lib/Fuzzer/test/FullCoverageSetTest.cpp index a868084a0ceef..415e0b4760c50 100644 --- a/lib/Fuzzer/test/FullCoverageSetTest.cpp +++ b/lib/Fuzzer/test/FullCoverageSetTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> #include <cstdlib> diff --git a/lib/Fuzzer/test/FuzzerFnAdapterUnittest.cpp b/lib/Fuzzer/test/FuzzerFnAdapterUnittest.cpp new file mode 100644 index 0000000000000..11be18096bc3a --- /dev/null +++ b/lib/Fuzzer/test/FuzzerFnAdapterUnittest.cpp @@ -0,0 +1,110 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +#include "FuzzerFnAdapter.h" +#include "gtest/gtest-spi.h" +#include "gtest/gtest.h" + +namespace fuzzer { +namespace impl { + +template <typename... Args> +bool Unpack(std::tuple<Args...> *Tuple, std::initializer_list<uint8_t> data) { + std::vector<uint8_t> V(data); + return Unpack(V.data(), V.size(), Tuple); +} + +TEST(Unpack, Bool) { + std::tuple<bool> T; + EXPECT_TRUE(Unpack(&T, {1})); + EXPECT_TRUE(std::get<0>(T)); + + EXPECT_TRUE(Unpack(&T, {0})); + EXPECT_FALSE(std::get<0>(T)); + + EXPECT_FALSE(Unpack(&T, {})); +} + +TEST(Unpack, BoolBool) { + std::tuple<bool, bool> T; + EXPECT_TRUE(Unpack(&T, {1, 0})); + EXPECT_TRUE(std::get<0>(T)); + EXPECT_FALSE(std::get<1>(T)); + + EXPECT_TRUE(Unpack(&T, {0, 1})); + EXPECT_FALSE(std::get<0>(T)); + EXPECT_TRUE(std::get<1>(T)); + + EXPECT_FALSE(Unpack(&T, {})); + EXPECT_FALSE(Unpack(&T, {10})); +} + +TEST(Unpack, BoolInt) { + std::tuple<bool, int> T; + EXPECT_TRUE(Unpack(&T, {1, 16, 2, 0, 0})); + EXPECT_TRUE(std::get<0>(T)); + EXPECT_EQ(528, std::get<1>(T)); + + EXPECT_FALSE(Unpack(&T, {1, 2})); +} + +TEST(Unpack, Vector) { + std::tuple<std::vector<uint8_t>> T; + const auto &V = std::get<0>(T); + + EXPECT_FALSE(Unpack(&T, {})); + + EXPECT_TRUE(Unpack(&T, {0})); + EXPECT_EQ(0ul, V.size()); + + EXPECT_TRUE(Unpack(&T, {0, 1, 2, 3})); + EXPECT_EQ(0ul, V.size()); + + EXPECT_TRUE(Unpack(&T, {2})); + EXPECT_EQ(0ul, V.size()); + + EXPECT_TRUE(Unpack(&T, {2, 3})); + EXPECT_EQ(1ul, V.size()); + EXPECT_EQ(3, V[0]); + + EXPECT_TRUE(Unpack(&T, {2, 9, 8})); + EXPECT_EQ(2ul, V.size()); + EXPECT_EQ(9, V[0]); + EXPECT_EQ(8, V[1]); +} + +TEST(Unpack, String) { + std::tuple<std::string> T; + const auto &S = std::get<0>(T); + + EXPECT_TRUE(Unpack(&T, {2, 3})); + EXPECT_EQ(1ul, S.size()); + EXPECT_EQ(3, S[0]); +} + +template <typename Fn> +bool UnpackAndApply(Fn F, std::initializer_list<uint8_t> Data) { + std::vector<uint8_t> V(Data); + return UnpackAndApply(F, V.data(), V.size()); +} + +static void fnBool(bool b) { EXPECT_TRUE(b); } + +TEST(Apply, Bool) { + EXPECT_FALSE(UnpackAndApply(fnBool, {})); + EXPECT_TRUE(UnpackAndApply(fnBool, {1})); + EXPECT_NONFATAL_FAILURE(UnpackAndApply(fnBool, {0}), + "Actual: false\nExpected: true"); +} + +static void fnInt(int i) { EXPECT_EQ(42, i); } + +TEST(Apply, Int) { + EXPECT_FALSE(UnpackAndApply(fnInt, {})); + EXPECT_TRUE(UnpackAndApply(fnInt, {42, 0, 0, 0})); + EXPECT_NONFATAL_FAILURE(UnpackAndApply(fnInt, {10, 0, 0, 0}), + "Actual: 10\nExpected: 42"); +} + +} // namespace impl +} // namespace fuzzer diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp index b33e0c9614558..3fd87e5b9e017 100644 --- a/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -1,18 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Avoid ODR violations (LibFuzzer is built without ASan and this test is built +// with ASan) involving C++ standard library types when using libcxx. +#define _LIBCPP_HAS_NO_ASAN + #include "FuzzerInternal.h" #include "gtest/gtest.h" +#include <memory> #include <set> using namespace fuzzer; // For now, have LLVMFuzzerTestOneInput just to make it link. // Later we may want to make unittests that actually call LLVMFuzzerTestOneInput. -extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { abort(); } TEST(Fuzzer, CrossOver) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); Unit A({0, 1, 2}), B({5, 6, 7}); Unit C; Unit Expected[] = { @@ -79,6 +89,8 @@ typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, size_t MaxSize); void TestEraseByte(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77}; @@ -87,8 +99,8 @@ void TestEraseByte(Mutator M, int NumIter) { uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77}; uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77}; uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + Random Rand(0); + MutationDispatcher MD(Rand, {}); int FoundMask = 0; for (int i = 0; i < NumIter; i++) { uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; @@ -113,8 +125,10 @@ TEST(FuzzerMutate, EraseByte2) { } void TestInsertByte(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); int FoundMask = 0; uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; @@ -147,8 +161,10 @@ TEST(FuzzerMutate, InsertByte2) { } void TestChangeByte(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); int FoundMask = 0; uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; @@ -181,8 +197,10 @@ TEST(FuzzerMutate, ChangeByte2) { } void TestChangeBit(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); int FoundMask = 0; uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; @@ -215,8 +233,10 @@ TEST(FuzzerMutate, ChangeBit2) { } void TestShuffleBytes(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); int FoundMask = 0; uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66}; uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66}; @@ -236,19 +256,21 @@ void TestShuffleBytes(Mutator M, int NumIter) { } TEST(FuzzerMutate, ShuffleBytes1) { - TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 15); + TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 16); } TEST(FuzzerMutate, ShuffleBytes2) { - TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 19); + TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20); } void TestAddWordFromDictionary(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD}; uint8_t Word2[3] = {0xFF, 0xEE, 0xEF}; - MD.AddWordToManualDictionary(Unit(Word1, Word1 + sizeof(Word1))); - MD.AddWordToManualDictionary(Unit(Word2, Word2 + sizeof(Word2))); + MD.AddWordToManualDictionary(Word(Word1, sizeof(Word1))); + MD.AddWordToManualDictionary(Word(Word2, sizeof(Word2))); int FoundMask = 0; uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD}; uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22}; @@ -283,18 +305,20 @@ TEST(FuzzerMutate, AddWordFromDictionary2) { } void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); - uint8_t Word[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF}; + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + uint8_t W[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF}; size_t PosHint = 7777; - MD.AddWordToAutoDictionary(Unit(Word, Word + sizeof(Word)), PosHint); + MD.AddWordToAutoDictionary({Word(W, sizeof(W)), PosHint}); int FoundMask = 0; for (int i = 0; i < NumIter; i++) { uint8_t T[10000]; memset(T, 0, sizeof(T)); size_t NewSize = (MD.*M)(T, 9000, 10000); - if (NewSize >= PosHint + sizeof(Word) && - !memcmp(Word, T + PosHint, sizeof(Word))) + if (NewSize >= PosHint + sizeof(W) && + !memcmp(W, T + PosHint, sizeof(W))) FoundMask = 1; } EXPECT_EQ(FoundMask, 1); @@ -302,7 +326,7 @@ void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) { TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) { TestAddWordFromDictionaryWithHint( - &MutationDispatcher::Mutate_AddWordFromAutoDictionary, 1 << 5); + &MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, 1 << 5); } TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) { @@ -310,8 +334,10 @@ TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) { } void TestChangeASCIIInteger(Mutator M, int NumIter) { - FuzzerRandomLibc Rand(0); - MutationDispatcher MD(Rand); + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'}; uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'}; @@ -400,3 +426,24 @@ TEST(FuzzerUtil, Base64) { EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); } + +TEST(Corpus, Distribution) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + Fuzzer Fuzz(LLVMFuzzerTestOneInput, MD, {}); + size_t N = 10; + size_t TriesPerUnit = 1<<20; + for (size_t i = 0; i < N; i++) { + Fuzz.AddToCorpus(Unit{ static_cast<uint8_t>(i) }); + } + std::vector<size_t> Hist(N); + for (size_t i = 0; i < N * TriesPerUnit; i++) { + Hist[Fuzz.ChooseUnitIdxToMutate()]++; + } + for (size_t i = 0; i < N; i++) { + // A weak sanity check that every unit gets invoked. + EXPECT_GT(Hist[i], TriesPerUnit / N / 3); + } +} diff --git a/lib/Fuzzer/test/InitializeTest.cpp b/lib/Fuzzer/test/InitializeTest.cpp new file mode 100644 index 0000000000000..d40ff2f793653 --- /dev/null +++ b/lib/Fuzzer/test/InitializeTest.cpp @@ -0,0 +1,26 @@ +// 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; + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (strncmp(reinterpret_cast<const char*>(Data), argv0, Size)) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/lib/Fuzzer/test/LeakTest.cpp b/lib/Fuzzer/test/LeakTest.cpp new file mode 100644 index 0000000000000..22e5164050e51 --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstddef> + +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/lib/Fuzzer/test/LeakTimeoutTest.cpp b/lib/Fuzzer/test/LeakTimeoutTest.cpp new file mode 100644 index 0000000000000..4f31b3e52c165 --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstddef> + +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/lib/Fuzzer/test/MemcmpTest.cpp b/lib/Fuzzer/test/MemcmpTest.cpp index c19c95717bbbb..fdbf94683f765 100644 --- a/lib/Fuzzer/test/MemcmpTest.cpp +++ b/lib/Fuzzer/test/MemcmpTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstring> #include <cstdint> @@ -9,7 +12,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 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 >= 16 && memcmp(Data + 14, "KLM", 3) == 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++) { diff --git a/lib/Fuzzer/test/NthRunCrashTest.cpp b/lib/Fuzzer/test/NthRunCrashTest.cpp new file mode 100644 index 0000000000000..b43e69e51b256 --- /dev/null +++ b/lib/Fuzzer/test/NthRunCrashTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Crash on the N-th execution. +#include <cstdint> +#include <cstddef> +#include <iostream> + +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"; + exit(1); + } + return 0; +} + diff --git a/lib/Fuzzer/test/NullDerefOnEmptyTest.cpp b/lib/Fuzzer/test/NullDerefOnEmptyTest.cpp new file mode 100644 index 0000000000000..153710920a5fd --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstdlib> +#include <cstddef> +#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/lib/Fuzzer/test/NullDerefTest.cpp b/lib/Fuzzer/test/NullDerefTest.cpp index 200c56ccbbc90..3f03d24981972 100644 --- a/lib/Fuzzer/test/NullDerefTest.cpp +++ b/lib/Fuzzer/test/NullDerefTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> #include <cstdlib> diff --git a/lib/Fuzzer/test/OneHugeAllocTest.cpp b/lib/Fuzzer/test/OneHugeAllocTest.cpp new file mode 100644 index 0000000000000..617fa20fa2e02 --- /dev/null +++ b/lib/Fuzzer/test/OneHugeAllocTest.cpp @@ -0,0 +1,29 @@ +// 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 <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> +#include <unistd.h> + +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/lib/Fuzzer/test/OutOfMemoryTest.cpp b/lib/Fuzzer/test/OutOfMemoryTest.cpp new file mode 100644 index 0000000000000..e5c9f0a038f5d --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> +#include <unistd.h> + +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; + sleep(1); + } + } + } + } + return 0; +} + diff --git a/lib/Fuzzer/test/RepeatedMemcmp.cpp b/lib/Fuzzer/test/RepeatedMemcmp.cpp new file mode 100644 index 0000000000000..a327bbee7815e --- /dev/null +++ b/lib/Fuzzer/test/RepeatedMemcmp.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + + +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Matches = 0; + for (size_t i = 0; i + 2 < Size; i += 3) { + const char *Pat = i % 2 ? "foo" : "bar"; + if (!memcmp(Data + i, Pat, 3)) + Matches++; + } + if (Matches > 20) { + fprintf(stderr, "BINGO!\n"); + exit(1); + } + return 0; +} diff --git a/lib/Fuzzer/test/SignedIntOverflowTest.cpp b/lib/Fuzzer/test/SignedIntOverflowTest.cpp new file mode 100644 index 0000000000000..7df32ad57933d --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> +#include <climits> + +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/lib/Fuzzer/test/SimpleCmpTest.cpp b/lib/Fuzzer/test/SimpleCmpTest.cpp index 8568c737efb1e..54dc016ce8437 100644 --- a/lib/Fuzzer/test/SimpleCmpTest.cpp +++ b/lib/Fuzzer/test/SimpleCmpTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdlib> diff --git a/lib/Fuzzer/test/SimpleDictionaryTest.cpp b/lib/Fuzzer/test/SimpleDictionaryTest.cpp index b9cb2f0270a33..cd7292bd006c8 100644 --- a/lib/Fuzzer/test/SimpleDictionaryTest.cpp +++ b/lib/Fuzzer/test/SimpleDictionaryTest.cpp @@ -1,3 +1,6 @@ +// 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" diff --git a/lib/Fuzzer/test/SimpleFnAdapterTest.cpp b/lib/Fuzzer/test/SimpleFnAdapterTest.cpp new file mode 100644 index 0000000000000..d30c98b250ea3 --- /dev/null +++ b/lib/Fuzzer/test/SimpleFnAdapterTest.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 Fn adapter. The fuzzer has to find two non-empty +// vectors with the same content. + +#include <iostream> +#include <vector> + +#include "FuzzerFnAdapter.h" + +static void TestFn(std::vector<uint8_t> V1, std::vector<uint8_t> V2) { + if (V1.size() > 0 && V1 == V2) { + std::cout << "BINGO; Found the target, exiting\n"; + exit(0); + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + fuzzer::Adapt(TestFn, Data, Size); + return 0; +} + + diff --git a/lib/Fuzzer/test/SimpleHashTest.cpp b/lib/Fuzzer/test/SimpleHashTest.cpp index 5bab3fa7f6494..00599de78ebed 100644 --- a/lib/Fuzzer/test/SimpleHashTest.cpp +++ b/lib/Fuzzer/test/SimpleHashTest.cpp @@ -1,3 +1,6 @@ +// 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. diff --git a/lib/Fuzzer/test/SimpleTest.cpp b/lib/Fuzzer/test/SimpleTest.cpp index 04225a889f5d5..e53ea160ed8fb 100644 --- a/lib/Fuzzer/test/SimpleTest.cpp +++ b/lib/Fuzzer/test/SimpleTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> diff --git a/lib/Fuzzer/test/SimpleThreadedTest.cpp b/lib/Fuzzer/test/SimpleThreadedTest.cpp new file mode 100644 index 0000000000000..5f02d3f8457cb --- /dev/null +++ b/lib/Fuzzer/test/SimpleThreadedTest.cpp @@ -0,0 +1,25 @@ +// 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 <cstdint> +#include <cstddef> +#include <cstring> +#include <iostream> +#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"; + 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/lib/Fuzzer/test/SpamyTest.cpp b/lib/Fuzzer/test/SpamyTest.cpp new file mode 100644 index 0000000000000..d294d4dc53e0c --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstdio> +#include <cstddef> +#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/lib/Fuzzer/test/StrcmpTest.cpp b/lib/Fuzzer/test/StrcmpTest.cpp index 835819ae2f451..5a13299046124 100644 --- a/lib/Fuzzer/test/StrcmpTest.cpp +++ b/lib/Fuzzer/test/StrcmpTest.cpp @@ -1,3 +1,6 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + // Break through a series of strcmp. #include <cstring> #include <cstdint> diff --git a/lib/Fuzzer/test/StrncmpTest.cpp b/lib/Fuzzer/test/StrncmpTest.cpp index 55344d75e0b1f..8575c2682f1a9 100644 --- a/lib/Fuzzer/test/StrncmpTest.cpp +++ b/lib/Fuzzer/test/StrncmpTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstring> #include <cstdint> diff --git a/lib/Fuzzer/test/StrstrTest.cpp b/lib/Fuzzer/test/StrstrTest.cpp new file mode 100644 index 0000000000000..90d539b660a9b --- /dev/null +++ b/lib/Fuzzer/test/StrstrTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test strstr and strcasestr hooks. +#include <string> +#include <string.h> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + std::string s(reinterpret_cast<const char*>(Data), Size); + if (strstr(s.c_str(), "FUZZ") && strcasestr(s.c_str(), "aBcD")) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/lib/Fuzzer/test/SwitchTest.cpp b/lib/Fuzzer/test/SwitchTest.cpp index 5de7fff745257..3dc051ff7b5b1 100644 --- a/lib/Fuzzer/test/SwitchTest.cpp +++ b/lib/Fuzzer/test/SwitchTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> #include <cstdlib> diff --git a/lib/Fuzzer/test/ThreadedLeakTest.cpp b/lib/Fuzzer/test/ThreadedLeakTest.cpp new file mode 100644 index 0000000000000..7511071108712 --- /dev/null +++ b/lib/Fuzzer/test/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 <cstdint> +#include <cstddef> +#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/lib/Fuzzer/test/ThreadedTest.cpp b/lib/Fuzzer/test/ThreadedTest.cpp index 7aa114a41f36d..09137a9a70c17 100644 --- a/lib/Fuzzer/test/ThreadedTest.cpp +++ b/lib/Fuzzer/test/ThreadedTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> diff --git a/lib/Fuzzer/test/TimeoutTest.cpp b/lib/Fuzzer/test/TimeoutTest.cpp index 71790ded95a28..f8107012c841f 100644 --- a/lib/Fuzzer/test/TimeoutTest.cpp +++ b/lib/Fuzzer/test/TimeoutTest.cpp @@ -1,3 +1,6 @@ +// 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 <cstdint> #include <cstdlib> diff --git a/lib/Fuzzer/test/UninstrumentedTest.cpp b/lib/Fuzzer/test/UninstrumentedTest.cpp index c1730198d83f1..ffe952c749d22 100644 --- a/lib/Fuzzer/test/UninstrumentedTest.cpp +++ b/lib/Fuzzer/test/UninstrumentedTest.cpp @@ -1,3 +1,6 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + // This test should not be instrumented. #include <cstdint> #include <cstddef> diff --git a/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp b/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp deleted file mode 100644 index 59f83b57bfad6..0000000000000 --- a/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Simple test for a fuzzer. -// The fuzzer must find the string "Hi!" preceded by a magic value. -// Uses UserSuppliedFuzzer which ensures that the magic is present. -#include <cstdint> -#include <cassert> -#include <cstdlib> -#include <cstddef> -#include <cstring> -#include <iostream> - -#include "FuzzerInterface.h" - -static const uint64_t kMagic = 8860221463604ULL; - -class MyFuzzer : public fuzzer::UserSuppliedFuzzer { - public: - MyFuzzer(fuzzer::FuzzerRandomBase *Rand) - : fuzzer::UserSuppliedFuzzer(Rand) {} - int TargetFunction(const uint8_t *Data, size_t Size) { - if (Size <= 10) return 0; - if (memcmp(Data, &kMagic, sizeof(kMagic))) return 0; - // It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing). - // So, we simply 'fix' the data in the custom mutator. - if (Data[8] == 'H') { - if (Data[9] == 'i') { - if (Data[10] == '!') { - std::cout << "BINGO; Found the target, exiting\n"; - exit(1); - } - } - } - return 0; - } - // Custom mutator. - virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(MaxSize > sizeof(kMagic)); - if (Size < sizeof(kMagic)) - Size = sizeof(kMagic); - // "Fix" the data, then mutate. - memcpy(Data, &kMagic, std::min(MaxSize, sizeof(kMagic))); - return fuzzer::UserSuppliedFuzzer::Mutate( - Data + sizeof(kMagic), Size - sizeof(kMagic), MaxSize - sizeof(kMagic)); - } - // No need to redefine CrossOver() here. -}; - -int main(int argc, char **argv) { - fuzzer::FuzzerRandomLibc Rand(0); - MyFuzzer F(&Rand); - fuzzer::FuzzerDriver(argc, argv, F); -} diff --git a/lib/Fuzzer/test/afl-driver-extra-stats.test b/lib/Fuzzer/test/afl-driver-extra-stats.test new file mode 100644 index 0000000000000..81e384e7dad2e --- /dev/null +++ b/lib/Fuzzer/test/afl-driver-extra-stats.test @@ -0,0 +1,28 @@ +; Test that not specifying an extra stats file isn't broken. +RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME +RUN: AFLDriverTest + +; Test that specifying an invalid extra stats file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash 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 AFLDriverTest + +; Test that specifying a valid nonexistent stats file works. +RUN: rm -f %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%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 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 AFLDriverTest +RUN: [[ $(grep "9999" %t | wc -l) -eq 2 ]] diff --git a/lib/Fuzzer/test/afl-driver-stderr.test b/lib/Fuzzer/test/afl-driver-stderr.test new file mode 100644 index 0000000000000..c0f9c8398c2a1 --- /dev/null +++ b/lib/Fuzzer/test/afl-driver-stderr.test @@ -0,0 +1,10 @@ +; Test that not specifying a stderr file isn't broken. +RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME +RUN: AFLDriverTest + +; Test that specifying an invalid file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash AFLDriverTest + +; Test that a file is created when specified as the duplicate stderr. +RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t AFLDriverTest +RUN: stat %t diff --git a/lib/Fuzzer/test/dfsan/CMakeLists.txt b/lib/Fuzzer/test/dfsan/CMakeLists.txt index 2b49831fcdb85..2a4dc18bfeedb 100644 --- a/lib/Fuzzer/test/dfsan/CMakeLists.txt +++ b/lib/Fuzzer/test/dfsan/CMakeLists.txt @@ -1,14 +1,19 @@ # These tests depend on both coverage and dfsan instrumentation. -set(CMAKE_CXX_FLAGS_RELEASE - "${LIBFUZZER_FLAGS_BASE} -O0 -fno-sanitize=all -fsanitize=dataflow") +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize=all -fsanitize=dataflow") + +set(DFSanTests + MemcmpTest + SimpleCmpTest + StrcmpTest + StrncmpTest + SwitchTest + ) foreach(Test ${DFSanTests}) - add_executable(LLVMFuzzer-${Test}-DFSan - ../${Test}.cpp - ) - target_link_libraries(LLVMFuzzer-${Test}-DFSan - LLVMFuzzer - ) + add_libfuzzer_test(${Test}-DFSan SOURCES ../${Test}.cpp) endforeach() +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/lib/Fuzzer/test/fuzzer-customcrossover.test b/lib/Fuzzer/test/fuzzer-customcrossover.test new file mode 100644 index 0000000000000..4be54d3f799e2 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-customcrossover.test @@ -0,0 +1,10 @@ +RUN: rm -rf %t/CustomCrossover +RUN: mkdir -p %t/CustomCrossover +RUN: echo "0123456789" > %t/CustomCrossover/digits +RUN: echo "abcdefghij" > %t/CustomCrossover/chars +RUN: not LLVMFuzzer-CustomCrossOverTest -seed=1 -use_memcmp=0 -runs=100000 -prune_corpus=0 %t/CustomCrossover 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomCrossover +RUN: rm -rf %t/CustomCrossover + +LLVMFuzzerCustomCrossover: In LLVMFuzzerCustomCrossover +LLVMFuzzerCustomCrossover: BINGO + diff --git a/lib/Fuzzer/test/fuzzer-custommutator.test b/lib/Fuzzer/test/fuzzer-custommutator.test new file mode 100644 index 0000000000000..fcd740bf5457c --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-custommutator.test @@ -0,0 +1,4 @@ +RUN: not LLVMFuzzer-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: BINGO + diff --git a/lib/Fuzzer/test/fuzzer-dfsan.test b/lib/Fuzzer/test/fuzzer-dfsan.test index 567086ed65afd..5bd5c0f18d2f1 100644 --- a/lib/Fuzzer/test/fuzzer-dfsan.test +++ b/lib/Fuzzer/test/fuzzer-dfsan.test @@ -1,3 +1,4 @@ +REQUIRES: dfsan CHECK1: BINGO CHECK2: BINGO CHECK3: BINGO @@ -7,10 +8,10 @@ CHECK_DFSanCmpCallback: DFSanCmpCallback: PC CHECK_DFSanSwitchCallback: DFSanSwitchCallback: PC CHECK_DFSanMemcmpCallback: DFSanMemcmpCallback: Pos -RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1 +RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=10000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1 RUN: LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=100 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanCmpCallback -RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2 +RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2 RUN: LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanMemcmpCallback RUN: not LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK3 diff --git a/lib/Fuzzer/test/fuzzer-dirs.test b/lib/Fuzzer/test/fuzzer-dirs.test new file mode 100644 index 0000000000000..3eaaf6b6bb5bd --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-dirs.test @@ -0,0 +1,12 @@ +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: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS +SUBDIRS: READ units: 3 +RUN: rm -rf %t/SUB1 + +RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR +NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting + diff --git a/lib/Fuzzer/test/fuzzer-fdmask.test b/lib/Fuzzer/test/fuzzer-fdmask.test new file mode 100644 index 0000000000000..abbc4bd6412f7 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-fdmask.test @@ -0,0 +1,30 @@ +RUN: LLVMFuzzer-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2 +RUN: LLVMFuzzer-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/lib/Fuzzer/test/fuzzer-finalstats.test b/lib/Fuzzer/test/fuzzer-finalstats.test new file mode 100644 index 0000000000000..1cbcd10f0498c --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-finalstats.test @@ -0,0 +1,11 @@ +RUN: LLVMFuzzer-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: LLVMFuzzer-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/lib/Fuzzer/test/fuzzer-flags.test b/lib/Fuzzer/test/fuzzer-flags.test new file mode 100644 index 0000000000000..a94faf20a5865 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-flags.test @@ -0,0 +1,8 @@ +RUN: LLVMFuzzer-SimpleTest -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: LLVMFuzzer-SimpleTest -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 + diff --git a/lib/Fuzzer/test/fuzzer-fn-adapter.test b/lib/Fuzzer/test/fuzzer-fn-adapter.test new file mode 100644 index 0000000000000..0ea96f3f9f000 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-fn-adapter.test @@ -0,0 +1,3 @@ +RUN: LLVMFuzzer-SimpleFnAdapterTest 2>&1 | FileCheck %s + +CHECK: BINGO diff --git a/lib/Fuzzer/test/fuzzer-leak.test b/lib/Fuzzer/test/fuzzer-leak.test new file mode 100644 index 0000000000000..59ba02cd7d280 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-leak.test @@ -0,0 +1,31 @@ +REQUIRES: lsan +RUN: not LLVMFuzzer-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 LLVMFuzzer-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 LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not LLVMFuzzer-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not LLVMFuzzer-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 LLVMFuzzer-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 LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT +LEAK_TIMEOUT: ERROR: libFuzzer: timeout after +LEAK_TIMEOUT-NOT: LeakSanitizer + +RUN: LLVMFuzzer-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/lib/Fuzzer/test/fuzzer-oom-with-profile.test b/lib/Fuzzer/test/fuzzer-oom-with-profile.test new file mode 100644 index 0000000000000..391fd4bb0ff60 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-oom-with-profile.test @@ -0,0 +1,6 @@ +REQUIRES: linux +RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=10 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 10Mb) +CHECK: Live Heap Allocations +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory diff --git a/lib/Fuzzer/test/fuzzer-oom.test b/lib/Fuzzer/test/fuzzer-oom.test new file mode 100644 index 0000000000000..4cdff2142fda3 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-oom.test @@ -0,0 +1,4 @@ +RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=10 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 10Mb) +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory diff --git a/lib/Fuzzer/test/fuzzer-printcovpcs.test b/lib/Fuzzer/test/fuzzer-printcovpcs.test new file mode 100644 index 0000000000000..70b22c7a54b94 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-printcovpcs.test @@ -0,0 +1,5 @@ +RUN: LLVMFuzzer-SimpleTest -print_new_cov_pcs=1 2>&1 | FileCheck %s --check-prefix=PCS +PCS:{{^0x[a-f0-9]+}} +PCS:NEW +PCS:BINGO + diff --git a/lib/Fuzzer/test/fuzzer-prunecorpus.test b/lib/Fuzzer/test/fuzzer-prunecorpus.test new file mode 100644 index 0000000000000..a8a660e91b9ad --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-prunecorpus.test @@ -0,0 +1,13 @@ +RUN: rm -rf %t/PruneCorpus +RUN: mkdir -p %t/PruneCorpus +RUN: echo a > %t/PruneCorpus/a +RUN: echo b > %t/PruneCorpus/b +RUN: LLVMFuzzer-EmptyTest %t/PruneCorpus -prune_corpus=1 -runs=0 2>&1 | FileCheck %s --check-prefix=PRUNE +RUN: LLVMFuzzer-EmptyTest %t/PruneCorpus -prune_corpus=0 -runs=0 2>&1 | FileCheck %s --check-prefix=NOPRUNE +RUN: rm -rf %t/PruneCorpus + +PRUNE: READ units: 2 +PRUNE: INITED{{.*}}units: 1 +NOPRUNE: READ units: 2 +NOPRUNE: INITED{{.*}}units: 2 + diff --git a/lib/Fuzzer/test/fuzzer-runs.test b/lib/Fuzzer/test/fuzzer-runs.test new file mode 100644 index 0000000000000..056c44782a15f --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-runs.test @@ -0,0 +1,8 @@ +RUN: mkdir -p %t +RUN: echo abcd > %t/NthRunCrashTest.in +RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in +RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 +RUN: not LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s +RUN: rm %t/NthRunCrashTest.in +CHECK: BINGO + diff --git a/lib/Fuzzer/test/fuzzer-seed.test b/lib/Fuzzer/test/fuzzer-seed.test new file mode 100644 index 0000000000000..f1bdf9e4ae942 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-seed.test @@ -0,0 +1,3 @@ +RUN: LLVMFuzzer-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE +CHECK_SEED_MINUS_ONE: Seed: 4294967295 + diff --git a/lib/Fuzzer/test/fuzzer-segv.test b/lib/Fuzzer/test/fuzzer-segv.test new file mode 100644 index 0000000000000..330f03bcc4945 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-segv.test @@ -0,0 +1,5 @@ +RUN: ASAN_OPTIONS=handle_segv=0 not LLVMFuzzer-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- + diff --git a/lib/Fuzzer/test/fuzzer-singleinputs.test b/lib/Fuzzer/test/fuzzer-singleinputs.test new file mode 100644 index 0000000000000..a4faf2cea50cc --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-singleinputs.test @@ -0,0 +1,13 @@ +RUN: not LLVMFuzzer-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: LLVMFuzzer-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: rm -rf %tmp/SINGLE_INPUTS +SINGLE_INPUTS: LLVMFuzzer-SimpleTest: Running 2 inputs 1 time(s) each. +SINGLE_INPUTS: aaa in +SINGLE_INPUTS: bbb in + diff --git a/lib/Fuzzer/test/fuzzer-timeout.test b/lib/Fuzzer/test/fuzzer-timeout.test index c3a9e8a3a9e08..8e8b713fcd792 100644 --- a/lib/Fuzzer/test/fuzzer-timeout.test +++ b/lib/Fuzzer/test/fuzzer-timeout.test @@ -7,7 +7,8 @@ TimeoutTest: #1 TimeoutTest: #2 TimeoutTest: SUMMARY: libFuzzer: timeout -RUN: not LLVMFuzzer-TimeoutTest -timeout=1 -test_single_input=%S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest -SingleInputTimeoutTest: ALARM: working on the last Unit for +RUN: not LLVMFuzzer-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: LLVMFuzzer-TimeoutTest -timeout=1 -timeout_exitcode=0 diff --git a/lib/Fuzzer/test/fuzzer-trace-pc.test b/lib/Fuzzer/test/fuzzer-trace-pc.test new file mode 100644 index 0000000000000..673249d047865 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-trace-pc.test @@ -0,0 +1,7 @@ +CHECK: BINGO +REQUIRES: linux +RUN: not LLVMFuzzer-FourIndependentBranchesTest-TracePC -seed=1 -runs=1000000 2>&1 | FileCheck %s +// FIXME: The test below uses a significant amount of memory on OSX and +// sometimes hits the 2GiB memory limit. This needs to be investigated. For now +// only run the test on Linux. +RUN: not LLVMFuzzer-FullCoverageSetTest-TracePC -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/lib/Fuzzer/test/fuzzer-traces-hooks.test b/lib/Fuzzer/test/fuzzer-traces-hooks.test new file mode 100644 index 0000000000000..71fe6f2daf110 --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-traces-hooks.test @@ -0,0 +1,25 @@ +// FIXME: Support sanitizer hooks for memcmp and strcmp need +// to be implemented in the sanitizer runtime for platforms other +// than linux +REQUIRES: linux +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: not LLVMFuzzer-MemcmpTest -seed=4294967295 -runs=100000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-MemcmpTest -use_memcmp=0 -seed=4294967295 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrncmpTest -seed=2 -runs=100000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrncmpTest -use_memcmp=0 -seed=3 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrcmpTest -seed=4 -runs=200000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrcmpTest -use_memcmp=0 -seed=5 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrstrTest -seed=6 -runs=200000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrstrTest -use_memmem=0 -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: LLVMFuzzer-RepeatedMemcmp -seed=10 -runs=100000 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/lib/Fuzzer/test/fuzzer-traces.test b/lib/Fuzzer/test/fuzzer-traces.test index 3b8639b8e9413..2d77295366436 100644 --- a/lib/Fuzzer/test/fuzzer-traces.test +++ b/lib/Fuzzer/test/fuzzer-traces.test @@ -1,20 +1,9 @@ CHECK: BINGO Done1000000: Done 1000000 runs in -Done10000000: Done 10000000 runs in - RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=10000001 2>&1 | FileCheck %s -RUN: not LLVMFuzzer-MemcmpTest -use_traces=1 -seed=4294967295 -runs=100000 2>&1 | FileCheck %s -RUN: LLVMFuzzer-MemcmpTest -seed=4294967295 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 - -RUN: not LLVMFuzzer-StrncmpTest -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s -RUN: LLVMFuzzer-StrncmpTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 - -RUN: not LLVMFuzzer-StrcmpTest -use_traces=1 -seed=1 -runs=200000 2>&1 | FileCheck %s -RUN: LLVMFuzzer-StrcmpTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 - -RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=1 -runs=1000002 2>&1 | FileCheck %s -RUN: LLVMFuzzer-SwitchTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 +RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=6 -runs=1000002 2>&1 | FileCheck %s +RUN: LLVMFuzzer-SwitchTest -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 -RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=1 -runs=10000000 2>&1 | FileCheck %s -RUN: LLVMFuzzer-SimpleHashTest -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=Done10000000 +RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=1000000 -max_len=16 2>&1 | FileCheck %s +RUN: LLVMFuzzer-SimpleHashTest -seed=9 -runs=1000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done1000000 diff --git a/lib/Fuzzer/test/fuzzer-trunc.test b/lib/Fuzzer/test/fuzzer-trunc.test new file mode 100644 index 0000000000000..ebab7b863a0fe --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-trunc.test @@ -0,0 +1,10 @@ +# Test truncate_units option. +RUN: rm -rf FuzzerTruncateTestCORPUS +RUN: mkdir FuzzerTruncateTestCORPUS +RUN: echo "01234567890123456789012345678901234567890" > FuzzerTruncateTestCORPUS/unit1 +# Simply running a fuzzer won't produce new results +RUN: LLVMFuzzer-EmptyTest -seed=1 -runs=100 -truncate_units=0 ./FuzzerTruncateTestCORPUS +# Truncating would create a new unit of length 1. +RUN: LLVMFuzzer-EmptyTest -seed=1 -runs=0 -truncate_units=1 ./FuzzerTruncateTestCORPUS +RUN: find FuzzerTruncateTestCORPUS/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c +RUN: rm -rf FuzzerTruncateTestCORPUS diff --git a/lib/Fuzzer/test/fuzzer-ubsan.test b/lib/Fuzzer/test/fuzzer-ubsan.test new file mode 100644 index 0000000000000..0e8ad6c94a1bb --- /dev/null +++ b/lib/Fuzzer/test/fuzzer-ubsan.test @@ -0,0 +1,4 @@ +RUN: not LLVMFuzzer-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/lib/Fuzzer/test/fuzzer.test b/lib/Fuzzer/test/fuzzer.test index c63014f59d62f..11343ae3834a1 100644 --- a/lib/Fuzzer/test/fuzzer.test +++ b/lib/Fuzzer/test/fuzzer.test @@ -2,19 +2,25 @@ CHECK: BINGO Done1000000: Done 1000000 runs in RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s -RUN: not LLVMFuzzer-NullDerefTest -test_single_input=%S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput -SingleInput-NOT: Test unit written to ./crash- + +# only_ascii mode. Will perform some minimal self-validation. +RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1 RUN: LLVMFuzzer-SimpleCmpTest -max_total_time=1 2>&1 | FileCheck %s --check-prefix=MaxTotalTime MaxTotalTime: Done {{.*}} runs in {{.}} second(s) -RUN: not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest +RUN: not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest +RUN: not LLVMFuzzer-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest +NullDerefTest: ERROR: AddressSanitizer: SEGV on unknown address NullDerefTest: Test unit written to ./crash- RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix NullDerefTestPrefix: Test unit written to ZZZcrash- RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath NullDerefTestExactPath: Test unit written to FOOBAR +RUN: not LLVMFuzzer-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 LLVMFuzzer-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s RUN: not LLVMFuzzer-CounterTest -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s @@ -23,14 +29,15 @@ RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len= # This one is flaky, may actually find the goal even w/o use_indir_calls. # LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 - -RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s - RUN: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting. -RUN: LLVMFuzzer-SimpleTest -print_new_cov_pcs=1 2>&1 | FileCheck %s --check-prefix=PCS -PCS:{{^0x[a-f0-9]+}} -PCS:NEW -PCS:BINGO +RUN: not LLVMFuzzer-UninstrumentedTest-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 LLVMFuzzer-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 LLVMFuzzer-InitializeTest 2>&1 | FileCheck %s diff --git a/lib/Fuzzer/test/lit.cfg b/lib/Fuzzer/test/lit.cfg index 2140a97668b37..e262e3c25850b 100644 --- a/lib/Fuzzer/test/lit.cfg +++ b/lib/Fuzzer/test/lit.cfg @@ -1,4 +1,5 @@ import lit.formats +import sys config.name = "LLVMFuzzer" config.test_format = lit.formats.ShTest(True) @@ -13,3 +14,22 @@ path = os.path.pathsep.join((llvm_tools_dir, config.test_exec_root, config.environment['PATH'])) config.environment['PATH'] = path +if config.has_dfsan: + lit_config.note('dfsan feature available') + config.available_features.add('dfsan') +else: + lit_config.note('dfsan feature unavailable') + +if config.has_lsan: + lit_config.note('lsan feature available') + config.available_features.add('lsan') +else: + lit_config.note('lsan feature unavailable') + +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') diff --git a/lib/Fuzzer/test/lit.site.cfg.in b/lib/Fuzzer/test/lit.site.cfg.in index e520db8e881de..95ad6d0ab178b 100644 --- a/lib/Fuzzer/test/lit.site.cfg.in +++ b/lib/Fuzzer/test/lit.site.cfg.in @@ -1,3 +1,5 @@ config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" +config.has_dfsan = True if @HAS_DFSAN@ == 1 else False +config.has_lsan = True if @HAS_LSAN@ == 1 else False lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/lib/Fuzzer/test/merge.test b/lib/Fuzzer/test/merge.test index 57ecc141bbfe2..6f19e21d132d7 100644 --- a/lib/Fuzzer/test/merge.test +++ b/lib/Fuzzer/test/merge.test @@ -8,8 +8,8 @@ RUN: echo ..Z... > %tmp/T1/3 # T1 has 3 elements, T2 is empty. RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK1 -CHECK1: Merge: running the initial corpus {{.*}} of 3 units -CHECK1: Merge: written 0 out of 0 units +CHECK1: === Minimizing the initial corpus of 3 units +CHECK1: === Merge: written 0 units RUN: echo ...Z.. > %tmp/T2/1 RUN: echo ....E. > %tmp/T2/2 @@ -20,10 +20,11 @@ RUN: echo ..Z... > %tmp/T2/c # T1 has 3 elements, T2 has 6 elements, only 3 are new. RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK2 -CHECK2: Merge: running the initial corpus {{.*}} of 3 units -CHECK2: Merge: written 3 out of 6 units +CHECK2: === Minimizing the initial corpus of 3 units +CHECK2: === Merging extra 6 units +CHECK2: === Merge: written 3 units # Now, T1 has 6 units and T2 has no new interesting units. RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK3 -CHECK3: Merge: running the initial corpus {{.*}} of 6 units -CHECK3: Merge: written 0 out of 6 units +CHECK3: === Minimizing the initial corpus of 6 units +CHECK3: === Merge: written 0 units diff --git a/lib/Fuzzer/test/no-coverage/CMakeLists.txt b/lib/Fuzzer/test/no-coverage/CMakeLists.txt new file mode 100644 index 0000000000000..1dc7d15926ca3 --- /dev/null +++ b/lib/Fuzzer/test/no-coverage/CMakeLists.txt @@ -0,0 +1,16 @@ +# These tests are not instrumented with coverage, +# but have coverage rt in the binary. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") + +set(NoCoverageTests + UninstrumentedTest + ) + +foreach(Test ${NoCoverageTests}) + add_libfuzzer_test(${Test}-NoCoverage SOURCES ../${Test}.cpp) +endforeach() + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/lib/Fuzzer/test/trace-bb/CMakeLists.txt b/lib/Fuzzer/test/trace-bb/CMakeLists.txt index 99af019565b5a..fd168c4515b95 100644 --- a/lib/Fuzzer/test/trace-bb/CMakeLists.txt +++ b/lib/Fuzzer/test/trace-bb/CMakeLists.txt @@ -1,14 +1,15 @@ # These tests are not instrumented with coverage. -set(CMAKE_CXX_FLAGS_RELEASE +set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fsanitize-coverage=edge,trace-bb") +set(TraceBBTests + SimpleTest + ) + foreach(Test ${TraceBBTests}) - add_executable(LLVMFuzzer-${Test}-TraceBB - ../${Test}.cpp - ) - target_link_libraries(LLVMFuzzer-${Test}-TraceBB - LLVMFuzzer - ) + add_libfuzzer_test(${Test}-TraceBB SOURCES ../${Test}.cpp) endforeach() +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/lib/Fuzzer/test/trace-pc/CMakeLists.txt b/lib/Fuzzer/test/trace-pc/CMakeLists.txt new file mode 100644 index 0000000000000..cf18278ac64b3 --- /dev/null +++ b/lib/Fuzzer/test/trace-pc/CMakeLists.txt @@ -0,0 +1,16 @@ +# These tests are not instrumented with coverage. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=8bit-counters -fsanitize-coverage=trace-pc") + +set(TracePCTests + FourIndependentBranchesTest + FullCoverageSetTest + ) + +foreach(Test ${TracePCTests}) + add_libfuzzer_test(${Test}-TracePC SOURCES ../${Test}.cpp) +endforeach() + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/lib/Fuzzer/test/ubsan/CMakeLists.txt b/lib/Fuzzer/test/ubsan/CMakeLists.txt new file mode 100644 index 0000000000000..7a9eacdbe7df3 --- /dev/null +++ b/lib/Fuzzer/test/ubsan/CMakeLists.txt @@ -0,0 +1,15 @@ +# These tests are instrumented with ubsan in non-recovery mode. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fsanitize=undefined -fno-sanitize-recover=all") + +set(UbsanTests + SignedIntOverflowTest + ) + +foreach(Test ${UbsanTests}) + add_libfuzzer_test(${Test}-Ubsan SOURCES ../${Test}.cpp) +endforeach() + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/lib/Fuzzer/test/uninstrumented/CMakeLists.txt b/lib/Fuzzer/test/uninstrumented/CMakeLists.txt index 443ba3716f665..06e48985e7efb 100644 --- a/lib/Fuzzer/test/uninstrumented/CMakeLists.txt +++ b/lib/Fuzzer/test/uninstrumented/CMakeLists.txt @@ -1,14 +1,16 @@ -# These tests are not instrumented with coverage. +# These tests are not instrumented with coverage and don't +# have coverage rt in the binary. -set(CMAKE_CXX_FLAGS_RELEASE - "${LIBFUZZER_FLAGS_BASE} -O0 -fno-sanitize=all") +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize=all -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") + +set(UninstrumentedTests + UninstrumentedTest + ) foreach(Test ${UninstrumentedTests}) - add_executable(LLVMFuzzer-${Test}-Uninstrumented - ../${Test}.cpp - ) - target_link_libraries(LLVMFuzzer-${Test}-Uninstrumented - LLVMFuzzer - ) + add_libfuzzer_test(${Test}-Uninstrumented SOURCES ../${Test}.cpp) endforeach() +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) |