Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: tools/ipc_fuzzer/mutate/fuzzer_main.cc

Issue 1000373004: Combine traits for IPC mutation and generation fuzzing plus other refactoring. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove a debug print Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <iostream>
6 #include <set>
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/strings/string_split.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "tools/ipc_fuzzer/message_lib/message_file.h"
13 #include "tools/ipc_fuzzer/mutate/fuzzer.h"
14 #include "tools/ipc_fuzzer/mutate/generator.h"
15 #include "tools/ipc_fuzzer/mutate/mutator.h"
16 #include "tools/ipc_fuzzer/mutate/rand_util.h"
17
18 namespace ipc_fuzzer {
19
20 namespace {
21
22 const char kCountSwitch[] = "count";
23 const char kCountSwitchHelp[] =
24 "Number of messages to generate (generator).";
25
26 const char kFrequencySwitch[] = "frequency";
27 const char kFrequencySwitchHelp[] =
28 "Probability of mutation; tweak every 1/|q| times (mutator).";
29
30 const char kFuzzerNameSwitch[] = "fuzzer-name";
31 const char kFuzzerNameSwitchHelp[] =
32 "Select generator, mutator, or no-op fuzzer. Default: generator";
33
34 const char kHelpSwitch[] = "help";
35 const char kHelpSwitchHelp[] =
36 "Show this message.";
37
38 const char kPermuteSwitch[] = "permute";
39 const char kPermuteSwitchHelp[] =
40 "Randomly shuffle the order of all messages (mutator).";
41
42 const char kTypeListSwitch[] = "type-list";
43 const char kTypeListSwitchHelp[] =
44 "Explicit list of the only message-ids to mutate (mutator).";
45
46 void usage() {
47 std::cerr << "Mutate messages from an exiting message file.\n";
48
49 std::cerr << "Usage:\n"
50 << " ipc_fuzzer"
51 << " [--" << kCountSwitch << "=c]"
52 << " [--" << kFrequencySwitch << "=q]"
53 << " [--" << kFuzzerNameSwitch << "=f]"
54 << " [--" << kHelpSwitch << "]"
55 << " [--" << kTypeListSwitch << "=x,y,z...]"
56 << " [--" << kPermuteSwitch << "]"
57 << " [infile (mutation only)] outfile\n";
58
59 std::cerr
60 << " --" << kCountSwitch << " - " << kCountSwitchHelp << "\n"
61 << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n"
62 << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n"
63 << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n"
64 << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n"
65 << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n";
66 }
67
68 } // namespace
69
70 class FuzzerFactory {
71 public:
72 static Fuzzer *Create(const std::string& name, int frequency) {
73 if (name == "default")
74 return new Generator();
75
76 if (name == "generate")
77 return new Generator();
78
79 if (name == "mutate")
80 return new Mutator(frequency);
81
82 if (name == "no-op")
83 return new NoOpFuzzer();
84
85 std::cerr << "No such fuzzer: " << name << "\n";
86 return 0;
87 }
88 };
89
90 static IPC::Message* RewriteMessage(
91 IPC::Message* message,
92 Fuzzer* fuzzer,
93 FuzzerFunctionMap* map) {
94 FuzzerFunctionMap::iterator it = map->find(message->type());
95 if (it == map->end()) {
96 // This usually indicates a missing message file in all_messages.h, or
97 // that the message dump file is taken from a different revision of
98 // chromium from this executable.
99 std::cerr << "Unknown message type: ["
100 << IPC_MESSAGE_ID_CLASS(message->type()) << ", "
101 << IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
102 return 0;
103 }
104
105 return (*it->second)(message, fuzzer);
106 }
107
108 int Generate(base::CommandLine* cmd, Fuzzer* fuzzer) {
109 base::CommandLine::StringVector args = cmd->GetArgs();
110 if (args.size() != 1) {
111 usage();
112 return EXIT_FAILURE;
113 }
114 base::FilePath::StringType output_file_name = args[0];
115
116 int message_count = 1000;
117 if (cmd->HasSwitch(kCountSwitch))
118 message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
119
120 MessageVector message_vector;
121 int bad_count = 0;
122 if (message_count < 0) {
123 // Enumerate them all.
124 for (size_t i = 0; i < g_function_vector.size(); ++i) {
125 if (IPC::Message* new_message = (*g_function_vector[i])(NULL, fuzzer))
126 message_vector.push_back(new_message);
127 else
128 bad_count += 1;
129 }
130 } else {
131 // Fuzz a random batch.
132 for (int i = 0; i < message_count; ++i) {
133 size_t index = RandInRange(g_function_vector.size());
134 if (IPC::Message* new_message = (*g_function_vector[index])(NULL, fuzzer))
135 message_vector.push_back(new_message);
136 else
137 bad_count += 1;
138 }
139 }
140
141 std::cerr << "Failed to generate " << bad_count << " messages.\n";
142 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
143 return EXIT_FAILURE;
144 return EXIT_SUCCESS;
145 }
146
147 int Mutate(base::CommandLine* cmd, Fuzzer* fuzzer) {
148 base::CommandLine::StringVector args = cmd->GetArgs();
149 if (args.size() != 2) {
150 usage();
151 return EXIT_FAILURE;
152 }
153 base::FilePath::StringType input_file_name = args[0];
154 base::FilePath::StringType output_file_name = args[1];
155
156 bool permute = cmd->HasSwitch(kPermuteSwitch);
157
158 std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
159 std::vector<std::string> type_string_vector;
160 base::SplitString(type_string_list, ',', &type_string_vector);
161 std::set<uint32> type_set;
162 for (size_t i = 0; i < type_string_vector.size(); ++i) {
163 type_set.insert(atoi(type_string_vector[i].c_str()));
164 }
165
166 FuzzerFunctionMap fuzz_function_map;
167 PopulateFuzzerFunctionMap(&fuzz_function_map);
168
169 MessageVector message_vector;
170 if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
171 return EXIT_FAILURE;
172
173 for (size_t i = 0; i < message_vector.size(); ++i) {
174 IPC::Message* msg = message_vector[i];
175 // If an explicit type set is specified, make sure we should be mutating
176 // this message type on this run.
177 if (!type_set.empty() && type_set.end() == std::find(
178 type_set.begin(), type_set.end(), msg->type())) {
179 continue;
180 }
181 IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map);
182 if (new_message) {
183 IPC::Message* old_message = message_vector[i];
184 delete old_message;
185 message_vector[i] = new_message;
186 }
187 }
188
189 if (permute) {
190 std::random_shuffle(message_vector.begin(), message_vector.end(),
191 RandInRange);
192 }
193
194 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
195 return EXIT_FAILURE;
196 return EXIT_SUCCESS;
197 }
198
199 int FuzzerMain(int argc, char** argv) {
200 base::CommandLine::Init(argc, argv);
201 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
202 base::CommandLine::StringVector args = cmd->GetArgs();
203
204 if (args.size() == 0 || args.size() > 2 || cmd->HasSwitch(kHelpSwitch)) {
205 usage();
206 return EXIT_FAILURE;
207 }
208
209 InitRand();
210
211 PopulateFuzzerFunctionVector(&g_function_vector);
212 std::cerr << "Counted " << g_function_vector.size()
213 << " distinct messages present in chrome.\n";
214
215 std::string fuzzer_name = "default";
216 if (cmd->HasSwitch(kFuzzerNameSwitch))
217 fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);
218
219 int frequency = 23;
inferno 2015/03/19 16:00:13 Please add a FIXME for this hardcoded value. Move
220 if (cmd->HasSwitch(kFrequencySwitch))
221 frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());
222
223 Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
224 if (!fuzzer)
225 return EXIT_FAILURE;
226
227 int result;
228 base::FilePath::StringType output_file_name;
229 if (fuzzer_name == "default" || fuzzer_name == "generate") {
230 result = Generate(cmd, fuzzer);
231 } else {
232 result = Mutate(cmd, fuzzer);
233 }
234
235 return result;
236 }
237
238 } // namespace ipc_fuzzer
239
240 int main(int argc, char** argv) {
241 return ipc_fuzzer::FuzzerMain(argc, argv);
242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698