Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerCommand.h
35262 views
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
// FuzzerCommand represents a command to run in a subprocess. It allows callers
9
// to manage command line arguments and output and error streams.
10
//===----------------------------------------------------------------------===//
11
12
#ifndef LLVM_FUZZER_COMMAND_H
13
#define LLVM_FUZZER_COMMAND_H
14
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
24
namespace fuzzer {
25
26
class Command final {
27
public:
28
// This command line flag is used to indicate that the remaining command line
29
// is immutable, meaning this flag effectively marks the end of the mutable
30
// 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 to
54
// "-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 after
61
// "-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 end
65
// 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 end
71
// 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 any
77
// 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 string
93
// if the flag isn't present. Ignores any occurrences after
94
// "-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 will
140
// 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
155
private:
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 fuzzer
178
179
#endif // LLVM_FUZZER_COMMAND_H
180
181