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

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

Powered by Google App Engine
This is Rietveld 408576698