Home | History | Annotate | Download | only in ipclist
      1 // Copyright (c) 2012 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 <algorithm>
      6 #include <ostream>
      7 #include <set>
      8 #include <vector>
      9 
     10 #include "base/command_line.h"
     11 #include "base/containers/hash_tables.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/singleton.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/pickle.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/string_util.h"
     18 #include "base/strings/utf_string_conversions.h"
     19 #include "base/threading/thread.h"
     20 #include "base/time/time.h"
     21 #include "chrome/common/all_messages.h"
     22 #include "content/common/all_messages.h"
     23 #include "ipc/ipc_message.h"
     24 #include "ipc/ipc_message_utils.h"
     25 #include "ipc/ipc_switches.h"
     26 #include "ipc/ipc_sync_channel.h"
     27 #include "ipc/ipc_sync_message.h"
     28 
     29 #if defined(OS_POSIX)
     30 #include <unistd.h>
     31 #endif
     32 
     33 namespace IPC {
     34 class Message;
     35 
     36 // Interface implemented by those who fuzz basic types.  The types all
     37 // correspond to the types which a pickle from base/pickle.h can pickle,
     38 // plus the floating point types.
     39 class Fuzzer {
     40  public:
     41   // Select a message for fuzzing.
     42   virtual bool FuzzThisMessage(const IPC::Message *msg) = 0;
     43 
     44   // Tweak individual values within a message.
     45   virtual void FuzzBool(bool* value) = 0;
     46   virtual void FuzzInt(int* value) = 0;
     47   virtual void FuzzLong(long* value) = 0;
     48   virtual void FuzzSize(size_t* value) = 0;
     49   virtual void FuzzUChar(unsigned char *value) = 0;
     50   virtual void FuzzUInt16(uint16* value) = 0;
     51   virtual void FuzzUInt32(uint32* value) = 0;
     52   virtual void FuzzInt64(int64* value) = 0;
     53   virtual void FuzzUInt64(uint64* value) = 0;
     54   virtual void FuzzFloat(float *value) = 0;
     55   virtual void FuzzDouble(double *value) = 0;
     56   virtual void FuzzString(std::string* value) = 0;
     57   virtual void FuzzWString(std::wstring* value) = 0;
     58   virtual void FuzzString16(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 }  // namespace IPC
     64 
     65 namespace {
     66 
     67 template <typename T>
     68 void FuzzIntegralType(T* value, unsigned int frequency) {
     69   if (rand() % frequency == 0) {
     70     switch (rand() % 4) {
     71       case 0: (*value) = 0; break;
     72       case 1: (*value)--; break;
     73       case 2: (*value)++; break;
     74       case 3: (*value) ^= rand(); break;
     75     }
     76   }
     77 }
     78 
     79 template <typename T>
     80 void FuzzStringType(T* value, unsigned int frequency,
     81                     const T& literal1, const T& literal2) {
     82   if (rand() % frequency == 0) {
     83     switch (rand() % 5) {
     84       case 4: (*value) = (*value) + (*value);   // FALLTHROUGH
     85       case 3: (*value) = (*value) + (*value);   // FALLTHROUGH
     86       case 2: (*value) = (*value) + (*value); break;
     87       case 1: (*value) += literal1; break;
     88       case 0: (*value) = literal2; break;
     89     }
     90   }
     91 }
     92 
     93 }  // namespace
     94 
     95 // One such fuzzer implementation.
     96 class DefaultFuzzer : public IPC::Fuzzer {
     97  public:
     98   static const int DEFAULT_FREQUENCY = 23;
     99 
    100   DefaultFuzzer() : frequency_(DEFAULT_FREQUENCY) {
    101     const char *env_var;
    102     if ((env_var = getenv("CHROME_IPC_FUZZING_LIST"))) {
    103       std::string str = std::string(env_var);
    104       size_t pos;
    105       while ((pos = str.find_first_of(',')) != std::string::npos) {
    106         message_set_.insert(atoi(str.substr(0, pos).c_str()));
    107         str = str.substr(pos+1);
    108       }
    109       message_set_.insert(atoi(str.c_str()));
    110     }
    111 
    112     if ((env_var = getenv("CHROME_IPC_FUZZING_SEED"))) {
    113       int new_seed = atoi(env_var);
    114       if (new_seed)
    115         srand(new_seed);
    116     }
    117 
    118     if ((env_var = getenv("CHROME_IPC_FUZZING_FREQUENCY"))) {
    119       unsigned int new_frequency = atoi(env_var);
    120       if (new_frequency)
    121         frequency_ = new_frequency;
    122     }
    123   }
    124 
    125   virtual ~DefaultFuzzer() {}
    126 
    127   virtual bool FuzzThisMessage(const IPC::Message *msg) OVERRIDE {
    128     return (message_set_.empty() ||
    129             std::find(message_set_.begin(),
    130                       message_set_.end(),
    131                       msg->type()) != message_set_.end());
    132   }
    133 
    134   virtual void FuzzBool(bool* value) OVERRIDE {
    135     if (rand() % frequency_ == 0)
    136       (*value) = !(*value);
    137   }
    138 
    139   virtual void FuzzInt(int* value) OVERRIDE {
    140     FuzzIntegralType<int>(value, frequency_);
    141   }
    142 
    143   virtual void FuzzLong(long* value) OVERRIDE {
    144     FuzzIntegralType<long>(value, frequency_);
    145   }
    146 
    147   virtual void FuzzSize(size_t* value) OVERRIDE {
    148     FuzzIntegralType<size_t>(value, frequency_);
    149   }
    150 
    151   virtual void FuzzUChar(unsigned char* value) OVERRIDE {
    152     FuzzIntegralType<unsigned char>(value, frequency_);
    153   }
    154 
    155   virtual void FuzzUInt16(uint16* value) OVERRIDE {
    156     FuzzIntegralType<uint16>(value, frequency_);
    157   }
    158 
    159   virtual void FuzzUInt32(uint32* value) OVERRIDE {
    160     FuzzIntegralType<uint32>(value, frequency_);
    161   }
    162 
    163   virtual void FuzzInt64(int64* value) OVERRIDE {
    164     FuzzIntegralType<int64>(value, frequency_);
    165   }
    166 
    167   virtual void FuzzUInt64(uint64* value) OVERRIDE {
    168     FuzzIntegralType<uint64>(value, frequency_);
    169   }
    170 
    171   virtual void FuzzFloat(float* value) OVERRIDE {
    172     if (rand() % frequency_ == 0)
    173       (*value) *= rand() / 1000000.0;
    174   }
    175 
    176   virtual void FuzzDouble(double* value) OVERRIDE {
    177     if (rand() % frequency_ == 0)
    178       (*value) *= rand() / 1000000.0;
    179   }
    180 
    181   virtual void FuzzString(std::string* value) OVERRIDE {
    182     FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
    183   }
    184 
    185   virtual void FuzzWString(std::wstring* value) OVERRIDE {
    186     FuzzStringType<std::wstring>(value, frequency_, L"BORKED", std::wstring());
    187   }
    188 
    189   virtual void FuzzString16(string16* value) OVERRIDE {
    190     FuzzStringType<string16>(value, frequency_,
    191                              WideToUTF16(L"BORKED"),
    192                              WideToUTF16(std::wstring()));
    193   }
    194 
    195   virtual void FuzzData(char* data, int length) OVERRIDE {
    196     if (rand() % frequency_ == 0) {
    197       for (int i = 0; i < length; ++i) {
    198         FuzzIntegralType<char>(&data[i], frequency_);
    199       }
    200     }
    201   }
    202 
    203   virtual void FuzzBytes(void* data, int data_len) OVERRIDE {
    204     FuzzData(static_cast<char*>(data), data_len);
    205   }
    206 
    207  private:
    208   std::set<int> message_set_;
    209   unsigned int frequency_;
    210 };
    211 
    212 
    213 // No-op fuzzer.  Rewrites each message unchanged to check if the message
    214 // re-assembly is legit.
    215 class NoOpFuzzer : public IPC::Fuzzer {
    216  public:
    217   NoOpFuzzer() {}
    218   virtual ~NoOpFuzzer() {}
    219 
    220   virtual bool FuzzThisMessage(const IPC::Message *msg) OVERRIDE {
    221     return true;
    222   }
    223 
    224   virtual void FuzzBool(bool* value) OVERRIDE {}
    225   virtual void FuzzInt(int* value) OVERRIDE {}
    226   virtual void FuzzLong(long* value) OVERRIDE {}
    227   virtual void FuzzSize(size_t* value) OVERRIDE {}
    228   virtual void FuzzUChar(unsigned char* value) OVERRIDE {}
    229   virtual void FuzzUInt16(uint16* value) OVERRIDE {}
    230   virtual void FuzzUInt32(uint32* value) OVERRIDE {}
    231   virtual void FuzzInt64(int64* value) OVERRIDE {}
    232   virtual void FuzzUInt64(uint64* value) OVERRIDE {}
    233   virtual void FuzzFloat(float* value) OVERRIDE {}
    234   virtual void FuzzDouble(double* value) OVERRIDE {}
    235   virtual void FuzzString(std::string* value) OVERRIDE {}
    236   virtual void FuzzWString(std::wstring* value) OVERRIDE {}
    237   virtual void FuzzString16(string16* value) OVERRIDE {}
    238   virtual void FuzzData(char* data, int length) OVERRIDE {}
    239   virtual void FuzzBytes(void* data, int data_len) OVERRIDE {}
    240 };
    241 
    242 class FuzzerFactory {
    243  public:
    244   static IPC::Fuzzer *NewFuzzer(const std::string& name) {
    245     if (name == "no-op")
    246       return new NoOpFuzzer();
    247     else
    248       return new DefaultFuzzer();
    249   }
    250 };
    251 
    252 // Partially-specialized class that knows how to fuzz a given type.
    253 template <class P>
    254 struct FuzzTraits {
    255   static void Fuzz(P* p, IPC::Fuzzer *fuzzer) {}
    256 };
    257 
    258 // Template function to invoke partially-specialized class method.
    259 template <class P>
    260 static void FuzzParam(P* p, IPC::Fuzzer* fuzzer) {
    261   FuzzTraits<P>::Fuzz(p, fuzzer);
    262 }
    263 
    264 // Specializations to fuzz primitive types.
    265 template <>
    266 struct FuzzTraits<bool> {
    267   static void Fuzz(bool* p, IPC::Fuzzer* fuzzer) {
    268     fuzzer->FuzzBool(p);
    269   }
    270 };
    271 
    272 template <>
    273 struct FuzzTraits<int> {
    274   static void Fuzz(int* p, IPC::Fuzzer* fuzzer) {
    275     fuzzer->FuzzInt(p);
    276   }
    277 };
    278 
    279 template <>
    280 struct FuzzTraits<unsigned int> {
    281   static void Fuzz(unsigned int* p, IPC::Fuzzer* fuzzer) {
    282     fuzzer->FuzzInt(reinterpret_cast<int*>(p));
    283   }
    284 };
    285 
    286 template <>
    287 struct FuzzTraits<long> {
    288   static void Fuzz(long* p, IPC::Fuzzer* fuzzer) {
    289     fuzzer->FuzzLong(p);
    290   }
    291 };
    292 
    293 template <>
    294 struct FuzzTraits<unsigned long> {
    295   static void Fuzz(unsigned long* p, IPC::Fuzzer* fuzzer) {
    296     fuzzer->FuzzLong(reinterpret_cast<long*>(p));
    297   }
    298 };
    299 
    300 template <>
    301 struct FuzzTraits<long long> {
    302   static void Fuzz(long long* p, IPC::Fuzzer* fuzzer) {
    303     fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
    304   }
    305 };
    306 
    307 template <>
    308 struct FuzzTraits<unsigned long long> {
    309   static void Fuzz(unsigned long long* p, IPC::Fuzzer* fuzzer) {
    310     fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
    311   }
    312 };
    313 
    314 template <>
    315 struct FuzzTraits<short> {
    316   static void Fuzz(short* p, IPC::Fuzzer* fuzzer) {
    317     fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
    318   }
    319 };
    320 
    321 template <>
    322 struct FuzzTraits<unsigned short> {
    323   static void Fuzz(unsigned short* p, IPC::Fuzzer* fuzzer) {
    324     fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
    325   }
    326 };
    327 
    328 template <>
    329 struct FuzzTraits<char> {
    330   static void Fuzz(char* p, IPC::Fuzzer* fuzzer) {
    331     fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
    332   }
    333 };
    334 
    335 template <>
    336 struct FuzzTraits<unsigned char> {
    337   static void Fuzz(unsigned char* p, IPC::Fuzzer* fuzzer) {
    338     fuzzer->FuzzUChar(p);
    339   }
    340 };
    341 
    342 template <>
    343 struct FuzzTraits<float> {
    344   static void Fuzz(float* p, IPC::Fuzzer* fuzzer) {
    345     fuzzer->FuzzFloat(p);
    346   }
    347 };
    348 
    349 template <>
    350 struct FuzzTraits<double> {
    351   static void Fuzz(double* p, IPC::Fuzzer* fuzzer) {
    352     fuzzer->FuzzDouble(p);
    353   }
    354 };
    355 
    356 template <>
    357 struct FuzzTraits<std::string> {
    358   static void Fuzz(std::string* p, IPC::Fuzzer* fuzzer) {
    359     fuzzer->FuzzString(p);
    360   }
    361 };
    362 
    363 template <>
    364 struct FuzzTraits<std::wstring> {
    365   static void Fuzz(std::wstring* p, IPC::Fuzzer* fuzzer) {
    366     fuzzer->FuzzWString(p);
    367   }
    368 };
    369 
    370 template <>
    371 struct FuzzTraits<string16> {
    372   static void Fuzz(string16* p, IPC::Fuzzer* fuzzer) {
    373     fuzzer->FuzzString16(p);
    374   }
    375 };
    376 
    377 // Specializations to fuzz tuples.
    378 template <class A>
    379 struct FuzzTraits<Tuple1<A> > {
    380   static void Fuzz(Tuple1<A>* p, IPC::Fuzzer* fuzzer) {
    381     FuzzParam(&p->a, fuzzer);
    382   }
    383 };
    384 
    385 template <class A, class B>
    386 struct FuzzTraits<Tuple2<A, B> > {
    387   static void Fuzz(Tuple2<A, B>* p, IPC::Fuzzer* fuzzer) {
    388     FuzzParam(&p->a, fuzzer);
    389     FuzzParam(&p->b, fuzzer);
    390   }
    391 };
    392 
    393 template <class A, class B, class C>
    394 struct FuzzTraits<Tuple3<A, B, C> > {
    395   static void Fuzz(Tuple3<A, B, C>* p, IPC::Fuzzer* fuzzer) {
    396     FuzzParam(&p->a, fuzzer);
    397     FuzzParam(&p->b, fuzzer);
    398     FuzzParam(&p->c, fuzzer);
    399   }
    400 };
    401 
    402 template <class A, class B, class C, class D>
    403 struct FuzzTraits<Tuple4<A, B, C, D> > {
    404   static void Fuzz(Tuple4<A, B, C, D>* p, IPC::Fuzzer* fuzzer) {
    405     FuzzParam(&p->a, fuzzer);
    406     FuzzParam(&p->b, fuzzer);
    407     FuzzParam(&p->c, fuzzer);
    408     FuzzParam(&p->d, fuzzer);
    409   }
    410 };
    411 
    412 template <class A, class B, class C, class D, class E>
    413 struct FuzzTraits<Tuple5<A, B, C, D, E> > {
    414   static void Fuzz(Tuple5<A, B, C, D, E>* p, IPC::Fuzzer* fuzzer) {
    415     FuzzParam(&p->a, fuzzer);
    416     FuzzParam(&p->b, fuzzer);
    417     FuzzParam(&p->c, fuzzer);
    418     FuzzParam(&p->d, fuzzer);
    419     FuzzParam(&p->e, fuzzer);
    420   }
    421 };
    422 
    423 // Specializations to fuzz containers.
    424 template <class A>
    425 struct FuzzTraits<std::vector<A> > {
    426   static void Fuzz(std::vector<A>* p, IPC::Fuzzer* fuzzer) {
    427     for (size_t i = 0; i < p->size(); ++i) {
    428       FuzzParam(&p->at(i), fuzzer);
    429     }
    430   }
    431 };
    432 
    433 template <class A, class B>
    434 struct FuzzTraits<std::map<A, B> > {
    435   static void Fuzz(std::map<A, B>* p, IPC::Fuzzer* fuzzer) {
    436     typename std::map<A, B>::iterator it;
    437     for (it = p->begin(); it != p->end(); ++it) {
    438       FuzzParam(&it->second, fuzzer);
    439     }
    440   }
    441 };
    442 
    443 template <class A, class B>
    444 struct FuzzTraits<std::pair<A, B> > {
    445   static void Fuzz(std::pair<A, B>* p, IPC::Fuzzer* fuzzer) {
    446     FuzzParam(&p->second, fuzzer);
    447   }
    448 };
    449 
    450 // Specializations to fuzz hand-coded tyoes
    451 template <>
    452 struct FuzzTraits<base::FileDescriptor> {
    453   static void Fuzz(base::FileDescriptor* p, IPC::Fuzzer* fuzzer) {
    454     FuzzParam(&p->fd, fuzzer);
    455   }
    456 };
    457 
    458 template <>
    459 struct FuzzTraits<GURL> {
    460   static void Fuzz(GURL *p, IPC::Fuzzer* fuzzer) {
    461     FuzzParam(&p->possibly_invalid_spec(), fuzzer);
    462   }
    463 };
    464 
    465 template <>
    466 struct FuzzTraits<gfx::Point> {
    467   static void Fuzz(gfx::Point *p, IPC::Fuzzer* fuzzer) {
    468     int x = p->x();
    469     int y = p->y();
    470     FuzzParam(&x, fuzzer);
    471     FuzzParam(&y, fuzzer);
    472     p->SetPoint(x, y);
    473   }
    474 };
    475 
    476 template <>
    477 struct FuzzTraits<gfx::Size> {
    478   static void Fuzz(gfx::Size *p, IPC::Fuzzer* fuzzer) {
    479     int w = p->width();
    480     int h = p->height();
    481     FuzzParam(&w, fuzzer);
    482     FuzzParam(&h, fuzzer);
    483     p->SetSize(w, h);
    484   }
    485 };
    486 
    487 template <>
    488 struct FuzzTraits<gfx::Rect> {
    489   static void Fuzz(gfx::Rect *p, IPC::Fuzzer* fuzzer) {
    490     gfx::Point origin = p->origin();
    491     gfx::Size  size = p->size();
    492     FuzzParam(&origin, fuzzer);
    493     FuzzParam(&size, fuzzer);
    494     p->set_origin(origin);
    495     p->set_size(size);
    496   }
    497 };
    498 
    499 // Means for updating message id in pickles.
    500 class PickleCracker : public Pickle {
    501  public:
    502   static void CopyMessageID(PickleCracker *dst, PickleCracker *src) {
    503     memcpy(dst->mutable_payload(), src->payload(), sizeof(int));
    504   }
    505 };
    506 
    507 // Redefine macros to generate fuzzing from traits declarations.
    508 // Null out all the macros that need nulling.
    509 #include "ipc/ipc_message_null_macros.h"
    510 
    511 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
    512 #undef IPC_STRUCT_BEGIN_WITH_PARENT
    513 #undef IPC_STRUCT_MEMBER
    514 #undef IPC_STRUCT_END
    515 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent)\
    516   IPC_STRUCT_TRAITS_BEGIN(struct_name)
    517 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
    518 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
    519 
    520 // Set up so next include will generate fuzz trait classes.
    521 #undef IPC_STRUCT_TRAITS_BEGIN
    522 #undef IPC_STRUCT_TRAITS_MEMBER
    523 #undef IPC_STRUCT_TRAITS_PARENT
    524 #undef IPC_STRUCT_TRAITS_END
    525 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
    526   template <> \
    527   struct FuzzTraits<struct_name> { \
    528     static void Fuzz(struct_name *p, IPC::Fuzzer* fuzzer) { \
    529 
    530 #define IPC_STRUCT_TRAITS_MEMBER(name) \
    531       FuzzParam(&p->name, fuzzer);
    532 
    533 #define IPC_STRUCT_TRAITS_PARENT(type) \
    534       FuzzParam(static_cast<type*>(p), fuzzer);
    535 
    536 #define IPC_STRUCT_TRAITS_END() \
    537     } \
    538   };
    539 
    540 #undef IPC_ENUM_TRAITS_VALIDATE
    541 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
    542   template <> \
    543   struct FuzzTraits<enum_name> { \
    544     static void Fuzz(enum_name* p, IPC::Fuzzer* fuzzer) { \
    545       FuzzParam(reinterpret_cast<int*>(p), fuzzer); \
    546     } \
    547   };
    548 
    549 // Bring them into existence.
    550 #include "chrome/common/all_messages.h"
    551 #include "content/common/all_messages.h"
    552 
    553 // Redefine macros to generate fuzzing funtions
    554 #include "ipc/ipc_message_null_macros.h"
    555 #undef IPC_MESSAGE_DECL
    556 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist)           \
    557   IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist)
    558 
    559 #define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist)                 \
    560   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    561     return NULL;                                                            \
    562   }
    563 
    564 #define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist)                  \
    565   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    566     return NULL;                                                            \
    567   }
    568 
    569 #define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist)                 \
    570   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    571     name* real_msg = static_cast<name*>(msg);                               \
    572     IPC_TUPLE_IN_##in ilist p;                                              \
    573     name::Read(real_msg, &p);                                               \
    574     FuzzParam(&p, fuzzer);                                                  \
    575     return new name(IPC_MEMBERS_IN_##in(p));                                \
    576   }
    577 
    578 #define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist)                  \
    579   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    580     name* real_msg = static_cast<name*>(msg);                               \
    581     IPC_TUPLE_IN_##in ilist p;                                              \
    582     name::Read(real_msg, &p);                                               \
    583     FuzzParam(&p, fuzzer);                                                  \
    584     return new name(msg->routing_id()                                       \
    585                     IPC_COMMA_##in                                          \
    586                     IPC_MEMBERS_IN_##in(p));                                \
    587   }
    588 
    589 #define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist)                  \
    590   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    591     name* real_msg = static_cast<name*>(msg);                               \
    592     IPC_TUPLE_IN_##in ilist p;                                              \
    593     name::ReadSendParam(real_msg, &p);                                      \
    594     FuzzParam(&p, fuzzer);                                                  \
    595     name* new_msg = new name(IPC_MEMBERS_IN_##in(p)                         \
    596                              IPC_COMMA_AND_##out(IPC_COMMA_##in)            \
    597                              IPC_MEMBERS_OUT_##out());                      \
    598     PickleCracker::CopyMessageID(                                           \
    599         reinterpret_cast<PickleCracker *>(new_msg),                         \
    600         reinterpret_cast<PickleCracker *>(real_msg));                       \
    601     return new_msg;                                                         \
    602   }
    603 
    604 
    605 #define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist)                   \
    606   IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
    607     name* real_msg = static_cast<name*>(msg);                               \
    608     IPC_TUPLE_IN_##in ilist p;                                              \
    609     name::ReadSendParam(real_msg, &p);                                      \
    610     FuzzParam(&p, fuzzer);                                                  \
    611     name* new_msg = new name(msg->routing_id()                              \
    612                              IPC_COMMA_OR_##out(IPC_COMMA_##in)             \
    613                              IPC_MEMBERS_IN_##in(p)                         \
    614                              IPC_COMMA_AND_##out(IPC_COMMA_##in)            \
    615                              IPC_MEMBERS_OUT_##out());                      \
    616     PickleCracker::CopyMessageID(                                           \
    617         reinterpret_cast<PickleCracker *>(new_msg),                         \
    618         reinterpret_cast<PickleCracker *>(real_msg));                       \
    619     return new_msg;                                                         \
    620   }
    621 
    622 #define IPC_MEMBERS_IN_0(p)
    623 #define IPC_MEMBERS_IN_1(p)                 p.a
    624 #define IPC_MEMBERS_IN_2(p)                 p.a, p.b
    625 #define IPC_MEMBERS_IN_3(p)                 p.a, p.b, p.c
    626 #define IPC_MEMBERS_IN_4(p)                 p.a, p.b, p.c, p.d
    627 #define IPC_MEMBERS_IN_5(p)                 p.a, p.b, p.c, p.d, p.e
    628 
    629 #define IPC_MEMBERS_OUT_0()
    630 #define IPC_MEMBERS_OUT_1()                NULL
    631 #define IPC_MEMBERS_OUT_2()                NULL, NULL
    632 #define IPC_MEMBERS_OUT_3()                NULL, NULL, NULL
    633 #define IPC_MEMBERS_OUT_4()                NULL, NULL, NULL, NULL
    634 #define IPC_MEMBERS_OUT_5()                NULL, NULL, NULL, NULL, NULL
    635 
    636 #include "chrome/common/all_messages.h"
    637 #include "content/common/all_messages.h"
    638 
    639 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, IPC::Fuzzer*);
    640 typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap;
    641 
    642 // Redefine macros to register fuzzing functions into map.
    643 #include "ipc/ipc_message_null_macros.h"
    644 #undef IPC_MESSAGE_DECL
    645 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
    646   (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name;
    647 
    648 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) {
    649 #include "chrome/common/all_messages.h"
    650 #include "content/common/all_messages.h"
    651 }
    652 
    653 class ipcfuzz : public IPC::ChannelProxy::OutgoingMessageFilter {
    654  public:
    655   ipcfuzz() {
    656     const char* env_var = getenv("CHROME_IPC_FUZZING_KIND");
    657     fuzzer_ = FuzzerFactory::NewFuzzer(env_var ? env_var : "");
    658     PopulateFuzzFunctionMap(&fuzz_function_map_);
    659   }
    660 
    661   virtual IPC::Message* Rewrite(IPC::Message* message) OVERRIDE {
    662     if (fuzzer_ && fuzzer_->FuzzThisMessage(message)) {
    663       FuzzFunctionMap::iterator it = fuzz_function_map_.find(message->type());
    664       if (it != fuzz_function_map_.end()) {
    665         IPC::Message* fuzzed_message = (*it->second)(message, fuzzer_);
    666         if (fuzzed_message)  {
    667           delete message;
    668           message = fuzzed_message;
    669         }
    670       }
    671     }
    672     return message;
    673   }
    674 
    675  private:
    676   IPC::Fuzzer* fuzzer_;
    677   FuzzFunctionMap fuzz_function_map_;
    678 };
    679 
    680 ipcfuzz g_ipcfuzz;
    681 
    682 // Entry point avoiding mangled names.
    683 extern "C" {
    684   __attribute__((visibility("default")))
    685   IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void);
    686 }
    687 
    688 IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void) {
    689   return &g_ipcfuzz;
    690 }
    691