From 117976818e1561b52f61800db2120e518753a3d6 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 25 Oct 2016 22:30:34 +0000 Subject: [PATCH] [libFuzzer] add StandaloneFuzzTargetMain.c and a test for it llvm-svn: 285135 --- .../Fuzzer/standalone/StandaloneFuzzTargetMain.c | 41 ++++++++++++++++++++++ llvm/lib/Fuzzer/test/CMakeLists.txt | 12 +++++++ llvm/lib/Fuzzer/test/InitializeTest.cpp | 6 ++-- llvm/lib/Fuzzer/test/fuzzer.test | 2 +- llvm/lib/Fuzzer/test/standalone.test | 4 +++ 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 llvm/lib/Fuzzer/standalone/StandaloneFuzzTargetMain.c create mode 100644 llvm/lib/Fuzzer/test/standalone.test diff --git a/llvm/lib/Fuzzer/standalone/StandaloneFuzzTargetMain.c b/llvm/lib/Fuzzer/standalone/StandaloneFuzzTargetMain.c new file mode 100644 index 0000000..0d76ea4 --- /dev/null +++ b/llvm/lib/Fuzzer/standalone/StandaloneFuzzTargetMain.c @@ -0,0 +1,41 @@ +/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This main() function can be linked to a fuzz target (i.e. a library +// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) +// instead of libFuzzer. This main() function will not perform any fuzzing +// but will simply feed all input files one by one to the fuzz target. +// +// Use this file to provide reproducers for bugs when linking against libFuzzer +// or other fuzzing engine is undesirable. +//===----------------------------------------------------------------------===*/ +#include +#include +#include + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); +int main(int argc, char **argv) { + fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + for (int i = 1; i < argc; i++) { + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char*)malloc(len); + size_t n_read = fread(buf, 1, len, f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + } +} diff --git a/llvm/lib/Fuzzer/test/CMakeLists.txt b/llvm/lib/Fuzzer/test/CMakeLists.txt index d869bfa..091b388 100644 --- a/llvm/lib/Fuzzer/test/CMakeLists.txt +++ b/llvm/lib/Fuzzer/test/CMakeLists.txt @@ -135,6 +135,11 @@ add_executable(LLVMFuzzer-Unittest FuzzerFnAdapterUnittest.cpp ) +add_executable(LLVMFuzzer-StandaloneInitializeTest + InitializeTest.cpp + ../standalone/StandaloneFuzzTargetMain.c + ) + target_link_libraries(LLVMFuzzer-Unittest gtest gtest_main @@ -150,6 +155,13 @@ set_target_properties(LLVMFuzzer-Unittest PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) + +set(TestBinaries ${TestBinaries} LLVMFuzzer-StandaloneInitializeTest) +set_target_properties(LLVMFuzzer-StandaloneInitializeTest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}" +) + ############################################################################### # Additional tests ############################################################################### diff --git a/llvm/lib/Fuzzer/test/InitializeTest.cpp b/llvm/lib/Fuzzer/test/InitializeTest.cpp index f8b6367..0d6a0fd 100644 --- a/llvm/lib/Fuzzer/test/InitializeTest.cpp +++ b/llvm/lib/Fuzzer/test/InitializeTest.cpp @@ -14,12 +14,14 @@ static char *argv0; extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { assert(*argc > 0); argv0 = **argv; + fprintf(stderr, "LLVMFuzzerInitialize: %s\n", argv0); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (strncmp(reinterpret_cast(Data), argv0, Size)) { - fprintf(stderr, "BINGO\n"); + if (Size == strlen(argv0) && + !strncmp(reinterpret_cast(Data), argv0, Size)) { + fprintf(stderr, "BINGO %s\n", argv0); exit(1); } return 0; diff --git a/llvm/lib/Fuzzer/test/fuzzer.test b/llvm/lib/Fuzzer/test/fuzzer.test index df69498..1838b30 100644 --- a/llvm/lib/Fuzzer/test/fuzzer.test +++ b/llvm/lib/Fuzzer/test/fuzzer.test @@ -47,7 +47,7 @@ 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 +RUN: not LLVMFuzzer-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO DSO: INFO: Loaded 3 modules diff --git a/llvm/lib/Fuzzer/test/standalone.test b/llvm/lib/Fuzzer/test/standalone.test new file mode 100644 index 0000000..3097b3f --- /dev/null +++ b/llvm/lib/Fuzzer/test/standalone.test @@ -0,0 +1,4 @@ +RUN: LLVMFuzzer-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s +CHECK: StandaloneFuzzTargetMain: running 2 inputs +CHECK: Done: {{.*}}hi.txt: (3 bytes) +CHECK: Done: {{.*}}dict1.txt: (61 bytes) -- 2.7.4