1ef598759SFangrui Song //===-- llvm-as-fuzzer.cpp - Fuzzer for llvm-as using lib/Fuzzer ----------===//
2b9c2c71dSKarl Schimpf //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b9c2c71dSKarl Schimpf //
7b9c2c71dSKarl Schimpf //===----------------------------------------------------------------------===//
8b9c2c71dSKarl Schimpf //
9b9c2c71dSKarl Schimpf // Build tool to fuzz the LLVM assembler (llvm-as) using
10b9c2c71dSKarl Schimpf // lib/Fuzzer. The main reason for using this tool is that it is much
11b9c2c71dSKarl Schimpf // faster than using afl-fuzz, since it is run in-process.
12b9c2c71dSKarl Schimpf //
13b9c2c71dSKarl Schimpf //===----------------------------------------------------------------------===//
14b9c2c71dSKarl Schimpf
15b9c2c71dSKarl Schimpf #include "llvm/ADT/StringRef.h"
16b9c2c71dSKarl Schimpf #include "llvm/AsmParser/Parser.h"
17b9c2c71dSKarl Schimpf #include "llvm/IR/LLVMContext.h"
18b9c2c71dSKarl Schimpf #include "llvm/IR/Module.h"
19b9c2c71dSKarl Schimpf #include "llvm/IR/Verifier.h"
20b9c2c71dSKarl Schimpf #include "llvm/Support/ErrorHandling.h"
21b9c2c71dSKarl Schimpf #include "llvm/Support/MemoryBuffer.h"
22b9c2c71dSKarl Schimpf #include "llvm/Support/SourceMgr.h"
23ef598759SFangrui Song #include "llvm/Support/raw_ostream.h"
24b9c2c71dSKarl Schimpf
25b9c2c71dSKarl Schimpf #include <csetjmp>
26b9c2c71dSKarl Schimpf
27b9c2c71dSKarl Schimpf using namespace llvm;
28b9c2c71dSKarl Schimpf
29b9c2c71dSKarl Schimpf static jmp_buf JmpBuf;
30b9c2c71dSKarl Schimpf
31b9c2c71dSKarl Schimpf namespace {
32b9c2c71dSKarl Schimpf
MyFatalErrorHandler(void * user_data,const char * reason,bool gen_crash_diag)33*e463b697SSimon Pilgrim void MyFatalErrorHandler(void *user_data, const char *reason,
34b9c2c71dSKarl Schimpf bool gen_crash_diag) {
35b9c2c71dSKarl Schimpf // Don't bother printing reason, just return to the test function,
36b9c2c71dSKarl Schimpf // since a fatal error represents a successful parse (i.e. it correctly
37b9c2c71dSKarl Schimpf // terminated with an error message to the user).
38b9c2c71dSKarl Schimpf longjmp(JmpBuf, 1);
39b9c2c71dSKarl Schimpf }
40b9c2c71dSKarl Schimpf
41b9c2c71dSKarl Schimpf static bool InstalledHandler = false;
42b9c2c71dSKarl Schimpf
43b9c2c71dSKarl Schimpf } // end of anonymous namespace
44b9c2c71dSKarl Schimpf
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)4520bb5e71SKostya Serebryany extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
46b9c2c71dSKarl Schimpf
47b9c2c71dSKarl Schimpf // Allocate space for locals before setjmp so that memory can be collected
48b9c2c71dSKarl Schimpf // if parse exits prematurely (via longjmp).
49b9c2c71dSKarl Schimpf StringRef Input((const char *)Data, Size);
50b9c2c71dSKarl Schimpf // Note: We need to create a buffer to add a null terminator to the
51b9c2c71dSKarl Schimpf // end of the input string. The parser assumes that the string
52b9c2c71dSKarl Schimpf // parsed is always null terminated.
53b9c2c71dSKarl Schimpf std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(Input);
54b9c2c71dSKarl Schimpf SMDiagnostic Err;
5503b42e41SMehdi Amini LLVMContext Context;
56b9c2c71dSKarl Schimpf std::unique_ptr<Module> M;
57b9c2c71dSKarl Schimpf
58b9c2c71dSKarl Schimpf if (setjmp(JmpBuf))
59b9c2c71dSKarl Schimpf // If reached, we have returned with non-zero status, so exit.
6020bb5e71SKostya Serebryany return 0;
61b9c2c71dSKarl Schimpf
62b9c2c71dSKarl Schimpf // TODO(kschimpf) Write a main to do this initialization.
63b9c2c71dSKarl Schimpf if (!InstalledHandler) {
64b9c2c71dSKarl Schimpf llvm::install_fatal_error_handler(::MyFatalErrorHandler, nullptr);
65b9c2c71dSKarl Schimpf InstalledHandler = true;
66b9c2c71dSKarl Schimpf }
67b9c2c71dSKarl Schimpf
68b9c2c71dSKarl Schimpf M = parseAssembly(MemBuf->getMemBufferRef(), Err, Context);
69b9c2c71dSKarl Schimpf
70b9c2c71dSKarl Schimpf if (!M.get())
7120bb5e71SKostya Serebryany return 0;
72b9c2c71dSKarl Schimpf
73c9f63297SCraig Topper if (verifyModule(*M.get(), &errs()))
74c9f63297SCraig Topper report_fatal_error("Broken module");
7520bb5e71SKostya Serebryany return 0;
76b9c2c71dSKarl Schimpf }
77