Home | History | Annotate | Download | only in mutate
      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 }
    730