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