Index: llvm/trunk/tools/llvm-as-fuzzer/CMakeLists.txt =================================================================== --- llvm/trunk/tools/llvm-as-fuzzer/CMakeLists.txt +++ llvm/trunk/tools/llvm-as-fuzzer/CMakeLists.txt @@ -0,0 +1,13 @@ +if( LLVM_USE_SANITIZE_COVERAGE ) + set(LLVM_LINK_COMPONENTS + AsmParser + BitWriter + Core + Support + ) + add_llvm_tool(llvm-as-fuzzer + llvm-as-fuzzer.cpp) + target_link_libraries(llvm-as-fuzzer + LLVMFuzzer + ) +endif() Index: llvm/trunk/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp =================================================================== --- llvm/trunk/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp +++ llvm/trunk/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 + +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 MemBuf = MemoryBuffer::getMemBufferCopy(Input); + SMDiagnostic Err; + LLVMContext &Context = getGlobalContext(); + std::unique_ptr 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()); +}