xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-as-fuzzer/llvm-as-fuzzer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- llvm-as-fuzzer.cpp - Fuzzer for llvm-as using lib/Fuzzer ----------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // Build tool to fuzz the LLVM assembler (llvm-as) using
1009467b48Spatrick // lib/Fuzzer. The main reason for using this tool is that it is much
1109467b48Spatrick // faster than using afl-fuzz, since it is run in-process.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1509467b48Spatrick #include "llvm/ADT/StringRef.h"
1609467b48Spatrick #include "llvm/AsmParser/Parser.h"
1709467b48Spatrick #include "llvm/IR/LLVMContext.h"
1809467b48Spatrick #include "llvm/IR/Module.h"
1909467b48Spatrick #include "llvm/IR/Verifier.h"
2009467b48Spatrick #include "llvm/Support/ErrorHandling.h"
2109467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
2209467b48Spatrick #include "llvm/Support/SourceMgr.h"
2309467b48Spatrick #include "llvm/Support/raw_ostream.h"
2409467b48Spatrick 
2509467b48Spatrick #include <csetjmp>
2609467b48Spatrick 
2709467b48Spatrick using namespace llvm;
2809467b48Spatrick 
2909467b48Spatrick static jmp_buf JmpBuf;
3009467b48Spatrick 
3109467b48Spatrick namespace {
3209467b48Spatrick 
MyFatalErrorHandler(void * user_data,const char * reason,bool gen_crash_diag)33*d415bd75Srobert void MyFatalErrorHandler(void *user_data, const char *reason,
3409467b48Spatrick                          bool gen_crash_diag) {
3509467b48Spatrick   // Don't bother printing reason, just return to the test function,
3609467b48Spatrick   // since a fatal error represents a successful parse (i.e. it correctly
3709467b48Spatrick   // terminated with an error message to the user).
3809467b48Spatrick   longjmp(JmpBuf, 1);
3909467b48Spatrick }
4009467b48Spatrick 
4109467b48Spatrick static bool InstalledHandler = false;
4209467b48Spatrick 
4309467b48Spatrick } // end of anonymous namespace
4409467b48Spatrick 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)4509467b48Spatrick extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
4609467b48Spatrick 
4709467b48Spatrick   // Allocate space for locals before setjmp so that memory can be collected
4809467b48Spatrick   // if parse exits prematurely (via longjmp).
4909467b48Spatrick   StringRef Input((const char *)Data, Size);
5009467b48Spatrick   // Note: We need to create a buffer to add a null terminator to the
5109467b48Spatrick   // end of the input string. The parser assumes that the string
5209467b48Spatrick   // parsed is always null terminated.
5309467b48Spatrick   std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(Input);
5409467b48Spatrick   SMDiagnostic Err;
5509467b48Spatrick   LLVMContext Context;
5609467b48Spatrick   std::unique_ptr<Module> M;
5709467b48Spatrick 
5809467b48Spatrick   if (setjmp(JmpBuf))
5909467b48Spatrick     // If reached, we have returned with non-zero status, so exit.
6009467b48Spatrick     return 0;
6109467b48Spatrick 
6209467b48Spatrick   // TODO(kschimpf) Write a main to do this initialization.
6309467b48Spatrick   if (!InstalledHandler) {
6409467b48Spatrick     llvm::install_fatal_error_handler(::MyFatalErrorHandler, nullptr);
6509467b48Spatrick     InstalledHandler = true;
6609467b48Spatrick   }
6709467b48Spatrick 
6809467b48Spatrick   M = parseAssembly(MemBuf->getMemBufferRef(), Err, Context);
6909467b48Spatrick 
7009467b48Spatrick   if (!M.get())
7109467b48Spatrick     return 0;
7209467b48Spatrick 
73097a140dSpatrick   if (verifyModule(*M.get(), &errs()))
74097a140dSpatrick     report_fatal_error("Broken module");
7509467b48Spatrick   return 0;
7609467b48Spatrick }
77