• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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