brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · 718d7e9 Raw
180 lines · c
1//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// FuzzerCommand represents a command to run in a subprocess.  It allows callers9// to manage command line arguments and output and error streams.10//===----------------------------------------------------------------------===//11 12#ifndef LLVM_FUZZER_COMMAND_H13#define LLVM_FUZZER_COMMAND_H14 15#include "FuzzerDefs.h"16#include "FuzzerIO.h"17 18#include <algorithm>19#include <sstream>20#include <string>21#include <vector>22#include <thread>23 24namespace fuzzer {25 26class Command final {27public:28  // This command line flag is used to indicate that the remaining command line29  // is immutable, meaning this flag effectively marks the end of the mutable30  // argument list.31  static inline const char *ignoreRemainingArgs() {32    return "-ignore_remaining_args=1";33  }34 35  Command() : CombinedOutAndErr(false) {}36 37  explicit Command(const std::vector<std::string> &ArgsToAdd)38      : Args(ArgsToAdd), CombinedOutAndErr(false) {}39 40  explicit Command(const Command &Other)41      : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr),42        OutputFile(Other.OutputFile) {}43 44  Command &operator=(const Command &Other) {45    Args = Other.Args;46    CombinedOutAndErr = Other.CombinedOutAndErr;47    OutputFile = Other.OutputFile;48    return *this;49  }50 51  ~Command() {}52 53  // Returns true if the given Arg is present in Args.  Only checks up to54  // "-ignore_remaining_args=1".55  bool hasArgument(const std::string &Arg) const {56    auto i = endMutableArgs();57    return std::find(Args.begin(), i, Arg) != i;58  }59 60  // Gets all of the current command line arguments, **including** those after61  // "-ignore-remaining-args=1".62  const std::vector<std::string> &getArguments() const { return Args; }63 64  // Adds the given argument before "-ignore_remaining_args=1", or at the end65  // if that flag isn't present.66  void addArgument(const std::string &Arg) {67    Args.insert(endMutableArgs(), Arg);68  }69 70  // Adds all given arguments before "-ignore_remaining_args=1", or at the end71  // if that flag isn't present.72  void addArguments(const std::vector<std::string> &ArgsToAdd) {73    Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end());74  }75 76  // Removes the given argument from the command argument list.  Ignores any77  // occurrences after "-ignore_remaining_args=1", if present.78  void removeArgument(const std::string &Arg) {79    auto i = endMutableArgs();80    Args.erase(std::remove(Args.begin(), i, Arg), i);81  }82 83  // Like hasArgument, but checks for "-[Flag]=...".84  bool hasFlag(const std::string &Flag) const {85    std::string Arg("-" + Flag + "=");86    auto IsMatch = [&](const std::string &Other) {87      return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;88    };89    return std::any_of(Args.begin(), endMutableArgs(), IsMatch);90  }91 92  // Returns the value of the first instance of a given flag, or an empty string93  // if the flag isn't present.  Ignores any occurrences after94  // "-ignore_remaining_args=1", if present.95  std::string getFlagValue(const std::string &Flag) const {96    std::string Arg("-" + Flag + "=");97    auto IsMatch = [&](const std::string &Other) {98      return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;99    };100    auto i = endMutableArgs();101    auto j = std::find_if(Args.begin(), i, IsMatch);102    std::string result;103    if (j != i) {104      result = j->substr(Arg.length());105    }106    return result;107  }108 109  // Like AddArgument, but adds "-[Flag]=[Value]".110  void addFlag(const std::string &Flag, const std::string &Value) {111    addArgument("-" + Flag + "=" + Value);112  }113 114  // Like RemoveArgument, but removes "-[Flag]=...".115  void removeFlag(const std::string &Flag) {116    std::string Arg("-" + Flag + "=");117    auto IsMatch = [&](const std::string &Other) {118      return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;119    };120    auto i = endMutableArgs();121    Args.erase(std::remove_if(Args.begin(), i, IsMatch), i);122  }123 124  // Returns whether the command's stdout is being written to an output file.125  bool hasOutputFile() const { return !OutputFile.empty(); }126 127  // Returns the currently set output file.128  const std::string &getOutputFile() const { return OutputFile; }129 130  // Configures the command to redirect its output to the name file.131  void setOutputFile(const std::string &FileName) { OutputFile = FileName; }132 133  // Returns whether the command's stderr is redirected to stdout.134  bool isOutAndErrCombined() const { return CombinedOutAndErr; }135 136  // Sets whether to redirect the command's stderr to its stdout.137  void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; }138 139  // Returns a string representation of the command.  On many systems this will140  // be the equivalent command line.141  std::string toString() const {142    std::stringstream SS;143    for (const auto &arg : getArguments())144      SS << arg << " ";145    if (hasOutputFile())146      SS << ">" << getOutputFile() << " ";147    if (isOutAndErrCombined())148      SS << "2>&1 ";149    std::string result = SS.str();150    if (!result.empty())151      result = result.substr(0, result.length() - 1);152    return result;153  }154 155private:156  Command(Command &&Other) = delete;157  Command &operator=(Command &&Other) = delete;158 159  std::vector<std::string>::iterator endMutableArgs() {160    return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());161  }162 163  std::vector<std::string>::const_iterator endMutableArgs() const {164    return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());165  }166 167  // The command arguments.  Args[0] is the command name.168  std::vector<std::string> Args;169 170  // True indicates stderr is redirected to stdout.171  bool CombinedOutAndErr;172 173  // If not empty, stdout is redirected to the named file.174  std::string OutputFile;175};176 177} // namespace fuzzer178 179#endif // LLVM_FUZZER_COMMAND_H180