summaryrefslogtreecommitdiff
path: root/lib/Fuzzer/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Fuzzer/test')
-rw-r--r--lib/Fuzzer/test/AFLDriverTest.cpp22
-rw-r--r--lib/Fuzzer/test/AccumulateAllocationsTest.cpp17
-rw-r--r--lib/Fuzzer/test/BufferOverflowOnInput.cpp23
-rw-r--r--lib/Fuzzer/test/CMakeLists.txt205
-rw-r--r--lib/Fuzzer/test/CallerCalleeTest.cpp3
-rw-r--r--lib/Fuzzer/test/CounterTest.cpp3
-rw-r--r--lib/Fuzzer/test/CustomCrossOverTest.cpp57
-rw-r--r--lib/Fuzzer/test/CustomMutatorTest.cpp38
-rw-r--r--lib/Fuzzer/test/EmptyTest.cpp11
-rw-r--r--lib/Fuzzer/test/FourIndependentBranchesTest.cpp3
-rw-r--r--lib/Fuzzer/test/FullCoverageSetTest.cpp3
-rw-r--r--lib/Fuzzer/test/FuzzerFnAdapterUnittest.cpp110
-rw-r--r--lib/Fuzzer/test/FuzzerUnittest.cpp103
-rw-r--r--lib/Fuzzer/test/InitializeTest.cpp26
-rw-r--r--lib/Fuzzer/test/LeakTest.cpp17
-rw-r--r--lib/Fuzzer/test/LeakTimeoutTest.cpp17
-rw-r--r--lib/Fuzzer/test/MemcmpTest.cpp5
-rw-r--r--lib/Fuzzer/test/NthRunCrashTest.cpp18
-rw-r--r--lib/Fuzzer/test/NullDerefOnEmptyTest.cpp19
-rw-r--r--lib/Fuzzer/test/NullDerefTest.cpp3
-rw-r--r--lib/Fuzzer/test/OneHugeAllocTest.cpp29
-rw-r--r--lib/Fuzzer/test/OutOfMemoryTest.cpp31
-rw-r--r--lib/Fuzzer/test/RepeatedMemcmp.cpp22
-rw-r--r--lib/Fuzzer/test/SignedIntOverflowTest.cpp28
-rw-r--r--lib/Fuzzer/test/SimpleCmpTest.cpp3
-rw-r--r--lib/Fuzzer/test/SimpleDictionaryTest.cpp3
-rw-r--r--lib/Fuzzer/test/SimpleFnAdapterTest.cpp24
-rw-r--r--lib/Fuzzer/test/SimpleHashTest.cpp3
-rw-r--r--lib/Fuzzer/test/SimpleTest.cpp3
-rw-r--r--lib/Fuzzer/test/SimpleThreadedTest.cpp25
-rw-r--r--lib/Fuzzer/test/SpamyTest.cpp21
-rw-r--r--lib/Fuzzer/test/StrcmpTest.cpp3
-rw-r--r--lib/Fuzzer/test/StrncmpTest.cpp3
-rw-r--r--lib/Fuzzer/test/StrstrTest.cpp18
-rw-r--r--lib/Fuzzer/test/SwitchTest.cpp3
-rw-r--r--lib/Fuzzer/test/ThreadedLeakTest.cpp18
-rw-r--r--lib/Fuzzer/test/ThreadedTest.cpp3
-rw-r--r--lib/Fuzzer/test/TimeoutTest.cpp3
-rw-r--r--lib/Fuzzer/test/UninstrumentedTest.cpp3
-rw-r--r--lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp51
-rw-r--r--lib/Fuzzer/test/afl-driver-extra-stats.test28
-rw-r--r--lib/Fuzzer/test/afl-driver-stderr.test10
-rw-r--r--lib/Fuzzer/test/dfsan/CMakeLists.txt21
-rw-r--r--lib/Fuzzer/test/fuzzer-customcrossover.test10
-rw-r--r--lib/Fuzzer/test/fuzzer-custommutator.test4
-rw-r--r--lib/Fuzzer/test/fuzzer-dfsan.test5
-rw-r--r--lib/Fuzzer/test/fuzzer-dirs.test12
-rw-r--r--lib/Fuzzer/test/fuzzer-fdmask.test30
-rw-r--r--lib/Fuzzer/test/fuzzer-finalstats.test11
-rw-r--r--lib/Fuzzer/test/fuzzer-flags.test8
-rw-r--r--lib/Fuzzer/test/fuzzer-fn-adapter.test3
-rw-r--r--lib/Fuzzer/test/fuzzer-leak.test31
-rw-r--r--lib/Fuzzer/test/fuzzer-oom-with-profile.test6
-rw-r--r--lib/Fuzzer/test/fuzzer-oom.test4
-rw-r--r--lib/Fuzzer/test/fuzzer-printcovpcs.test5
-rw-r--r--lib/Fuzzer/test/fuzzer-prunecorpus.test13
-rw-r--r--lib/Fuzzer/test/fuzzer-runs.test8
-rw-r--r--lib/Fuzzer/test/fuzzer-seed.test3
-rw-r--r--lib/Fuzzer/test/fuzzer-segv.test5
-rw-r--r--lib/Fuzzer/test/fuzzer-singleinputs.test13
-rw-r--r--lib/Fuzzer/test/fuzzer-timeout.test5
-rw-r--r--lib/Fuzzer/test/fuzzer-trace-pc.test7
-rw-r--r--lib/Fuzzer/test/fuzzer-traces-hooks.test25
-rw-r--r--lib/Fuzzer/test/fuzzer-traces.test19
-rw-r--r--lib/Fuzzer/test/fuzzer-trunc.test10
-rw-r--r--lib/Fuzzer/test/fuzzer-ubsan.test4
-rw-r--r--lib/Fuzzer/test/fuzzer.test27
-rw-r--r--lib/Fuzzer/test/lit.cfg20
-rw-r--r--lib/Fuzzer/test/lit.site.cfg.in2
-rw-r--r--lib/Fuzzer/test/merge.test13
-rw-r--r--lib/Fuzzer/test/no-coverage/CMakeLists.txt16
-rw-r--r--lib/Fuzzer/test/trace-bb/CMakeLists.txt15
-rw-r--r--lib/Fuzzer/test/trace-pc/CMakeLists.txt16
-rw-r--r--lib/Fuzzer/test/ubsan/CMakeLists.txt15
-rw-r--r--lib/Fuzzer/test/uninstrumented/CMakeLists.txt20
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)