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

Side by Side Diff: tools/ipc_fuzzer/mutate/mutator.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: Minor cleanup (if to else if) 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 <algorithm>
6 #include <iostream>
7 #include <set>
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/command_line.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "ipc/ipc_message.h"
17 #include "ipc/ipc_message_macros.h"
18 #include "tools/ipc_fuzzer/mutate/mutator.h"
19 #include "tools/ipc_fuzzer/mutate/rand_util.h"
20
21 namespace ipc_fuzzer {
22
23 template <typename T>
24 void FuzzIntegralType(T* value, unsigned int frequency) {
25 if (RandEvent(frequency)) {
26 switch (RandInRange(4)) {
27 case 0: (*value) = 0; break;
28 case 1: (*value)--; break;
29 case 2: (*value)++; break;
30 case 3: (*value) = RandU64(); break;
31 }
32 }
33 }
34
35 template <typename T>
36 void FuzzStringType(T* value, unsigned int frequency,
37 const T& literal1, const T& literal2) {
38 if (RandEvent(frequency)) {
39 switch (RandInRange(5)) {
40 case 4: (*value) = (*value) + (*value); // FALLTHROUGH
41 case 3: (*value) = (*value) + (*value); // FALLTHROUGH
42 case 2: (*value) = (*value) + (*value); break;
43 case 1: (*value) += literal1; break;
44 case 0: (*value) = literal2; break;
45 }
46 }
47 }
48
49 void Mutator::FuzzBool(bool* value) {
50 if (RandEvent(frequency_))
51 (*value) = !(*value);
52 }
53
54 void Mutator::FuzzInt(int* value) {
55 FuzzIntegralType<int>(value, frequency_);
56 }
57
58 void Mutator::FuzzLong(long* value) {
59 FuzzIntegralType<long>(value, frequency_);
60 }
61
62 void Mutator::FuzzSize(size_t* value) {
63 FuzzIntegralType<size_t>(value, frequency_);
64 }
65
66 void Mutator::FuzzUChar(unsigned char* value) {
67 FuzzIntegralType<unsigned char>(value, frequency_);
68 }
69
70 void Mutator::FuzzWChar(wchar_t* value) {
71 FuzzIntegralType<wchar_t>(value, frequency_);
72 }
73
74 void Mutator::FuzzUInt16(uint16* value) {
75 FuzzIntegralType<uint16>(value, frequency_);
76 }
77
78 void Mutator::FuzzUInt32(uint32* value) {
79 FuzzIntegralType<uint32>(value, frequency_);
80 }
81
82 void Mutator::FuzzInt64(int64* value) {
83 FuzzIntegralType<int64>(value, frequency_);
84 }
85
86 void Mutator::FuzzUInt64(uint64* value) {
87 FuzzIntegralType<uint64>(value, frequency_);
88 }
89
90 void Mutator::FuzzFloat(float* value) {
91 if (RandEvent(frequency_))
92 *value = RandDouble();
93 }
94
95 void Mutator::FuzzDouble(double* value) {
96 if (RandEvent(frequency_))
97 *value = RandDouble();
98 }
99
100 void Mutator:: FuzzString(std::string* value) {
101 FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
102 }
103
104 void Mutator::FuzzString16(base::string16* value) {
105 FuzzStringType<base::string16>(value, frequency_,
106 base::WideToUTF16(L"BORKED"),
107 base::WideToUTF16(L""));
108 }
109
110 void Mutator::FuzzData(char* data, int length) {
111 if (RandEvent(frequency_)) {
112 for (int i = 0; i < length; ++i) {
113 FuzzIntegralType<char>(&data[i], frequency_);
114 }
115 }
116 }
117
118 void Mutator::FuzzBytes(void* data, int data_len) {
119 FuzzData(static_cast<char*>(data), data_len);
120 }
121
122 bool Mutator::ShouldGenerate() {
123 // TODO(mbarbella): With a low probability, allow something to be fully
124 // rewritten while mutating instead of always changing the existing value.
125 return false;
126 }
127
128 class FuzzerFactory {
129 public:
130 static Fuzzer *Create(const std::string& name, int frequency) {
131 if (name == "no-op")
132 return new NoOpFuzzer();
133
134 if (name == "default")
135 return new Mutator(frequency);
136
137 std::cerr << "No such fuzzer: " << name << "\n";
138 return 0;
139 }
140 };
141
142 static IPC::Message* RewriteMessage(
143 IPC::Message* message,
144 Fuzzer* fuzzer,
145 FuzzerFunctionMap* map) {
146 FuzzerFunctionMap::iterator it = map->find(message->type());
147 if (it == map->end()) {
148 // This usually indicates a missing message file in all_messages.h, or
149 // that the message dump file is taken from a different revision of
150 // chromium from this executable.
151 std::cerr << "Unknown message type: ["
152 << IPC_MESSAGE_ID_CLASS(message->type()) << ", "
153 << IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
154 return 0;
155 }
156
157 return (*it->second)(message, fuzzer);
158 }
159
160 namespace {
161
162 static const char kHelpSwitch[] = "help";
163 const char kHelpSwitchHelp[] =
164 "show this message";
165
166 const char kFrequencySwitch[] = "frequency";
167 const char kFrequencySwitchHelp[] =
168 "probability of mutation; tweak every 1/|q| times.";
169
170 const char kFuzzerNameSwitch[] = "fuzzer-name";
171 const char kFuzzerNameSwitchHelp[] =
172 "select default or no-op fuzzer.";
173
174 const char kPermuteSwitch[] = "permute";
175 const char kPermuteSwitchHelp[] =
176 "Randomly shuffle the order of all messages.";
177
178 const char kTypeListSwitch[] = "type-list";
179 const char kTypeListSwitchHelp[] =
180 "explicit list of the only message-ids to mutate.";
181
182 void usage() {
183 std::cerr << "Mutate messages from an exiting message file.\n";
184
185 std::cerr << "Usage:\n"
186 << " ipc_fuzzer_mutate"
187 << " [--" << kHelpSwitch << "]"
188 << " [--" << kFuzzerNameSwitch << "=f]"
189 << " [--" << kFrequencySwitch << "=q]"
190 << " [--" << kTypeListSwitch << "=x,y,z...]"
191 << " [--" << kPermuteSwitch << "]"
192 << " infile outfile\n";
193
194 std::cerr
195 << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n"
196 << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n"
197 << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n"
198 << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n"
199 << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n";
200 }
201
202 } // namespace
203
204 int MutateMain(int argc, char** argv) {
205 base::CommandLine::Init(argc, argv);
206 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
207 base::CommandLine::StringVector args = cmd->GetArgs();
208
209 if (args.size() != 2 || cmd->HasSwitch(kHelpSwitch)) {
210 usage();
211 return EXIT_FAILURE;
212 }
213
214 base::FilePath::StringType input_file_name = args[0];
215 base::FilePath::StringType output_file_name = args[1];
216
217 bool permute = cmd->HasSwitch(kPermuteSwitch);
218
219 std::string fuzzer_name = "default";
220 if (cmd->HasSwitch(kFuzzerNameSwitch))
221 fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);
222
223 int frequency = 23;
224 if (cmd->HasSwitch(kFrequencySwitch))
225 frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());
226
227 std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
228 std::vector<std::string> type_string_vector;
229 base::SplitString(type_string_list, ',', &type_string_vector);
230 std::set<uint32> type_set;
231 for (size_t i = 0; i < type_string_vector.size(); ++i) {
232 type_set.insert(atoi(type_string_vector[i].c_str()));
233 }
234
235 InitRand();
236
237 Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
238 if (!fuzzer)
239 return EXIT_FAILURE;
240
241 FuzzerFunctionMap fuzz_function_map;
242 PopulateFuzzerFunctionMap(&fuzz_function_map);
243 PopulateFuzzerFunctionVector(&g_function_vector);
244
245 MessageVector message_vector;
246 if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
247 return EXIT_FAILURE;
248
249 for (size_t i = 0; i < message_vector.size(); ++i) {
250 IPC::Message* msg = message_vector[i];
251 // If an explicit type set is specified, make sure we should be mutating
252 // this message type on this run.
253 if (!type_set.empty() && type_set.end() == std::find(
254 type_set.begin(), type_set.end(), msg->type())) {
255 continue;
256 }
257 IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map);
258 if (new_message) {
259 IPC::Message* old_message = message_vector[i];
260 delete old_message;
261 message_vector[i] = new_message;
262 }
263 }
264
265 if (permute) {
266 std::random_shuffle(message_vector.begin(), message_vector.end(),
267 RandInRange);
268 }
269
270 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
271 return EXIT_FAILURE;
272
273 return EXIT_SUCCESS;
274 }
275
276 } // namespace ipc_fuzzer
277
278 int main(int argc, char** argv) {
279 return ipc_fuzzer::MutateMain(argc, argv);
280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698