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
34namespace IPC {
35class Message;
36}  // namespace IPC
37
38namespace 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.
43class 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
63template <typename T>
64void 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
75template <typename T>
76void 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.
90class 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.
173class 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
195class 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.
210template <class P>
211struct 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.
220template <class P>
221static void FuzzParam(P* p, Fuzzer* fuzzer) {
222  FuzzTraits<P>::Fuzz(p, fuzzer);
223}
224
225// Specializations to fuzz primitive types.
226template <>
227struct FuzzTraits<bool> {
228  static void Fuzz(bool* p, Fuzzer* fuzzer) {
229    fuzzer->FuzzBool(p);
230  }
231};
232
233template <>
234struct FuzzTraits<int> {
235  static void Fuzz(int* p, Fuzzer* fuzzer) {
236    fuzzer->FuzzInt(p);
237  }
238};
239
240template <>
241struct FuzzTraits<unsigned int> {
242  static void Fuzz(unsigned int* p, Fuzzer* fuzzer) {
243    fuzzer->FuzzInt(reinterpret_cast<int*>(p));
244  }
245};
246
247template <>
248struct FuzzTraits<long> {
249  static void Fuzz(long* p, Fuzzer* fuzzer) {
250    fuzzer->FuzzLong(p);
251  }
252};
253
254template <>
255struct FuzzTraits<unsigned long> {
256  static void Fuzz(unsigned long* p, Fuzzer* fuzzer) {
257    fuzzer->FuzzLong(reinterpret_cast<long*>(p));
258  }
259};
260
261template <>
262struct FuzzTraits<long long> {
263  static void Fuzz(long long* p, Fuzzer* fuzzer) {
264    fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
265  }
266};
267
268template <>
269struct FuzzTraits<unsigned long long> {
270  static void Fuzz(unsigned long long* p, Fuzzer* fuzzer) {
271    fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
272  }
273};
274
275template <>
276struct FuzzTraits<short> {
277  static void Fuzz(short* p, Fuzzer* fuzzer) {
278    fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
279  }
280};
281
282template <>
283struct FuzzTraits<unsigned short> {
284  static void Fuzz(unsigned short* p, Fuzzer* fuzzer) {
285    fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
286  }
287};
288
289template <>
290struct FuzzTraits<char> {
291  static void Fuzz(char* p, Fuzzer* fuzzer) {
292    fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
293  }
294};
295
296template <>
297struct FuzzTraits<unsigned char> {
298  static void Fuzz(unsigned char* p, Fuzzer* fuzzer) {
299    fuzzer->FuzzUChar(p);
300  }
301};
302
303template <>
304struct FuzzTraits<float> {
305  static void Fuzz(float* p, Fuzzer* fuzzer) {
306    fuzzer->FuzzFloat(p);
307  }
308};
309
310template <>
311struct FuzzTraits<double> {
312  static void Fuzz(double* p, Fuzzer* fuzzer) {
313    fuzzer->FuzzDouble(p);
314  }
315};
316
317template <>
318struct FuzzTraits<std::string> {
319  static void Fuzz(std::string* p, Fuzzer* fuzzer) {
320    fuzzer->FuzzString(p);
321  }
322};
323
324template <>
325struct FuzzTraits<base::string16> {
326  static void Fuzz(base::string16* p, Fuzzer* fuzzer) {
327    fuzzer->FuzzString16(p);
328  }
329};
330
331// Specializations to fuzz tuples.
332template <class A>
333struct FuzzTraits<Tuple1<A> > {
334  static void Fuzz(Tuple1<A>* p, Fuzzer* fuzzer) {
335    FuzzParam(&p->a, fuzzer);
336  }
337};
338
339template <class A, class B>
340struct 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
347template <class A, class B, class C>
348struct 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
356template <class A, class B, class C, class D>
357struct 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
366template <class A, class B, class C, class D, class E>
367struct 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.
378template <class A>
379struct 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
387template <class A, class B>
388struct 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
397template <class A, class B>
398struct 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
405template <>
406struct FuzzTraits<base::FileDescriptor> {
407  static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) {
408    FuzzParam(&p->fd, fuzzer);
409  }
410};
411
412template <>
413struct FuzzTraits<GURL> {
414  static void Fuzz(GURL *p, Fuzzer* fuzzer) {
415    FuzzParam(&p->possibly_invalid_spec(), fuzzer);
416  }
417};
418
419template <>
420struct 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
430template <>
431struct 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
441template <>
442struct 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
582typedef IPC::Message* (*FuzzFunction)(IPC::Message*, Fuzzer*);
583typedef 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
591void PopulateFuzzFunctionMap(FuzzFunctionMap *map) {
592#include "tools/ipc_fuzzer/message_lib/all_messages.h"
593}
594
595static 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
613namespace {
614
615const char kHelpSwitch[] = "help";
616const char kHelpSwitchHelp[] =
617    "show this message";
618
619const char kFrequencySwitch[] = "frequency";
620const char kFrequencySwitchHelp[] =
621    "probability of mutation; tweak every 1/|q| times.";
622
623const char kFuzzerNameSwitch[] = "fuzzer-name";
624const char kFuzzerNameSwitchHelp[] =
625    "select default or no-op fuzzer.";
626
627const char kPermuteSwitch[] = "permute";
628const char kPermuteSwitchHelp[] =
629    "Randomly shuffle the order of all messages.";
630
631const char kTypeListSwitch[] = "type-list";
632const char kTypeListSwitchHelp[] =
633    "explicit list of the only message-ids to mutate.";
634
635void 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
657int 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
727int main(int argc, char** argv) {
728  return ipc_fuzzer::MutateMain(argc, argv);
729}
730