diff options
Diffstat (limited to 'gnu/llvm/lib/Fuzzer/test')
36 files changed, 1230 insertions, 0 deletions
diff --git a/gnu/llvm/lib/Fuzzer/test/CMakeLists.txt b/gnu/llvm/lib/Fuzzer/test/CMakeLists.txt new file mode 100644 index 00000000000..cd0b167eb38 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/CMakeLists.txt @@ -0,0 +1,118 @@ +# 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 + ) + +set(Tests + CallerCalleeTest + CounterTest + FourIndependentBranchesTest + FullCoverageSetTest + MemcmpTest + NullDerefTest + SimpleCmpTest + SimpleDictionaryTest + SimpleHashTest + SimpleTest + StrcmpTest + StrncmpTest + SwitchTest + ThreadedTest + TimeoutTest + ) + +set(CustomMainTests + UserSuppliedFuzzerTest + ) + +set(UninstrumentedTests + UninstrumentedTest + ) + +set(TraceBBTests + SimpleTest + ) + +set(TestBinaries) + +foreach(Test ${Tests}) + add_executable(LLVMFuzzer-${Test} + ${Test}.cpp + ) + target_link_libraries(LLVMFuzzer-${Test} + LLVMFuzzer + ) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}) +endforeach() + +foreach(Test ${CustomMainTests}) + add_executable(LLVMFuzzer-${Test} + ${Test}.cpp + ) + target_link_libraries(LLVMFuzzer-${Test} + LLVMFuzzerNoMain + ) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}) +endforeach() + + +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 + ) + +include_directories(..) +include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) + +add_executable(LLVMFuzzer-Unittest + FuzzerUnittest.cpp + $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects> + ) + +target_link_libraries(LLVMFuzzer-Unittest + gtest + gtest_main + ) + +set(TestBinaries ${TestBinaries} LLVMFuzzer-Unittest) + +add_subdirectory(dfsan) + +foreach(Test ${DFSanTests}) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-DFSan) +endforeach() + +add_subdirectory(uninstrumented) + +foreach(Test ${UninstrumentedTests}) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-Uninstrumented) +endforeach() + +add_subdirectory(trace-bb) + +foreach(Test ${TraceBBTests}) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test}-TraceBB) +endforeach() + +set_target_properties(${TestBinaries} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + +add_lit_testsuite(check-fuzzer "Running Fuzzer tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${TestBinaries} FileCheck not + ) diff --git a/gnu/llvm/lib/Fuzzer/test/CallerCalleeTest.cpp b/gnu/llvm/lib/Fuzzer/test/CallerCalleeTest.cpp new file mode 100644 index 00000000000..150b2fc0405 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/CallerCalleeTest.cpp @@ -0,0 +1,56 @@ +// Simple test for a fuzzer. +// Try to find the target using the indirect caller-callee pairs. +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +typedef void (*F)(); +static F t[256]; + +void f34() { + std::cerr << "BINGO\n"; + exit(1); +} +void f23() { t[(unsigned)'d'] = f34;} +void f12() { t[(unsigned)'c'] = f23;} +void f01() { t[(unsigned)'b'] = f12;} +void f00() {} + +static F t0[256] = { + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + // Spoof the counters. + for (int i = 0; i < 200; i++) { + f23(); + f12(); + f01(); + } + memcpy(t, t0, sizeof(t)); + t[(unsigned)'a'] = f01; + t[Data[0]](); + t[Data[1]](); + t[Data[2]](); + t[Data[3]](); + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/CounterTest.cpp b/gnu/llvm/lib/Fuzzer/test/CounterTest.cpp new file mode 100644 index 00000000000..b61f419c499 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/CounterTest.cpp @@ -0,0 +1,15 @@ +// Test for a fuzzer: must find the case where a particular basic block is +// executed many times. +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Num = 0; + for (size_t i = 0; i < Size; i++) + if (Data[i] == 'A' + i) + Num++; + if (Num >= 4) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp b/gnu/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp new file mode 100644 index 00000000000..6007dd4a027 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp @@ -0,0 +1,19 @@ +// Simple test for a fuzzer. The fuzzer must find the string "FUZZ". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (bits == 15) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp b/gnu/llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp new file mode 100644 index 00000000000..a868084a0ce --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp @@ -0,0 +1,21 @@ +// Simple test for a fuzzer. The fuzzer must find the string "FUZZER". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (Size > 4 && Data[4] == 'E') bits |= 16; + if (Size > 5 && Data[5] == 'R') bits |= 32; + if (bits == 63) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp b/gnu/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp new file mode 100644 index 00000000000..b33e0c96145 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -0,0 +1,402 @@ +#include "FuzzerInternal.h" +#include "gtest/gtest.h" +#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) { + abort(); +} + +TEST(Fuzzer, CrossOver) { + FuzzerRandomLibc Rand(0); + MutationDispatcher MD(Rand); + Unit A({0, 1, 2}), B({5, 6, 7}); + Unit C; + Unit Expected[] = { + { 0 }, + { 0, 1 }, + { 0, 5 }, + { 0, 1, 2 }, + { 0, 1, 5 }, + { 0, 5, 1 }, + { 0, 5, 6 }, + { 0, 1, 2, 5 }, + { 0, 1, 5, 2 }, + { 0, 1, 5, 6 }, + { 0, 5, 1, 2 }, + { 0, 5, 1, 6 }, + { 0, 5, 6, 1 }, + { 0, 5, 6, 7 }, + { 0, 1, 2, 5, 6 }, + { 0, 1, 5, 2, 6 }, + { 0, 1, 5, 6, 2 }, + { 0, 1, 5, 6, 7 }, + { 0, 5, 1, 2, 6 }, + { 0, 5, 1, 6, 2 }, + { 0, 5, 1, 6, 7 }, + { 0, 5, 6, 1, 2 }, + { 0, 5, 6, 1, 7 }, + { 0, 5, 6, 7, 1 }, + { 0, 1, 2, 5, 6, 7 }, + { 0, 1, 5, 2, 6, 7 }, + { 0, 1, 5, 6, 2, 7 }, + { 0, 1, 5, 6, 7, 2 }, + { 0, 5, 1, 2, 6, 7 }, + { 0, 5, 1, 6, 2, 7 }, + { 0, 5, 1, 6, 7, 2 }, + { 0, 5, 6, 1, 2, 7 }, + { 0, 5, 6, 1, 7, 2 }, + { 0, 5, 6, 7, 1, 2 } + }; + for (size_t Len = 1; Len < 8; Len++) { + std::set<Unit> FoundUnits, ExpectedUnitsWitThisLength; + for (int Iter = 0; Iter < 3000; Iter++) { + C.resize(Len); + size_t NewSize = MD.CrossOver(A.data(), A.size(), B.data(), B.size(), + C.data(), C.size()); + C.resize(NewSize); + FoundUnits.insert(C); + } + for (const Unit &U : Expected) + if (U.size() <= Len) + ExpectedUnitsWitThisLength.insert(U); + EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits); + } +} + +TEST(Fuzzer, Hash) { + uint8_t A[] = {'a', 'b', 'c'}; + fuzzer::Unit U(A, A + sizeof(A)); + EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U)); + U.push_back('d'); + EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U)); +} + +typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, + size_t MaxSize); + +void TestEraseByte(Mutator M, int NumIter) { + 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}; + uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77}; + 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); + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, sizeof(T), sizeof(T)); + if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4; + if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5; + if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6; + if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, EraseByte1) { + TestEraseByte(&MutationDispatcher::Mutate_EraseByte, 100); +} +TEST(FuzzerMutate, EraseByte2) { + TestEraseByte(&MutationDispatcher::Mutate, 1000); +} + +void TestInsertByte(Mutator M, int NumIter) { + FuzzerRandomLibc 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}; + uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66}; + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66}; + uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (MD.*M)(T, 7, 8); + if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, InsertByte1) { + TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15); +} +TEST(FuzzerMutate, InsertByte2) { + TestInsertByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestChangeByte(Mutator M, int NumIter) { + FuzzerRandomLibc 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}; + uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeByte1) { + TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15); +} +TEST(FuzzerMutate, ChangeByte2) { + TestChangeByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestChangeBit(Mutator M, int NumIter) { + FuzzerRandomLibc 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}; + uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBit1) { + TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16); +} +TEST(FuzzerMutate, ChangeBit2) { + TestChangeBit(&MutationDispatcher::Mutate, 1 << 18); +} + +void TestShuffleBytes(Mutator M, int NumIter) { + FuzzerRandomLibc 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}; + uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33}; + uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (MD.*M)(T, 7, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ShuffleBytes1) { + TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 15); +} +TEST(FuzzerMutate, ShuffleBytes2) { + TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 19); +} + +void TestAddWordFromDictionary(Mutator M, int NumIter) { + FuzzerRandomLibc 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))); + 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}; + uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22}; + uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22}; + uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF}; + uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22}; + uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22}; + uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22}; + size_t NewSize = (MD.*M)(T, 3, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4; + if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5; + if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6; + if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, AddWordFromDictionary1) { + TestAddWordFromDictionary( + &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15); +} + +TEST(FuzzerMutate, AddWordFromDictionary2) { + TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15); +} + +void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) { + FuzzerRandomLibc Rand(0); + MutationDispatcher MD(Rand); + uint8_t Word[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF}; + size_t PosHint = 7777; + MD.AddWordToAutoDictionary(Unit(Word, Word + sizeof(Word)), 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))) + FoundMask = 1; + } + EXPECT_EQ(FoundMask, 1); +} + +TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) { + TestAddWordFromDictionaryWithHint( + &MutationDispatcher::Mutate_AddWordFromAutoDictionary, 1 << 5); +} + +TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) { + TestAddWordFromDictionaryWithHint(&MutationDispatcher::Mutate, 1 << 10); +} + +void TestChangeASCIIInteger(Mutator M, int NumIter) { + FuzzerRandomLibc 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'}; + uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'}; + uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'}; + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'}; + size_t NewSize = (MD.*M)(T, 8, 8); + /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + else if (NewSize == 8) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ChangeASCIIInteger1) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger, + 1 << 15); +} + +TEST(FuzzerMutate, ChangeASCIIInteger2) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15); +} + + +TEST(FuzzerDictionary, ParseOneDictionaryEntry) { + Unit U; + EXPECT_FALSE(ParseOneDictionaryEntry("", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U)); + EXPECT_EQ(U, Unit({'a'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U)); + EXPECT_EQ(U, Unit({'\\'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U)); + EXPECT_EQ(U, Unit({0xAB})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U)); + EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U)); + EXPECT_EQ(U, Unit({'#'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U)); + EXPECT_EQ(U, Unit({'"'})); +} + +TEST(FuzzerDictionary, ParseDictionaryFile) { + std::vector<Unit> Units; + EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units)); + EXPECT_FALSE(ParseDictionaryFile("", &Units)); + EXPECT_TRUE(ParseDictionaryFile("\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units)); + EXPECT_EQ(Units, std::vector<Unit>({Unit({'a', 'a'})})); + EXPECT_TRUE( + ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units)); + EXPECT_EQ(Units, + std::vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); +} + +TEST(FuzzerUtil, Base64) { + EXPECT_EQ("", Base64({})); + EXPECT_EQ("YQ==", Base64({'a'})); + EXPECT_EQ("eA==", Base64({'x'})); + EXPECT_EQ("YWI=", Base64({'a', 'b'})); + EXPECT_EQ("eHk=", Base64({'x', 'y'})); + EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'})); + EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'})); + EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'})); + EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); + EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); +} diff --git a/gnu/llvm/lib/Fuzzer/test/MemcmpTest.cpp b/gnu/llvm/lib/Fuzzer/test/MemcmpTest.cpp new file mode 100644 index 00000000000..c19c95717bb --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/MemcmpTest.cpp @@ -0,0 +1,28 @@ +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) { + if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) { + if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) { + if (Size >= 16 && memcmp(Data + 14, "KLM", 3) == 0) { + if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){ + fprintf(stderr, "BINGO %zd\n", Size); + for (size_t i = 0; i < Size; i++) { + uint8_t C = Data[i]; + if (C >= 32 && C < 127) + fprintf(stderr, "%c", C); + } + fprintf(stderr, "\n"); + exit(1); + } + } + } + } + } + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/NullDerefTest.cpp b/gnu/llvm/lib/Fuzzer/test/NullDerefTest.cpp new file mode 100644 index 00000000000..200c56ccbbc --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/NullDerefTest.cpp @@ -0,0 +1,23 @@ +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; +static volatile int *Null = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "Found the target, dereferencing NULL\n"; + *Null = 1; + } + } + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/SimpleCmpTest.cpp b/gnu/llvm/lib/Fuzzer/test/SimpleCmpTest.cpp new file mode 100644 index 00000000000..8568c737efb --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/SimpleCmpTest.cpp @@ -0,0 +1,31 @@ +// Simple test for a fuzzer. The fuzzer must find several narrow ranges. +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) return 0; + uint64_t x = 0; + int64_t y = 0; + int z = 0; + unsigned short a = 0; + memcpy(&x, Data, 8); + memcpy(&y, Data + Size - 8, 8); + memcpy(&z, Data + Size / 2, sizeof(z)); + memcpy(&a, Data + Size / 2 + 4, sizeof(a)); + + if (x > 1234567890 && + x < 1234567895 && + y >= 987654321 && + y <= 987654325 && + z < -10000 && + z >= -10005 && + z != -10003 && + a == 4242) { + fprintf(stderr, "BINGO; Found the target: size %zd (%zd, %zd, %d, %d), exiting.\n", + Size, x, y, z, a); + exit(1); + } + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/SimpleDictionaryTest.cpp b/gnu/llvm/lib/Fuzzer/test/SimpleDictionaryTest.cpp new file mode 100644 index 00000000000..b9cb2f0270a --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/SimpleDictionaryTest.cpp @@ -0,0 +1,26 @@ +// Simple test for a fuzzer. +// The fuzzer must find a string based on dictionary words: +// "Elvis" +// "Presley" +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +static volatile int Zero = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *Expected = "ElvisPresley"; + if (Size < strlen(Expected)) return 0; + size_t Match = 0; + for (size_t i = 0; Expected[i]; i++) + if (Expected[i] + Zero == Data[i]) + Match++; + if (Match == strlen(Expected)) { + std::cout << "BINGO; Found the target, exiting\n"; + exit(1); + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/SimpleHashTest.cpp b/gnu/llvm/lib/Fuzzer/test/SimpleHashTest.cpp new file mode 100644 index 00000000000..5bab3fa7f64 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/SimpleHashTest.cpp @@ -0,0 +1,37 @@ +// This test computes a checksum of the data (all but the last 4 bytes), +// and then compares the last 4 bytes with the computed value. +// A fuzzer with cmp traces is expected to defeat this check. +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +// A modified jenkins_one_at_a_time_hash initialized by non-zero, +// so that simple_hash(0) != 0. See also +// https://en.wikipedia.org/wiki/Jenkins_hash_function +static uint32_t simple_hash(const uint8_t *Data, size_t Size) { + uint32_t Hash = 0x12039854; + for (uint32_t i = 0; i < Size; i++) { + Hash += Data[i]; + Hash += (Hash << 10); + Hash ^= (Hash >> 6); + } + Hash += (Hash << 3); + Hash ^= (Hash >> 11); + Hash += (Hash << 15); + return Hash; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) + return 0; + + uint32_t Hash = simple_hash(&Data[0], Size - 4); + uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0]; + if (Hash != Want) + return 0; + fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash, + (unsigned int)Want); + exit(1); + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/SimpleTest.cpp b/gnu/llvm/lib/Fuzzer/test/SimpleTest.cpp new file mode 100644 index 00000000000..04225a889f5 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/SimpleTest.cpp @@ -0,0 +1,24 @@ +// 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 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(0); + } + } + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/StrcmpTest.cpp b/gnu/llvm/lib/Fuzzer/test/StrcmpTest.cpp new file mode 100644 index 00000000000..835819ae2f4 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/StrcmpTest.cpp @@ -0,0 +1,29 @@ +// Break through a series of strcmp. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cassert> + +bool Eq(const uint8_t *Data, size_t Size, const char *Str) { + char Buff[1024]; + size_t Len = strlen(Str); + if (Size < Len) return false; + if (Len >= sizeof(Buff)) return false; + memcpy(Buff, (char*)Data, Len); + Buff[Len] = 0; + int res = strcmp(Buff, Str); + return res == 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Eq(Data, Size, "AAA") && + Size >= 3 && Eq(Data + 3, Size - 3, "BBBB") && + Size >= 7 && Eq(Data + 7, Size - 7, "CCCCCC") && + Size >= 14 && Data[13] == 42 + ) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/StrncmpTest.cpp b/gnu/llvm/lib/Fuzzer/test/StrncmpTest.cpp new file mode 100644 index 00000000000..55344d75e0b --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/StrncmpTest.cpp @@ -0,0 +1,25 @@ +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + char *S = (char*)Data; + if (Size >= 8 && strncmp(S, "123", 8)) + sink = 1; + if (Size >= 8 && strncmp(S, "01234567", 8) == 0) { + if (Size >= 12 && strncmp(S + 8, "ABCD", 4) == 0) { + if (Size >= 14 && strncmp(S + 12, "XY", 2) == 0) { + if (Size >= 16 && strncmp(S + 14, "KLM", 3) == 0) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + } + } + } + return 0; +} diff --git a/gnu/llvm/lib/Fuzzer/test/SwitchTest.cpp b/gnu/llvm/lib/Fuzzer/test/SwitchTest.cpp new file mode 100644 index 00000000000..5de7fff7452 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/SwitchTest.cpp @@ -0,0 +1,55 @@ +// Simple test for a fuzzer. The fuzzer must find the interesting switch value. +#include <cstdint> +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <cstddef> + +static volatile int Sink; + +template<class T> +bool Switch(const uint8_t *Data, size_t Size) { + T X; + if (Size < sizeof(X)) return false; + memcpy(&X, Data, sizeof(X)); + switch (X) { + case 1: Sink = __LINE__; break; + case 101: Sink = __LINE__; break; + case 1001: Sink = __LINE__; break; + case 10001: Sink = __LINE__; break; + case 100001: Sink = __LINE__; break; + case 1000001: Sink = __LINE__; break; + case 10000001: Sink = __LINE__; break; + case 100000001: return true; + } + return false; +} + +bool ShortSwitch(const uint8_t *Data, size_t Size) { + short X; + if (Size < sizeof(short)) return false; + memcpy(&X, Data, sizeof(short)); + switch(X) { + case 42: Sink = __LINE__; break; + case 402: Sink = __LINE__; break; + case 4002: Sink = __LINE__; break; + case 5002: Sink = __LINE__; break; + case 7002: Sink = __LINE__; break; + case 9002: Sink = __LINE__; break; + case 14002: Sink = __LINE__; break; + case 21402: return true; + } + return false; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 4 && Switch<int>(Data, Size) && + Size >= 12 && Switch<uint64_t>(Data + 4, Size - 4) && + Size >= 14 && ShortSwitch(Data + 12, 2) + ) { + fprintf(stderr, "BINGO; Found the target, exiting\n"); + exit(1); + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/ThreadedTest.cpp b/gnu/llvm/lib/Fuzzer/test/ThreadedTest.cpp new file mode 100644 index 00000000000..7aa114a41f3 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/ThreadedTest.cpp @@ -0,0 +1,23 @@ +// Threaded test for a fuzzer. The fuzzer should not crash. +#include <assert.h> +#include <cstdint> +#include <cstddef> +#include <cstring> +#include <thread> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + assert(Data); + auto C = [&] { + size_t Res = 0; + for (size_t i = 0; i < Size / 2; i++) + Res += memcmp(Data, Data + Size / 2, 4); + return Res; + }; + std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), + std::thread(C), std::thread(C), std::thread(C)}; + for (auto &X : T) + X.join(); + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/TimeoutTest.cpp b/gnu/llvm/lib/Fuzzer/test/TimeoutTest.cpp new file mode 100644 index 00000000000..71790ded95a --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/TimeoutTest.cpp @@ -0,0 +1,23 @@ +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + Sink = 2; + while (Sink) + ; + } + } + } + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/UninstrumentedTest.cpp b/gnu/llvm/lib/Fuzzer/test/UninstrumentedTest.cpp new file mode 100644 index 00000000000..c1730198d83 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/UninstrumentedTest.cpp @@ -0,0 +1,8 @@ +// This test should not be instrumented. +#include <cstdint> +#include <cstddef> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} + diff --git a/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp b/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp new file mode 100644 index 00000000000..59f83b57bfa --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp @@ -0,0 +1,51 @@ +// 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/gnu/llvm/lib/Fuzzer/test/dfsan/CMakeLists.txt b/gnu/llvm/lib/Fuzzer/test/dfsan/CMakeLists.txt new file mode 100644 index 00000000000..2b49831fcdb --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/dfsan/CMakeLists.txt @@ -0,0 +1,14 @@ +# These tests depend on both coverage and dfsan instrumentation. + +set(CMAKE_CXX_FLAGS_RELEASE + "${LIBFUZZER_FLAGS_BASE} -O0 -fno-sanitize=all -fsanitize=dataflow") + +foreach(Test ${DFSanTests}) + add_executable(LLVMFuzzer-${Test}-DFSan + ../${Test}.cpp + ) + target_link_libraries(LLVMFuzzer-${Test}-DFSan + LLVMFuzzer + ) +endforeach() + diff --git a/gnu/llvm/lib/Fuzzer/test/dict1.txt b/gnu/llvm/lib/Fuzzer/test/dict1.txt new file mode 100644 index 00000000000..520d0cc7b7d --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/dict1.txt @@ -0,0 +1,4 @@ +# Dictionary for SimpleDictionaryTest + +a="Elvis" +b="Presley" diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-dfsan.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-dfsan.test new file mode 100644 index 00000000000..567086ed65a --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-dfsan.test @@ -0,0 +1,23 @@ +CHECK1: BINGO +CHECK2: BINGO +CHECK3: BINGO +CHECK4: BINGO + +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: 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: 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 +RUN: LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanMemcmpCallback + +RUN: not LLVMFuzzer-StrcmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK3 +RUN: LLVMFuzzer-StrcmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanMemcmpCallback + +RUN: not LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK4 +RUN: LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanSwitchCallback diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-dict.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-dict.test new file mode 100644 index 00000000000..dec002f6a37 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-dict.test @@ -0,0 +1,6 @@ +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s +RUN: LLVMFuzzer-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-drill.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-drill.test new file mode 100644 index 00000000000..b2fc1fecd27 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-drill.test @@ -0,0 +1,8 @@ +CHECK: BINGO +RUN: rm -rf FourIndependentBranchesTestCORPUS +RUN: mkdir FourIndependentBranchesTestCORPUS +RUN: LLVMFuzzer-FourIndependentBranchesTest -seed=1 -runs=100000 FourIndependentBranchesTestCORPUS +RUN: not LLVMFuzzer-FourIndependentBranchesTest -runs=100000 -drill=1 -jobs=200 FourIndependentBranchesTestCORPUS 2>&1 | FileCheck %s +RUN: rm -rf FourIndependentBranchesTestCORPUS + + diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-threaded.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-threaded.test new file mode 100644 index 00000000000..c58a33456cc --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-threaded.test @@ -0,0 +1,7 @@ +CHECK: Done 1000 runs in + +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s + diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-timeout.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-timeout.test new file mode 100644 index 00000000000..c3a9e8a3a9e --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-timeout.test @@ -0,0 +1,13 @@ +RUN: not LLVMFuzzer-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest +TimeoutTest: ALARM: working on the last Unit for +TimeoutTest: Test unit written to ./timeout- +TimeoutTest: == ERROR: libFuzzer: timeout after +TimeoutTest: #0 +TimeoutTest: #1 +TimeoutTest: #2 +TimeoutTest: SUMMARY: libFuzzer: timeout + +RUN: not 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 +SingleInputTimeoutTest-NOT: Test unit written to ./timeout- + diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer-traces.test b/gnu/llvm/lib/Fuzzer/test/fuzzer-traces.test new file mode 100644 index 00000000000..3b8639b8e94 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer-traces.test @@ -0,0 +1,20 @@ +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-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 diff --git a/gnu/llvm/lib/Fuzzer/test/fuzzer.test b/gnu/llvm/lib/Fuzzer/test/fuzzer.test new file mode 100644 index 00000000000..c63014f59d6 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/fuzzer.test @@ -0,0 +1,36 @@ +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- + +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 +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 + +#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 + +RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s +# 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 + diff --git a/gnu/llvm/lib/Fuzzer/test/hi.txt b/gnu/llvm/lib/Fuzzer/test/hi.txt new file mode 100644 index 00000000000..2f9031f0ec7 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/hi.txt @@ -0,0 +1 @@ +Hi!
\ No newline at end of file diff --git a/gnu/llvm/lib/Fuzzer/test/lit.cfg b/gnu/llvm/lib/Fuzzer/test/lit.cfg new file mode 100644 index 00000000000..2140a97668b --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/lit.cfg @@ -0,0 +1,15 @@ +import lit.formats + +config.name = "LLVMFuzzer" +config.test_format = lit.formats.ShTest(True) +config.suffixes = ['.test'] +config.test_source_root = os.path.dirname(__file__) + +# Tweak PATH to include llvm tools dir and current exec dir. +llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) +if (not llvm_tools_dir) or (not os.path.exists(llvm_tools_dir)): + lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % llvm_tools_dir) +path = os.path.pathsep.join((llvm_tools_dir, config.test_exec_root, + config.environment['PATH'])) +config.environment['PATH'] = path + diff --git a/gnu/llvm/lib/Fuzzer/test/lit.site.cfg.in b/gnu/llvm/lib/Fuzzer/test/lit.site.cfg.in new file mode 100644 index 00000000000..e520db8e881 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/lit.site.cfg.in @@ -0,0 +1,3 @@ +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/gnu/llvm/lib/Fuzzer/test/merge.test b/gnu/llvm/lib/Fuzzer/test/merge.test new file mode 100644 index 00000000000..57ecc141bbf --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/merge.test @@ -0,0 +1,29 @@ +CHECK: BINGO + +RUN: rm -rf %tmp/T1 %tmp/T2 +RUN: mkdir -p %tmp/T1 %tmp/T2 +RUN: echo F..... > %tmp/T1/1 +RUN: echo .U.... > %tmp/T1/2 +RUN: echo ..Z... > %tmp/T1/3 + +# 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 + +RUN: echo ...Z.. > %tmp/T2/1 +RUN: echo ....E. > %tmp/T2/2 +RUN: echo .....R > %tmp/T2/3 +RUN: echo F..... > %tmp/T2/a +RUN: echo .U.... > %tmp/T2/b +RUN: echo ..Z... > %tmp/T2/c + +# T1 has 3 elements, T2 has 6 elements, only 3 are new. +RUN: 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 + +# 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 diff --git a/gnu/llvm/lib/Fuzzer/test/trace-bb/CMakeLists.txt b/gnu/llvm/lib/Fuzzer/test/trace-bb/CMakeLists.txt new file mode 100644 index 00000000000..99af019565b --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/trace-bb/CMakeLists.txt @@ -0,0 +1,14 @@ +# These tests are not instrumented with coverage. + +set(CMAKE_CXX_FLAGS_RELEASE + "${LIBFUZZER_FLAGS_BASE} -fsanitize-coverage=edge,trace-bb") + +foreach(Test ${TraceBBTests}) + add_executable(LLVMFuzzer-${Test}-TraceBB + ../${Test}.cpp + ) + target_link_libraries(LLVMFuzzer-${Test}-TraceBB + LLVMFuzzer + ) +endforeach() + diff --git a/gnu/llvm/lib/Fuzzer/test/uninstrumented/CMakeLists.txt b/gnu/llvm/lib/Fuzzer/test/uninstrumented/CMakeLists.txt new file mode 100644 index 00000000000..443ba3716f6 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/uninstrumented/CMakeLists.txt @@ -0,0 +1,14 @@ +# These tests are not instrumented with coverage. + +set(CMAKE_CXX_FLAGS_RELEASE + "${LIBFUZZER_FLAGS_BASE} -O0 -fno-sanitize=all") + +foreach(Test ${UninstrumentedTests}) + add_executable(LLVMFuzzer-${Test}-Uninstrumented + ../${Test}.cpp + ) + target_link_libraries(LLVMFuzzer-${Test}-Uninstrumented + LLVMFuzzer + ) +endforeach() + diff --git a/gnu/llvm/lib/Fuzzer/test/unit/lit.cfg b/gnu/llvm/lib/Fuzzer/test/unit/lit.cfg new file mode 100644 index 00000000000..0cc31939c55 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/unit/lit.cfg @@ -0,0 +1,7 @@ +import lit.formats + +config.name = "LLVMFuzzer-Unittest" +print config.test_exec_root +config.test_format = lit.formats.GoogleTest(".", "Unittest") +config.suffixes = [] +config.test_source_root = config.test_exec_root diff --git a/gnu/llvm/lib/Fuzzer/test/unit/lit.site.cfg.in b/gnu/llvm/lib/Fuzzer/test/unit/lit.site.cfg.in new file mode 100644 index 00000000000..114daf474b6 --- /dev/null +++ b/gnu/llvm/lib/Fuzzer/test/unit/lit.site.cfg.in @@ -0,0 +1,2 @@ +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/unit/lit.cfg") |
