diff options
author | Karl Schimpf <kschimpf@google.com> | 2015-08-31 17:55:32 +0000 |
---|---|---|
committer | Karl Schimpf <kschimpf@google.com> | 2015-08-31 17:55:32 +0000 |
commit | b9c2c71d09ee49e43618901cc9803fdc637c15c9 (patch) | |
tree | d597b2eaad99175c7d7d42e66b3637313a5ba9e8 /llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp | |
parent | 86dbd923347c5946c7cee8d5e60387c39e32c758 (diff) | |
download | bcm5719-llvm-b9c2c71d09ee49e43618901cc9803fdc637c15c9.tar.gz bcm5719-llvm-b9c2c71d09ee49e43618901cc9803fdc637c15c9.zip |
Build a lib/Fuzzer version for llvm-as.
Summary:
This CL is associated with a fuzzing effort to find bugs in LLVM. The
first step is to fuzz llvm-as to find potential issues in generating
IR. Both afl-fuzz and LLVM's lib/Fuzzer are being used.
This CL introduces the executable that implements the in-process
fuzzer using LLVM's lib/Fuzzer. The motivation for using lib/Fuzzer is
based on time comparisons between afl-fuzz and lib/Fuzzer. Early
results show that per-process, the lib/Fuzzer implemenation of llvm-as
(i.e. this CL) generates over 30 times the number of mutations found
by afl-fuzz, per hour runtime. The speedup is due to the removal of
overhead of forking a process, and loading the executable into memory.
I placed this under the tools directory, since it is an executable. It
is also only conditionally built if (using cmake) the flag
LLVM_USEE_SANITIZE_COVERAGE is used, so that it isn't built by
default.
Reviewers: kcc, filcab
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D12438
llvm-svn: 246458
Diffstat (limited to 'llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp')
-rw-r--r-- | llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp b/llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp new file mode 100644 index 00000000000..47cea87cc37 --- /dev/null +++ b/llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp @@ -0,0 +1,75 @@ +//===--- fuzz-llvm-as.cpp - Fuzzer for llvm-as using lib/Fuzzer -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Build tool to fuzz the LLVM assembler (llvm-as) using +// lib/Fuzzer. The main reason for using this tool is that it is much +// faster than using afl-fuzz, since it is run in-process. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" + +#include <csetjmp> + +using namespace llvm; + +static jmp_buf JmpBuf; + +namespace { + +void MyFatalErrorHandler(void *user_data, const std::string& reason, + bool gen_crash_diag) { + // Don't bother printing reason, just return to the test function, + // since a fatal error represents a successful parse (i.e. it correctly + // terminated with an error message to the user). + longjmp(JmpBuf, 1); +} + +static bool InstalledHandler = false; + +} // end of anonymous namespace + +extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + // Allocate space for locals before setjmp so that memory can be collected + // if parse exits prematurely (via longjmp). + StringRef Input((const char *)Data, Size); + // Note: We need to create a buffer to add a null terminator to the + // end of the input string. The parser assumes that the string + // parsed is always null terminated. + std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(Input); + SMDiagnostic Err; + LLVMContext &Context = getGlobalContext(); + std::unique_ptr<Module> M; + + if (setjmp(JmpBuf)) + // If reached, we have returned with non-zero status, so exit. + return; + + // TODO(kschimpf) Write a main to do this initialization. + if (!InstalledHandler) { + llvm::install_fatal_error_handler(::MyFatalErrorHandler, nullptr); + InstalledHandler = true; + } + + M = parseAssembly(MemBuf->getMemBufferRef(), Err, Context); + + if (!M.get()) + return; + + verifyModule(*M.get()); +} |