cmake_parse_arguments(ARG "" "DUMMY_MAIN" "" ${ARGN})
if( LLVM_USE_SANITIZE_COVERAGE )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
+ set(LLVM_OPTIONAL_SOURCES ${ARG_DUMMY_MAIN})
add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS})
set_target_properties(${name} PROPERTIES FOLDER "Fuzzers")
elseif( ARG_DUMMY_MAIN )
--- /dev/null
+//===-- FuzzerCLI.h - Common logic for CLIs of fuzzers ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common logic needed to implement LLVM's fuzz targets' CLIs - including LLVM
+// concepts like cl::opt and libFuzzer concepts like -ignore_remaining_args=1.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZMUTATE_FUZZER_CLI_H
+#define LLVM_FUZZMUTATE_FUZZER_CLI_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+/// Parse cl::opts from a fuzz target commandline.
+///
+/// This handles all arguments after -ignore_remaining_args=1 as cl::opts.
+void parseFuzzerCLOpts(int ArgC, char *ArgV[]);
+
+using FuzzerTestFun = int (*)(const uint8_t *Data, size_t Size);
+using FuzzerInitFun = int (*)(int *argc, char ***argv);
+
+/// Runs a fuzz target on the inputs specified on the command line.
+///
+/// Useful for testing fuzz targets without linking to libFuzzer. Finds inputs
+/// in the argument list in a libFuzzer compatible way.
+int runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
+ FuzzerInitFun Init = [](int *, char ***) { return 0; });
+
+} // end llvm namespace
+
+#endif // LLVM_FUZZMUTATE_FUZZER_CLI_H
add_llvm_library(LLVMFuzzMutate
+ FuzzerCLI.cpp
IRMutator.cpp
OpDescriptor.cpp
Operations.cpp
--- /dev/null
+//===-- FuzzerCLI.cpp -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/FuzzMutate/FuzzerCLI.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
+ std::vector<const char *> CLArgs;
+ CLArgs.push_back(ArgV[0]);
+
+ int I = 1;
+ while (I < ArgC)
+ if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
+ break;
+ while (I < ArgC)
+ CLArgs.push_back(ArgV[I++]);
+
+ cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
+}
+
+int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
+ FuzzerInitFun Init) {
+ errs() << "*** This tool was not linked to libFuzzer.\n"
+ << "*** No fuzzing will be performed.\n";
+ if (int RC = Init(&ArgC, &ArgV)) {
+ errs() << "Initialization failed\n";
+ return RC;
+ }
+
+ for (int I = 1; I < ArgC; ++I) {
+ StringRef Arg(ArgV[I]);
+ if (Arg.startswith("-")) {
+ if (Arg.equals("-ignore_remaining_args=1"))
+ break;
+ continue;
+ }
+
+ auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1,
+ /*RequiresNullTerminator=*/false);
+ if (std::error_code EC = BufOrErr.getError()) {
+ errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
+ return 1;
+ }
+ std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
+ errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
+ TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
+ Buf->getBufferSize());
+ }
+ return 0;
+}
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
+#include "llvm/FuzzMutate/FuzzerCLI.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv);
-
int main(int argc, char *argv[]) {
- errs() << "*** This tool was not linked to libFuzzer.\n"
- << "*** No fuzzing will be performed.\n";
- if (int RC = LLVMFuzzerInitialize(&argc, &argv)) {
- errs() << "Initialization failed\n";
- return RC;
- }
-
- for (int I = 1; I < argc; ++I) {
- StringRef Arg(argv[I]);
- if (Arg.startswith("-")) {
- if (Arg.equals("-ignore_remaining_args=1"))
- break;
- continue;
- }
-
- auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1,
- /*RequiresNullTerminator=*/false);
- if (std::error_code EC = BufOrErr.getError()) {
- errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
- return 1;
- }
- std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
- errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
- LLVMFuzzerTestOneInput(
- reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
- Buf->getBufferSize());
- }
+ return llvm::runFuzzerOnInputs(argc, argv, LLVMFuzzerTestOneInput,
+ LLVMFuzzerInitialize);
}
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/FuzzMutate/FuzzerCLI.h"
#include "llvm/FuzzMutate/IRMutator.h"
#include "llvm/FuzzMutate/Operations.h"
#include "llvm/FuzzMutate/Random.h"
return 0;
}
-/// Parse command line options, but ignore anything before '--'.
-static void parseCLOptsAfterDashDash(int argc, char *argv[]) {
- std::vector<const char *> CLArgs;
- CLArgs.push_back(argv[0]);
-
- int I = 1;
- while (I < argc)
- if (StringRef(argv[I++]).equals("-ignore_remaining_args=1"))
- break;
- while (I < argc)
- CLArgs.push_back(argv[I++]);
-
- cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
-}
-
static void handleLLVMFatalError(void *, const std::string &Message, bool) {
// TODO: Would it be better to call into the fuzzer internals directly?
dbgs() << "LLVM ERROR: " << Message << "\n"
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
- parseCLOptsAfterDashDash(*argc, *argv);
+ parseFuzzerCLOpts(*argc, *argv);
if (TargetTriple.empty()) {
errs() << *argv[0] << ": -mtriple must be specified\n";