Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / ipc_fuzzer / mutate / mutate.cc
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>
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>
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:
92   DefaultFuzzer(int frequency) : frequency_(frequency) {
93   }
94
95   virtual ~DefaultFuzzer() {}
96
97   virtual void FuzzBool(bool* value) override {
98     if (RandEvent(frequency_))
99       (*value) = !(*value);
100   }
101
102   virtual void FuzzInt(int* value) override {
103     FuzzIntegralType<int>(value, frequency_);
104   }
105
106   virtual void FuzzLong(long* value) override {
107     FuzzIntegralType<long>(value, frequency_);
108   }
109
110   virtual void FuzzSize(size_t* value) override {
111     FuzzIntegralType<size_t>(value, frequency_);
112   }
113
114   virtual void FuzzUChar(unsigned char* value) override {
115     FuzzIntegralType<unsigned char>(value, frequency_);
116   }
117
118   virtual void FuzzUInt16(uint16* value) override {
119     FuzzIntegralType<uint16>(value, frequency_);
120   }
121
122   virtual void FuzzUInt32(uint32* value) override {
123     FuzzIntegralType<uint32>(value, frequency_);
124   }
125
126   virtual void FuzzInt64(int64* value) override {
127     FuzzIntegralType<int64>(value, frequency_);
128   }
129
130   virtual void FuzzUInt64(uint64* value) override {
131     FuzzIntegralType<uint64>(value, frequency_);
132   }
133
134   virtual void FuzzFloat(float* value) override {
135     if (RandEvent(frequency_))
136       *value = RandDouble();
137   }
138
139   virtual void FuzzDouble(double* value) override {
140     if (RandEvent(frequency_))
141       *value = RandDouble();
142   }
143
144   virtual void FuzzString(std::string* value) override {
145     FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
146   }
147
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
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
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:
175   NoOpFuzzer() {}
176   virtual ~NoOpFuzzer() {}
177
178   virtual void FuzzBool(bool* value) override {}
179   virtual void FuzzInt(int* value) override {}
180   virtual void FuzzLong(long* value) override {}
181   virtual void FuzzSize(size_t* value) override {}
182   virtual void FuzzUChar(unsigned char* value) override {}
183   virtual void FuzzUInt16(uint16* value) override {}
184   virtual void FuzzUInt32(uint32* value) override {}
185   virtual void FuzzInt64(int64* value) override {}
186   virtual void FuzzUInt64(uint64* value) override {}
187   virtual void FuzzFloat(float* value) override {}
188   virtual void FuzzDouble(double* value) override {}
189   virtual void FuzzString(std::string* value) override {}
190   virtual void FuzzString16(base::string16* value) override {}
191   virtual void FuzzData(char* data, int length) override {}
192   virtual void FuzzBytes(void* data, int data_len) override {}
193 };
194
195 class FuzzerFactory {
196  public:
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 {
212   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>
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> {
228   static void Fuzz(bool* p, Fuzzer* fuzzer) {
229     fuzzer->FuzzBool(p);
230   }
231 };
232
233 template <>
234 struct FuzzTraits<int> {
235   static void Fuzz(int* p, Fuzzer* fuzzer) {
236     fuzzer->FuzzInt(p);
237   }
238 };
239
240 template <>
241 struct FuzzTraits<unsigned int> {
242   static void Fuzz(unsigned int* p, Fuzzer* fuzzer) {
243     fuzzer->FuzzInt(reinterpret_cast<int*>(p));
244   }
245 };
246
247 template <>
248 struct FuzzTraits<long> {
249   static void Fuzz(long* p, Fuzzer* fuzzer) {
250     fuzzer->FuzzLong(p);
251   }
252 };
253
254 template <>
255 struct FuzzTraits<unsigned long> {
256   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> {
263   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> {
270   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> {
277   static void Fuzz(short* p, Fuzzer* fuzzer) {
278     fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
279   }
280 };
281
282 template <>
283 struct FuzzTraits<unsigned short> {
284   static void Fuzz(unsigned short* p, Fuzzer* fuzzer) {
285     fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
286   }
287 };
288
289 template <>
290 struct FuzzTraits<char> {
291   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> {
298   static void Fuzz(unsigned char* p, Fuzzer* fuzzer) {
299     fuzzer->FuzzUChar(p);
300   }
301 };
302
303 template <>
304 struct FuzzTraits<float> {
305   static void Fuzz(float* p, Fuzzer* fuzzer) {
306     fuzzer->FuzzFloat(p);
307   }
308 };
309
310 template <>
311 struct FuzzTraits<double> {
312   static void Fuzz(double* p, Fuzzer* fuzzer) {
313     fuzzer->FuzzDouble(p);
314   }
315 };
316
317 template <>
318 struct FuzzTraits<std::string> {
319   static void Fuzz(std::string* p, Fuzzer* fuzzer) {
320     fuzzer->FuzzString(p);
321   }
322 };
323
324 template <>
325 struct FuzzTraits<base::string16> {
326   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> > {
334   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> > {
341   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> > {
349   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> > {
358   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> > {
368   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> > {
380   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> > {
389   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> > {
399   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> {
407   static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) {
408     FuzzParam(&p->fd, fuzzer);
409   }
410 };
411
412 template <>
413 struct FuzzTraits<GURL> {
414   static void Fuzz(GURL *p, Fuzzer* fuzzer) {
415     FuzzParam(&p->possibly_invalid_spec(), fuzzer);
416   }
417 };
418
419 template <>
420 struct FuzzTraits<gfx::Point> {
421   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> {
432   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> {
443   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
591 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) {
592 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
593 }
594
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
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
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
727 int main(int argc, char** argv) {
728   return ipc_fuzzer::MutateMain(argc, argv);
729 }