1 // Copyright 2013 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 <stdlib.h>
6
7 #include <algorithm>
8 #include <iostream>
9 #include <ostream>
10 #include <set>
11 #include <string>
12 #include <vector>
13
14 #include "base/command_line.h"
15 #include "base/pickle.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "ipc/ipc_message.h"
21 #include "ipc/ipc_message_utils.h"
22 #include "ipc/ipc_switches.h"
23 #include "ipc/ipc_sync_channel.h"
24 #include "ipc/ipc_sync_message.h"
25 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
26 #include "tools/ipc_fuzzer/message_lib/message_cracker.h"
27 #include "tools/ipc_fuzzer/message_lib/message_file.h"
28 #include "tools/ipc_fuzzer/mutate/rand_util.h"
29
30 #if defined(OS_POSIX)
31 #include <unistd.h>
32 #endif
33
34 namespace IPC {
35 class Message;
36 } // namespace IPC
37
38 namespace ipc_fuzzer {
39
40 // Interface implemented by those who fuzz basic types. The types all
41 // correspond to the types which a pickle from base/pickle.h can pickle,
42 // plus the floating point types.
43 class Fuzzer {
44 public:
45 // Tweak individual values within a message.
46 virtual void FuzzBool(bool* value) = 0;
47 virtual void FuzzInt(int* value) = 0;
48 virtual void FuzzLong(long* value) = 0;
49 virtual void FuzzSize(size_t* value) = 0;
50 virtual void FuzzUChar(unsigned char *value) = 0;
51 virtual void FuzzUInt16(uint16* value) = 0;
52 virtual void FuzzUInt32(uint32* value) = 0;
53 virtual void FuzzInt64(int64* value) = 0;
54 virtual void FuzzUInt64(uint64* value) = 0;
55 virtual void FuzzFloat(float *value) = 0;
56 virtual void FuzzDouble(double *value) = 0;
57 virtual void FuzzString(std::string* value) = 0;
58 virtual void FuzzString16(base::string16* value) = 0;
59 virtual void FuzzData(char* data, int length) = 0;
60 virtual void FuzzBytes(void* data, int data_len) = 0;
61 };
62
63 template <typename T>
FuzzIntegralType(T * value,unsigned int frequency)64 void FuzzIntegralType(T* value, unsigned int frequency) {
65 if (RandEvent(frequency)) {
66 switch (RandInRange(4)) {
67 case 0: (*value) = 0; break;
68 case 1: (*value)--; break;
69 case 2: (*value)++; break;
70 case 3: (*value) = RandU64(); break;
71 }
72 }
73 }
74
75 template <typename T>
FuzzStringType(T * value,unsigned int frequency,const T & literal1,const T & literal2)76 void FuzzStringType(T* value, unsigned int frequency,
77 const T& literal1, const T& literal2) {
78 if (RandEvent(frequency)) {
79 switch (RandInRange(5)) {
80 case 4: (*value) = (*value) + (*value); // FALLTHROUGH
81 case 3: (*value) = (*value) + (*value); // FALLTHROUGH
82 case 2: (*value) = (*value) + (*value); break;
83 case 1: (*value) += literal1; break;
84 case 0: (*value) = literal2; break;
85 }
86 }
87 }
88
89 // One such fuzzer implementation.
90 class DefaultFuzzer : public Fuzzer {
91 public:
DefaultFuzzer(int frequency)92 DefaultFuzzer(int frequency) : frequency_(frequency) {
93 }
94
~DefaultFuzzer()95 virtual ~DefaultFuzzer() {}
96
FuzzBool(bool * value)97 virtual void FuzzBool(bool* value) OVERRIDE {
98 if (RandEvent(frequency_))
99 (*value) = !(*value);
100 }
101
FuzzInt(int * value)102 virtual void FuzzInt(int* value) OVERRIDE {
103 FuzzIntegralType<int>(value, frequency_);
104 }
105
FuzzLong(long * value)106 virtual void FuzzLong(long* value) OVERRIDE {
107 FuzzIntegralType<long>(value, frequency_);
108 }
109
FuzzSize(size_t * value)110 virtual void FuzzSize(size_t* value) OVERRIDE {
111 FuzzIntegralType<size_t>(value, frequency_);
112 }
113
FuzzUChar(unsigned char * value)114 virtual void FuzzUChar(unsigned char* value) OVERRIDE {
115 FuzzIntegralType<unsigned char>(value, frequency_);
116 }
117
FuzzUInt16(uint16 * value)118 virtual void FuzzUInt16(uint16* value) OVERRIDE {
119 FuzzIntegralType<uint16>(value, frequency_);
120 }
121
FuzzUInt32(uint32 * value)122 virtual void FuzzUInt32(uint32* value) OVERRIDE {
123 FuzzIntegralType<uint32>(value, frequency_);
124 }
125
FuzzInt64(int64 * value)126 virtual void FuzzInt64(int64* value) OVERRIDE {
127 FuzzIntegralType<int64>(value, frequency_);
128 }
129
FuzzUInt64(uint64 * value)130 virtual void FuzzUInt64(uint64* value) OVERRIDE {
131 FuzzIntegralType<uint64>(value, frequency_);
132 }
133
FuzzFloat(float * value)134 virtual void FuzzFloat(float* value) OVERRIDE {
135 if (RandEvent(frequency_))
136 *value = RandDouble();
137 }
138
FuzzDouble(double * value)139 virtual void FuzzDouble(double* value) OVERRIDE {
140 if (RandEvent(frequency_))
141 *value = RandDouble();
142 }
143
FuzzString(std::string * value)144 virtual void FuzzString(std::string* value) OVERRIDE {
145 FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
146 }
147
FuzzString16(base::string16 * value)148 virtual void FuzzString16(base::string16* value) OVERRIDE {
149 FuzzStringType<base::string16>(value, frequency_,
150 base::WideToUTF16(L"BORKED"),
151 base::WideToUTF16(L""));
152 }
153
FuzzData(char * data,int length)154 virtual void FuzzData(char* data, int length) OVERRIDE {
155 if (RandEvent(frequency_)) {
156 for (int i = 0; i < length; ++i) {
157 FuzzIntegralType<char>(&data[i], frequency_);
158 }
159 }
160 }
161
FuzzBytes(void * data,int data_len)162 virtual void FuzzBytes(void* data, int data_len) OVERRIDE {
163 FuzzData(static_cast<char*>(data), data_len);
164 }
165
166 private:
167 unsigned int frequency_;
168 };
169
170
171 // No-op fuzzer. Rewrites each message unchanged to check if the message
172 // re-assembly is legit.
173 class NoOpFuzzer : public Fuzzer {
174 public:
NoOpFuzzer()175 NoOpFuzzer() {}
~NoOpFuzzer()176 virtual ~NoOpFuzzer() {}
177
FuzzBool(bool * value)178 virtual void FuzzBool(bool* value) OVERRIDE {}
FuzzInt(int * value)179 virtual void FuzzInt(int* value) OVERRIDE {}
FuzzLong(long * value)180 virtual void FuzzLong(long* value) OVERRIDE {}
FuzzSize(size_t * value)181 virtual void FuzzSize(size_t* value) OVERRIDE {}
FuzzUChar(unsigned char * value)182 virtual void FuzzUChar(unsigned char* value) OVERRIDE {}
FuzzUInt16(uint16 * value)183 virtual void FuzzUInt16(uint16* value) OVERRIDE {}
FuzzUInt32(uint32 * value)184 virtual void FuzzUInt32(uint32* value) OVERRIDE {}
FuzzInt64(int64 * value)185 virtual void FuzzInt64(int64* value) OVERRIDE {}
FuzzUInt64(uint64 * value)186 virtual void FuzzUInt64(uint64* value) OVERRIDE {}
FuzzFloat(float * value)187 virtual void FuzzFloat(float* value) OVERRIDE {}
FuzzDouble(double * value)188 virtual void FuzzDouble(double* value) OVERRIDE {}
FuzzString(std::string * value)189 virtual void FuzzString(std::string* value) OVERRIDE {}
FuzzString16(base::string16 * value)190 virtual void FuzzString16(base::string16* value) OVERRIDE {}
FuzzData(char * data,int length)191 virtual void FuzzData(char* data, int length) OVERRIDE {}
FuzzBytes(void * data,int data_len)192 virtual void FuzzBytes(void* data, int data_len) OVERRIDE {}
193 };
194
195 class FuzzerFactory {
196 public:
Create(const std::string & name,int frequency)197 static Fuzzer *Create(const std::string& name, int frequency) {
198 if (name == "no-op")
199 return new NoOpFuzzer();
200
201 if (name == "default")
202 return new DefaultFuzzer(frequency);
203
204 std::cerr << "No such fuzzer: " << name << "\n";
205 return 0;
206 }
207 };
208
209 // Partially-specialized class that knows how to fuzz a given type.
210 template <class P>
211 struct FuzzTraits {
Fuzzipc_fuzzer::FuzzTraits212 static void Fuzz(P* p, Fuzzer *fuzzer) {
213 // This is the catch-all for types we don't have enough information
214 // to fuzz. It simply does nothing to the type. We might want to
215 // change it to randomly flip a bit in the range (p, p+sizeof(P)).
216 }
217 };
218
219 // Template function to invoke partially-specialized class method.
220 template <class P>
FuzzParam(P * p,Fuzzer * fuzzer)221 static void FuzzParam(P* p, Fuzzer* fuzzer) {
222 FuzzTraits<P>::Fuzz(p, fuzzer);
223 }
224
225 // Specializations to fuzz primitive types.
226 template <>
227 struct FuzzTraits<bool> {
Fuzzipc_fuzzer::FuzzTraits228 static void Fuzz(bool* p, Fuzzer* fuzzer) {
229 fuzzer->FuzzBool(p);
230 }
231 };
232
233 template <>
234 struct FuzzTraits<int> {
Fuzzipc_fuzzer::FuzzTraits235 static void Fuzz(int* p, Fuzzer* fuzzer) {
236 fuzzer->FuzzInt(p);
237 }
238 };
239
240 template <>
241 struct FuzzTraits<unsigned int> {
Fuzzipc_fuzzer::FuzzTraits242 static void Fuzz(unsigned int* p, Fuzzer* fuzzer) {
243 fuzzer->FuzzInt(reinterpret_cast<int*>(p));
244 }
245 };
246
247 template <>
248 struct FuzzTraits<long> {
Fuzzipc_fuzzer::FuzzTraits249 static void Fuzz(long* p, Fuzzer* fuzzer) {
250 fuzzer->FuzzLong(p);
251 }
252 };
253
254 template <>
255 struct FuzzTraits<unsigned long> {
Fuzzipc_fuzzer::FuzzTraits256 static void Fuzz(unsigned long* p, Fuzzer* fuzzer) {
257 fuzzer->FuzzLong(reinterpret_cast<long*>(p));
258 }
259 };
260
261 template <>
262 struct FuzzTraits<long long> {
Fuzzipc_fuzzer::FuzzTraits263 static void Fuzz(long long* p, Fuzzer* fuzzer) {
264 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
265 }
266 };
267
268 template <>
269 struct FuzzTraits<unsigned long long> {
Fuzzipc_fuzzer::FuzzTraits270 static void Fuzz(unsigned long long* p, Fuzzer* fuzzer) {
271 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
272 }
273 };
274
275 template <>
276 struct FuzzTraits<short> {
Fuzzipc_fuzzer::FuzzTraits277 static void Fuzz(short* p, Fuzzer* fuzzer) {
278 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
279 }
280 };
281
282 template <>
283 struct FuzzTraits<unsigned short> {
Fuzzipc_fuzzer::FuzzTraits284 static void Fuzz(unsigned short* p, Fuzzer* fuzzer) {
285 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
286 }
287 };
288
289 template <>
290 struct FuzzTraits<char> {
Fuzzipc_fuzzer::FuzzTraits291 static void Fuzz(char* p, Fuzzer* fuzzer) {
292 fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
293 }
294 };
295
296 template <>
297 struct FuzzTraits<unsigned char> {
Fuzzipc_fuzzer::FuzzTraits298 static void Fuzz(unsigned char* p, Fuzzer* fuzzer) {
299 fuzzer->FuzzUChar(p);
300 }
301 };
302
303 template <>
304 struct FuzzTraits<float> {
Fuzzipc_fuzzer::FuzzTraits305 static void Fuzz(float* p, Fuzzer* fuzzer) {
306 fuzzer->FuzzFloat(p);
307 }
308 };
309
310 template <>
311 struct FuzzTraits<double> {
Fuzzipc_fuzzer::FuzzTraits312 static void Fuzz(double* p, Fuzzer* fuzzer) {
313 fuzzer->FuzzDouble(p);
314 }
315 };
316
317 template <>
318 struct FuzzTraits<std::string> {
Fuzzipc_fuzzer::FuzzTraits319 static void Fuzz(std::string* p, Fuzzer* fuzzer) {
320 fuzzer->FuzzString(p);
321 }
322 };
323
324 template <>
325 struct FuzzTraits<base::string16> {
Fuzzipc_fuzzer::FuzzTraits326 static void Fuzz(base::string16* p, Fuzzer* fuzzer) {
327 fuzzer->FuzzString16(p);
328 }
329 };
330
331 // Specializations to fuzz tuples.
332 template <class A>
333 struct FuzzTraits<Tuple1<A> > {
Fuzzipc_fuzzer::FuzzTraits334 static void Fuzz(Tuple1<A>* p, Fuzzer* fuzzer) {
335 FuzzParam(&p->a, fuzzer);
336 }
337 };
338
339 template <class A, class B>
340 struct FuzzTraits<Tuple2<A, B> > {
Fuzzipc_fuzzer::FuzzTraits341 static void Fuzz(Tuple2<A, B>* p, Fuzzer* fuzzer) {
342 FuzzParam(&p->a, fuzzer);
343 FuzzParam(&p->b, fuzzer);
344 }
345 };
346
347 template <class A, class B, class C>
348 struct FuzzTraits<Tuple3<A, B, C> > {
Fuzzipc_fuzzer::FuzzTraits349 static void Fuzz(Tuple3<A, B, C>* p, Fuzzer* fuzzer) {
350 FuzzParam(&p->a, fuzzer);
351 FuzzParam(&p->b, fuzzer);
352 FuzzParam(&p->c, fuzzer);
353 }
354 };
355
356 template <class A, class B, class C, class D>
357 struct FuzzTraits<Tuple4<A, B, C, D> > {
Fuzzipc_fuzzer::FuzzTraits358 static void Fuzz(Tuple4<A, B, C, D>* p, Fuzzer* fuzzer) {
359 FuzzParam(&p->a, fuzzer);
360 FuzzParam(&p->b, fuzzer);
361 FuzzParam(&p->c, fuzzer);
362 FuzzParam(&p->d, fuzzer);
363 }
364 };
365
366 template <class A, class B, class C, class D, class E>
367 struct FuzzTraits<Tuple5<A, B, C, D, E> > {
Fuzzipc_fuzzer::FuzzTraits368 static void Fuzz(Tuple5<A, B, C, D, E>* p, Fuzzer* fuzzer) {
369 FuzzParam(&p->a, fuzzer);
370 FuzzParam(&p->b, fuzzer);
371 FuzzParam(&p->c, fuzzer);
372 FuzzParam(&p->d, fuzzer);
373 FuzzParam(&p->e, fuzzer);
374 }
375 };
376
377 // Specializations to fuzz containers.
378 template <class A>
379 struct FuzzTraits<std::vector<A> > {
Fuzzipc_fuzzer::FuzzTraits380 static void Fuzz(std::vector<A>* p, Fuzzer* fuzzer) {
381 for (size_t i = 0; i < p->size(); ++i) {
382 FuzzParam(&p->at(i), fuzzer);
383 }
384 }
385 };
386
387 template <class A, class B>
388 struct FuzzTraits<std::map<A, B> > {
Fuzzipc_fuzzer::FuzzTraits389 static void Fuzz(std::map<A, B>* p, Fuzzer* fuzzer) {
390 typename std::map<A, B>::iterator it;
391 for (it = p->begin(); it != p->end(); ++it) {
392 FuzzParam(&it->second, fuzzer);
393 }
394 }
395 };
396
397 template <class A, class B>
398 struct FuzzTraits<std::pair<A, B> > {
Fuzzipc_fuzzer::FuzzTraits399 static void Fuzz(std::pair<A, B>* p, Fuzzer* fuzzer) {
400 FuzzParam(&p->second, fuzzer);
401 }
402 };
403
404 // Specializations to fuzz hand-coded tyoes
405 template <>
406 struct FuzzTraits<base::FileDescriptor> {
Fuzzipc_fuzzer::FuzzTraits407 static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) {
408 FuzzParam(&p->fd, fuzzer);
409 }
410 };
411
412 template <>
413 struct FuzzTraits<GURL> {
Fuzzipc_fuzzer::FuzzTraits414 static void Fuzz(GURL *p, Fuzzer* fuzzer) {
415 FuzzParam(&p->possibly_invalid_spec(), fuzzer);
416 }
417 };
418
419 template <>
420 struct FuzzTraits<gfx::Point> {
Fuzzipc_fuzzer::FuzzTraits421 static void Fuzz(gfx::Point *p, Fuzzer* fuzzer) {
422 int x = p->x();
423 int y = p->y();
424 FuzzParam(&x, fuzzer);
425 FuzzParam(&y, fuzzer);
426 p->SetPoint(x, y);
427 }
428 };
429
430 template <>
431 struct FuzzTraits<gfx::Size> {
Fuzzipc_fuzzer::FuzzTraits432 static void Fuzz(gfx::Size *p, Fuzzer* fuzzer) {
433 int w = p->width();
434 int h = p->height();
435 FuzzParam(&w, fuzzer);
436 FuzzParam(&h, fuzzer);
437 p->SetSize(w, h);
438 }
439 };
440
441 template <>
442 struct FuzzTraits<gfx::Rect> {
Fuzzipc_fuzzer::FuzzTraits443 static void Fuzz(gfx::Rect *p, Fuzzer* fuzzer) {
444 gfx::Point origin = p->origin();
445 gfx::Size size = p->size();
446 FuzzParam(&origin, fuzzer);
447 FuzzParam(&size, fuzzer);
448 p->set_origin(origin);
449 p->set_size(size);
450 }
451 };
452
453 // Redefine macros to generate fuzzing from traits declarations.
454 // Null out all the macros that need nulling.
455 #include "ipc/ipc_message_null_macros.h"
456
457 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
458 #undef IPC_STRUCT_BEGIN
459 #undef IPC_STRUCT_BEGIN_WITH_PARENT
460 #undef IPC_STRUCT_MEMBER
461 #undef IPC_STRUCT_END
462 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
463 IPC_STRUCT_BEGIN(struct_name)
464 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
465 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
466 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
467
468 // Set up so next include will generate fuzz trait classes.
469 #undef IPC_STRUCT_TRAITS_BEGIN
470 #undef IPC_STRUCT_TRAITS_MEMBER
471 #undef IPC_STRUCT_TRAITS_PARENT
472 #undef IPC_STRUCT_TRAITS_END
473 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
474 template <> \
475 struct FuzzTraits<struct_name> { \
476 static void Fuzz(struct_name *p, Fuzzer* fuzzer) {
477
478 #define IPC_STRUCT_TRAITS_MEMBER(name) \
479 FuzzParam(&p->name, fuzzer);
480
481 #define IPC_STRUCT_TRAITS_PARENT(type) \
482 FuzzParam(static_cast<type*>(p), fuzzer);
483
484 #define IPC_STRUCT_TRAITS_END() \
485 } \
486 };
487
488 // TODO(tsepez): Make sure to end up with an enum that meets |condition|.
489 #undef IPC_ENUM_TRAITS_VALIDATE
490 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, conditon) \
491 template <> \
492 struct FuzzTraits<enum_name> { \
493 static void Fuzz(enum_name* p, Fuzzer* fuzzer) { \
494 FuzzParam(reinterpret_cast<int*>(p), fuzzer); \
495 } \
496 };
497
498 // Bring them into existence.
499 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
500
501 // Redefine macros to generate fuzzing funtions
502 #include "ipc/ipc_message_null_macros.h"
503 #undef IPC_MESSAGE_DECL
504 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
505 IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist)
506
507 #define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \
508 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
509 return NULL; \
510 }
511
512 #define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \
513 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
514 return NULL; \
515 }
516
517 #define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \
518 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
519 name* real_msg = static_cast<name*>(msg); \
520 IPC_TUPLE_IN_##in ilist p; \
521 name::Read(real_msg, &p); \
522 FuzzParam(&p, fuzzer); \
523 return new name(IPC_MEMBERS_IN_##in(p)); \
524 }
525
526 #define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \
527 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
528 name* real_msg = static_cast<name*>(msg); \
529 IPC_TUPLE_IN_##in ilist p; \
530 name::Read(real_msg, &p); \
531 FuzzParam(&p, fuzzer); \
532 return new name(msg->routing_id() \
533 IPC_COMMA_##in \
534 IPC_MEMBERS_IN_##in(p)); \
535 }
536
537 #define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \
538 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
539 name* real_msg = static_cast<name*>(msg); \
540 IPC_TUPLE_IN_##in ilist p; \
541 name::ReadSendParam(real_msg, &p); \
542 FuzzParam(&p, fuzzer); \
543 name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \
544 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
545 IPC_MEMBERS_OUT_##out()); \
546 MessageCracker::CopyMessageID(new_msg, real_msg); \
547 return new_msg; \
548 }
549
550
551 #define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \
552 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \
553 name* real_msg = static_cast<name*>(msg); \
554 IPC_TUPLE_IN_##in ilist p; \
555 name::ReadSendParam(real_msg, &p); \
556 FuzzParam(&p, fuzzer); \
557 name* new_msg = new name(msg->routing_id() \
558 IPC_COMMA_OR_##out(IPC_COMMA_##in) \
559 IPC_MEMBERS_IN_##in(p) \
560 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
561 IPC_MEMBERS_OUT_##out()); \
562 MessageCracker::CopyMessageID(new_msg, real_msg); \
563 return new_msg; \
564 }
565
566 #define IPC_MEMBERS_IN_0(p)
567 #define IPC_MEMBERS_IN_1(p) p.a
568 #define IPC_MEMBERS_IN_2(p) p.a, p.b
569 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
570 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
571 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e
572
573 #define IPC_MEMBERS_OUT_0()
574 #define IPC_MEMBERS_OUT_1() NULL
575 #define IPC_MEMBERS_OUT_2() NULL, NULL
576 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL
577 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL
578 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL
579
580 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
581
582 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, Fuzzer*);
583 typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap;
584
585 // Redefine macros to register fuzzing functions into map.
586 #include "ipc/ipc_message_null_macros.h"
587 #undef IPC_MESSAGE_DECL
588 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
589 (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name;
590
PopulateFuzzFunctionMap(FuzzFunctionMap * map)591 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) {
592 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
593 }
594
RewriteMessage(IPC::Message * message,Fuzzer * fuzzer,FuzzFunctionMap * map)595 static IPC::Message* RewriteMessage(
596 IPC::Message* message,
597 Fuzzer* fuzzer,
598 FuzzFunctionMap* map) {
599 FuzzFunctionMap::iterator it = map->find(message->type());
600 if (it == map->end()) {
601 // This usually indicates a missing message file in all_messages.h, or
602 // that the message dump file is taken from a different revision of
603 // chromium from this executable.
604 std::cerr << "Unknown message type: ["
605 << IPC_MESSAGE_ID_CLASS(message->type()) << ", "
606 << IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
607 return 0;
608 }
609
610 return (*it->second)(message, fuzzer);
611 }
612
613 namespace {
614
615 const char kHelpSwitch[] = "help";
616 const char kHelpSwitchHelp[] =
617 "show this message";
618
619 const char kFrequencySwitch[] = "frequency";
620 const char kFrequencySwitchHelp[] =
621 "probability of mutation; tweak every 1/|q| times.";
622
623 const char kFuzzerNameSwitch[] = "fuzzer-name";
624 const char kFuzzerNameSwitchHelp[] =
625 "select default or no-op fuzzer.";
626
627 const char kPermuteSwitch[] = "permute";
628 const char kPermuteSwitchHelp[] =
629 "Randomly shuffle the order of all messages.";
630
631 const char kTypeListSwitch[] = "type-list";
632 const char kTypeListSwitchHelp[] =
633 "explicit list of the only message-ids to mutate.";
634
usage()635 void usage() {
636 std::cerr << "Mutate messages from an exiting message file.\n";
637
638 std::cerr << "Usage:\n"
639 << " ipc_fuzzer_mutate"
640 << " [--" << kHelpSwitch << "]"
641 << " [--" << kFuzzerNameSwitch << "=f]"
642 << " [--" << kFrequencySwitch << "=q]"
643 << " [--" << kTypeListSwitch << "=x,y,z...]"
644 << " [--" << kPermuteSwitch << "]"
645 << " infile outfile\n";
646
647 std::cerr
648 << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n"
649 << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n"
650 << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n"
651 << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n"
652 << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n";
653 }
654
655 } // namespace
656
MutateMain(int argc,char ** argv)657 int MutateMain(int argc, char** argv) {
658 CommandLine::Init(argc, argv);
659 CommandLine* cmd = CommandLine::ForCurrentProcess();
660 CommandLine::StringVector args = cmd->GetArgs();
661
662 if (args.size() != 2 || cmd->HasSwitch(kHelpSwitch)) {
663 usage();
664 return EXIT_FAILURE;
665 }
666
667 std::string input_file_name = args[0];
668 std::string output_file_name = args[1];
669
670 bool permute = cmd->HasSwitch(kPermuteSwitch);
671
672 std::string fuzzer_name = "default";
673 if (cmd->HasSwitch(kFuzzerNameSwitch))
674 fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);
675
676 int frequency = 23;
677 if (cmd->HasSwitch(kFrequencySwitch))
678 frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());
679
680 std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
681 std::vector<std::string> type_string_vector;
682 base::SplitString(type_string_list, ',', &type_string_vector);
683 std::set<int> type_set;
684 for (size_t i = 0; i < type_string_vector.size(); ++i) {
685 type_set.insert(atoi(type_string_vector[i].c_str()));
686 }
687
688 InitRand();
689
690 Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
691 if (!fuzzer)
692 return EXIT_FAILURE;
693
694 FuzzFunctionMap fuzz_function_map;
695 PopulateFuzzFunctionMap(&fuzz_function_map);
696
697 MessageVector message_vector;
698 if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
699 return EXIT_FAILURE;
700
701 for (size_t i = 0; i < message_vector.size(); ++i) {
702 IPC::Message* msg = message_vector[i];
703 if (!type_set.empty() && type_set.end() == std::find(
704 type_set.begin(), type_set.end(), msg->type())) {
705 continue;
706 }
707 IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map);
708 if (new_message) {
709 delete message_vector[i];
710 message_vector[i] = new_message;
711 }
712 }
713
714 if (permute) {
715 std::random_shuffle(message_vector.begin(), message_vector.end(),
716 RandInRange);
717 }
718
719 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
720 return EXIT_FAILURE;
721
722 return EXIT_SUCCESS;
723 }
724
725 } // namespace ipc_fuzzer
726
main(int argc,char ** argv)727 int main(int argc, char** argv) {
728 return ipc_fuzzer::MutateMain(argc, argv);
729 }
730