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 <vector>
     12 
     13 #include "base/command_line.h"
     14 #include "base/pickle.h"
     15 #include "base/strings/string_util.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "ipc/ipc_message.h"
     19 #include "ipc/ipc_message_utils.h"
     20 #include "ipc/ipc_switches.h"
     21 #include "ipc/ipc_sync_channel.h"
     22 #include "ipc/ipc_sync_message.h"
     23 #include "tools/ipc_fuzzer/message_lib/message_file.h"
     24 #include "tools/ipc_fuzzer/mutate/rand_util.h"
     25 
     26 #if defined(OS_POSIX)
     27 #include <unistd.h>
     28 #endif
     29 
     30 // First include of message files to provide basic type.
     31 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
     32 #include "ipc/ipc_message_null_macros.h"
     33 
     34 namespace IPC {
     35 class Message;
     36 }  // namespace IPC
     37 
     38 namespace {
     39 // For breaking deep recursion.
     40 int g_depth = 0;
     41 }  // namespace
     42 
     43 namespace ipc_fuzzer {
     44 
     45 // Interface implemented by those who generate basic types.  The types all
     46 // correspond to the types which a pickle from base/pickle.h can pickle,
     47 // plus the floating point types.
     48 class Generator {
     49  public:
     50   virtual void GenerateBool(bool* value) = 0;
     51   virtual void GenerateInt(int* value) = 0;
     52   virtual void GenerateLong(long* value) = 0;
     53   virtual void GenerateSize(size_t* value) = 0;
     54   virtual void GenerateUChar(unsigned char *value) = 0;
     55   virtual void GenerateUInt16(uint16* value) = 0;
     56   virtual void GenerateUInt32(uint32* value) = 0;
     57   virtual void GenerateInt64(int64* value) = 0;
     58   virtual void GenerateUInt64(uint64* value) = 0;
     59   virtual void GenerateFloat(float *value) = 0;
     60   virtual void GenerateDouble(double *value) = 0;
     61   virtual void GenerateString(std::string* value) = 0;
     62   virtual void GenerateString16(base::string16* value) = 0;
     63   virtual void GenerateData(char* data, int length) = 0;
     64   virtual void GenerateBytes(void* data, int data_len) = 0;
     65 };
     66 
     67 template <typename T>
     68 void GenerateIntegralType(T* value) {
     69   switch (RandInRange(16)) {
     70     case 0:
     71       *value = 0;
     72       break;
     73     case 1:
     74       *value = 1;
     75       break;
     76     case 2:
     77       *value = -1;
     78       break;
     79     case 3:
     80       *value = 2;
     81       break;
     82     default:
     83       *value = static_cast<T>(RandU64());
     84       break;
     85   }
     86 }
     87 
     88 template <typename T>
     89 void GenerateFloatingType(T* value) {
     90   *value = RandDouble();
     91 }
     92 
     93 template <typename T>
     94 void GenerateStringType(T* value) {
     95   T temp_string;
     96   size_t length = RandInRange(300);
     97   for (size_t i = 0; i < length; ++i)
     98     temp_string += RandInRange(256);
     99   *value = temp_string;
    100 }
    101 
    102 class GeneratorImpl : public Generator {
    103  public:
    104   GeneratorImpl() {}
    105   virtual ~GeneratorImpl() {}
    106 
    107   virtual void GenerateBool(bool* value) OVERRIDE {
    108     *value = RandInRange(2);
    109   }
    110 
    111   virtual void GenerateInt(int* value) OVERRIDE {
    112     GenerateIntegralType<int>(value);
    113   }
    114 
    115   virtual void GenerateLong(long* value) OVERRIDE {
    116     GenerateIntegralType<long>(value);
    117   }
    118 
    119   virtual void GenerateSize(size_t* value) OVERRIDE {
    120     GenerateIntegralType<size_t>(value);
    121   }
    122 
    123   virtual void GenerateUChar(unsigned char* value) OVERRIDE {
    124     GenerateIntegralType<unsigned char>(value);
    125   }
    126 
    127   virtual void GenerateUInt16(uint16* value) OVERRIDE {
    128     GenerateIntegralType<uint16>(value);
    129   }
    130 
    131   virtual void GenerateUInt32(uint32* value) OVERRIDE {
    132     GenerateIntegralType<uint32>(value);
    133   }
    134 
    135   virtual void GenerateInt64(int64* value) OVERRIDE {
    136     GenerateIntegralType<int64>(value);
    137   }
    138 
    139   virtual void GenerateUInt64(uint64* value) OVERRIDE {
    140     GenerateIntegralType<uint64>(value);
    141   }
    142 
    143   virtual void GenerateFloat(float* value) OVERRIDE {
    144     GenerateFloatingType<float>(value);
    145   }
    146 
    147   virtual void GenerateDouble(double* value) OVERRIDE {
    148     GenerateFloatingType<double>(value);
    149   }
    150 
    151   virtual void GenerateString(std::string* value) OVERRIDE {
    152     GenerateStringType<std::string>(value);
    153   }
    154 
    155   virtual void GenerateString16(base::string16* value) OVERRIDE {
    156     GenerateStringType<base::string16>(value);
    157   }
    158 
    159   virtual void GenerateData(char* data, int length) OVERRIDE {
    160     for (int i = 0; i < length; ++i) {
    161       GenerateIntegralType<char>(&data[i]);
    162     }
    163   }
    164 
    165   virtual void GenerateBytes(void* data, int data_len) OVERRIDE {
    166     GenerateData(static_cast<char*>(data), data_len);
    167   }
    168 };
    169 
    170 // Partially-specialized class that knows how to generate a given type.
    171 template <class P>
    172 struct GenerateTraits {
    173   static bool Generate(P* p, Generator *generator) {
    174     // This is the catch-all for types we don't have enough information
    175     // to generate.
    176     std::cerr << "Can't handle " << __PRETTY_FUNCTION__ << "\n";
    177     return false;
    178   }
    179 };
    180 
    181 // Template function to invoke partially-specialized class method.
    182 template <class P>
    183 static bool GenerateParam(P* p, Generator* generator) {
    184   return GenerateTraits<P>::Generate(p, generator);
    185 }
    186 
    187 // Specializations to generate primitive types.
    188 template <>
    189 struct GenerateTraits<bool> {
    190   static bool Generate(bool* p, Generator* generator) {
    191     generator->GenerateBool(p);
    192     return true;
    193   }
    194 };
    195 
    196 template <>
    197 struct GenerateTraits<int> {
    198   static bool Generate(int* p, Generator* generator) {
    199     generator->GenerateInt(p);
    200     return true;
    201   }
    202 };
    203 
    204 template <>
    205 struct GenerateTraits<unsigned int> {
    206   static bool Generate(unsigned int* p, Generator* generator) {
    207     generator->GenerateInt(reinterpret_cast<int*>(p));
    208     return true;
    209   }
    210 };
    211 
    212 template <>
    213 struct GenerateTraits<long> {
    214   static bool Generate(long* p, Generator* generator) {
    215     generator->GenerateLong(p);
    216     return true;
    217   }
    218 };
    219 
    220 template <>
    221 struct GenerateTraits<unsigned long> {
    222   static bool Generate(unsigned long* p, Generator* generator) {
    223     generator->GenerateLong(reinterpret_cast<long*>(p));
    224     return true;
    225   }
    226 };
    227 
    228 template <>
    229 struct GenerateTraits<long long> {
    230   static bool Generate(long long* p, Generator* generator) {
    231     generator->GenerateInt64(reinterpret_cast<int64*>(p));
    232     return true;
    233   }
    234 };
    235 
    236 template <>
    237 struct GenerateTraits<unsigned long long> {
    238   static bool Generate(unsigned long long* p, Generator* generator) {
    239     generator->GenerateInt64(reinterpret_cast<int64*>(p));
    240     return true;
    241   }
    242 };
    243 
    244 template <>
    245 struct GenerateTraits<short> {
    246   static bool Generate(short* p, Generator* generator) {
    247     generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    248     return true;
    249   }
    250 };
    251 
    252 template <>
    253 struct GenerateTraits<unsigned short> {
    254   static bool Generate(unsigned short* p, Generator* generator) {
    255     generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    256     return true;
    257   }
    258 };
    259 
    260 template <>
    261 struct GenerateTraits<char> {
    262   static bool Generate(char* p, Generator* generator) {
    263     generator->GenerateUChar(reinterpret_cast<unsigned char*>(p));
    264     return true;
    265   }
    266 };
    267 
    268 template <>
    269 struct GenerateTraits<unsigned char> {
    270   static bool Generate(unsigned char* p, Generator* generator) {
    271     generator->GenerateUChar(p);
    272     return true;
    273   }
    274 };
    275 
    276 template <>
    277 struct GenerateTraits<float> {
    278   static bool Generate(float* p, Generator* generator) {
    279     generator->GenerateFloat(p);
    280     return true;
    281   }
    282 };
    283 
    284 template <>
    285 struct GenerateTraits<double> {
    286   static bool Generate(double* p, Generator* generator) {
    287     generator->GenerateDouble(p);
    288     return true;
    289   }
    290 };
    291 
    292 template <>
    293 struct GenerateTraits<std::string> {
    294   static bool Generate(std::string* p, Generator* generator) {
    295     generator->GenerateString(p);
    296     return true;
    297   }
    298 };
    299 
    300 template <>
    301 struct GenerateTraits<base::string16> {
    302   static bool Generate(base::string16* p, Generator* generator) {
    303     generator->GenerateString16(p);
    304     return true;
    305   }
    306 };
    307 
    308 // Specializations to generate tuples.
    309 template <>
    310 struct GenerateTraits<Tuple0> {
    311   static bool Generate(Tuple0* p, Generator* generator) {
    312     return true;
    313   }
    314 };
    315 
    316 template <class A>
    317 struct GenerateTraits<Tuple1<A> > {
    318   static bool Generate(Tuple1<A>* p, Generator* generator) {
    319     return GenerateParam(&p->a, generator);
    320   }
    321 };
    322 
    323 template <class A, class B>
    324 struct GenerateTraits<Tuple2<A, B> > {
    325   static bool Generate(Tuple2<A, B>* p, Generator* generator) {
    326     return
    327         GenerateParam(&p->a, generator) &&
    328         GenerateParam(&p->b, generator);
    329   }
    330 };
    331 
    332 template <class A, class B, class C>
    333 struct GenerateTraits<Tuple3<A, B, C> > {
    334   static bool Generate(Tuple3<A, B, C>* p, Generator* generator) {
    335     return
    336         GenerateParam(&p->a, generator) &&
    337         GenerateParam(&p->b, generator) &&
    338         GenerateParam(&p->c, generator);
    339   }
    340 };
    341 
    342 template <class A, class B, class C, class D>
    343 struct GenerateTraits<Tuple4<A, B, C, D> > {
    344   static bool Generate(Tuple4<A, B, C, D>* p, Generator* generator) {
    345     return
    346         GenerateParam(&p->a, generator) &&
    347         GenerateParam(&p->b, generator) &&
    348         GenerateParam(&p->c, generator) &&
    349         GenerateParam(&p->d, generator);
    350   }
    351 };
    352 
    353 template <class A, class B, class C, class D, class E>
    354 struct GenerateTraits<Tuple5<A, B, C, D, E> > {
    355   static bool Generate(Tuple5<A, B, C, D, E>* p, Generator* generator) {
    356     return
    357         GenerateParam(&p->a, generator) &&
    358         GenerateParam(&p->b, generator) &&
    359         GenerateParam(&p->c, generator) &&
    360         GenerateParam(&p->d, generator) &&
    361         GenerateParam(&p->e, generator);
    362   }
    363 };
    364 
    365 // Specializations to generate containers.
    366 template <class A>
    367 struct GenerateTraits<std::vector<A> > {
    368   static bool Generate(std::vector<A>* p, Generator* generator) {
    369     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    370     p->resize(count);
    371     for (size_t i = 0; i < count; ++i) {
    372       if (!GenerateParam(&p->at(i), generator)) {
    373         --g_depth;
    374         return false;
    375       }
    376     }
    377     --g_depth;
    378     return true;
    379   }
    380 };
    381 
    382 template <class A>
    383 struct GenerateTraits<std::set<A> > {
    384   static bool Generate(std::set<A>* p, Generator* generator) {
    385     static int g_depth = 0;
    386     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    387     A a;
    388     for (size_t i = 0; i < count; ++i) {
    389       if (!GenerateParam(&a, generator)) {
    390         --g_depth;
    391         return false;
    392       }
    393       p->insert(a);
    394     }
    395     --g_depth;
    396     return true;
    397   }
    398 };
    399 
    400 
    401 template <class A, class B>
    402 struct GenerateTraits<std::map<A, B> > {
    403   static bool Generate(std::map<A, B>* p, Generator* generator) {
    404     static int g_depth = 0;
    405     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    406     std::pair<A, B> place_holder;
    407     for (size_t i = 0; i < count; ++i) {
    408       if (!GenerateParam(&place_holder, generator)) {
    409         --g_depth;
    410         return false;
    411       }
    412       p->insert(place_holder);
    413     }
    414     --g_depth;
    415     return true;
    416   }
    417 };
    418 
    419 template <class A, class B>
    420 struct GenerateTraits<std::pair<A, B> > {
    421   static bool Generate(std::pair<A, B>* p, Generator* generator) {
    422     return
    423         GenerateParam(&p->first, generator) &&
    424         GenerateParam(&p->second, generator);
    425   }
    426 };
    427 
    428 // Specializations to generate hand-coded tyoes
    429 template <>
    430 struct GenerateTraits<base::NullableString16> {
    431   static bool Generate(base::NullableString16* p, Generator* generator) {
    432     *p = base::NullableString16();
    433     return true;
    434   }
    435 };
    436 
    437 template <>
    438 struct GenerateTraits<base::FileDescriptor> {
    439   static bool Generate(base::FileDescriptor* p, Generator* generator) {
    440     // I don't think we can generate real ones due to check on construct.
    441     p->fd = -1;
    442     return true;
    443   }
    444 };
    445 
    446 template <>
    447 struct GenerateTraits<base::FilePath> {
    448   static bool Generate(base::FilePath* p, Generator* generator) {
    449     const char path_chars[] = "ACz0/.~:";
    450     size_t count = RandInRange(60);
    451     std::string random_path;
    452     for (size_t i = 0; i < count; ++i)
    453       random_path += path_chars[RandInRange(sizeof(path_chars) - 1)];
    454     *p = base::FilePath(random_path);
    455     return true;
    456   }
    457 };
    458 
    459 template <>
    460 struct GenerateTraits<base::File::Error> {
    461   static bool Generate(base::File::Error* p, Generator* generator) {
    462     int temporary;
    463     if (!GenerateParam(&temporary, generator))
    464       return false;
    465     *p = static_cast<base::File::Error>(temporary);
    466     return true;
    467   }
    468 };
    469 
    470 template <>
    471 struct GenerateTraits<base::File::Info> {
    472   static bool Generate(base::File::Info* p, Generator* generator) {
    473     double last_modified;
    474     double last_accessed;
    475     double creation_time;
    476     if (!GenerateParam(&p->size, generator))
    477       return false;
    478     if (!GenerateParam(&p->is_directory, generator))
    479       return false;
    480     if (!GenerateParam(&last_modified, generator))
    481       return false;
    482     if (GenerateParam(&last_accessed, generator))
    483       return false;
    484     if (GenerateParam(&creation_time, generator))
    485       return false;
    486     p->last_modified = base::Time::FromDoubleT(last_modified);
    487     p->last_accessed = base::Time::FromDoubleT(last_accessed);
    488     p->creation_time = base::Time::FromDoubleT(creation_time);
    489     return true;
    490   }
    491 };
    492 
    493 template <>
    494 struct GenerateTraits<base::Time> {
    495   static bool Generate(base::Time* p, Generator* generator) {
    496     *p = base::Time::FromInternalValue(RandU64());
    497     return true;
    498   }
    499 };
    500 
    501 template <>
    502 struct GenerateTraits<base::TimeDelta> {
    503   static bool Generate(base::TimeDelta* p, Generator* generator) {
    504     *p = base::TimeDelta::FromInternalValue(RandU64());
    505     return true;
    506   }
    507 };
    508 
    509 template <>
    510 struct GenerateTraits<base::TimeTicks> {
    511   static bool Generate(base::TimeTicks* p, Generator* generator) {
    512     *p = base::TimeTicks::FromInternalValue(RandU64());
    513     return true;
    514   }
    515 };
    516 
    517 template <>
    518 struct GenerateTraits<base::ListValue> {
    519   static bool Generate(base::ListValue* p, Generator* generator) {
    520     ++g_depth;
    521     size_t list_length = g_depth > 3 ? 0 : RandInRange(8);
    522     for (size_t index = 0; index < list_length; ++index) {
    523       switch (RandInRange(8))
    524       {
    525         case base::Value::TYPE_BOOLEAN: {
    526           bool tmp;
    527           generator->GenerateBool(&tmp);
    528           p->Set(index, new base::FundamentalValue(tmp));
    529           break;
    530         }
    531         case base::Value::TYPE_INTEGER: {
    532           int tmp;
    533           generator->GenerateInt(&tmp);
    534           p->Set(index, new base::FundamentalValue(tmp));
    535           break;
    536         }
    537         case base::Value::TYPE_DOUBLE: {
    538           double tmp;
    539           generator->GenerateDouble(&tmp);
    540           p->Set(index, new base::FundamentalValue(tmp));
    541           break;
    542         }
    543         case base::Value::TYPE_STRING: {
    544           std::string tmp;
    545           generator->GenerateString(&tmp);
    546           p->Set(index, new base::StringValue(tmp));
    547           break;
    548         }
    549         case base::Value::TYPE_BINARY: {
    550           char tmp[200];
    551           size_t bin_length = RandInRange(sizeof(tmp));
    552           generator->GenerateData(tmp, bin_length);
    553           p->Set(index,
    554                  base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
    555           break;
    556         }
    557         case base::Value::TYPE_DICTIONARY: {
    558           base::DictionaryValue* tmp = new base::DictionaryValue();
    559           GenerateParam(tmp, generator);
    560           p->Set(index, tmp);
    561           break;
    562         }
    563         case base::Value::TYPE_LIST: {
    564           base::ListValue* tmp = new base::ListValue();
    565           GenerateParam(tmp, generator);
    566           p->Set(index, tmp);
    567           break;
    568         }
    569         case base::Value::TYPE_NULL:
    570         default:
    571           break;
    572       }
    573     }
    574     --g_depth;
    575     return true;
    576   }
    577 };
    578 
    579 template <>
    580 struct GenerateTraits<base::DictionaryValue> {
    581   static bool Generate(base::DictionaryValue* p, Generator* generator) {
    582     ++g_depth;
    583     size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
    584     for (size_t index = 0; index < dict_length; ++index) {
    585       std::string property;
    586       generator->GenerateString(&property);
    587       switch (RandInRange(8))
    588       {
    589         case base::Value::TYPE_BOOLEAN: {
    590           bool tmp;
    591           generator->GenerateBool(&tmp);
    592           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
    593           break;
    594         }
    595         case base::Value::TYPE_INTEGER: {
    596           int tmp;
    597           generator->GenerateInt(&tmp);
    598           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
    599           break;
    600         }
    601         case base::Value::TYPE_DOUBLE: {
    602           double tmp;
    603           generator->GenerateDouble(&tmp);
    604           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
    605           break;
    606         }
    607         case base::Value::TYPE_STRING: {
    608           std::string tmp;
    609           generator->GenerateString(&tmp);
    610           p->SetWithoutPathExpansion(property, new base::StringValue(tmp));
    611           break;
    612         }
    613         case base::Value::TYPE_BINARY: {
    614           char tmp[200];
    615           size_t bin_length = RandInRange(sizeof(tmp));
    616           generator->GenerateData(tmp, bin_length);
    617           p->SetWithoutPathExpansion(
    618               property,
    619               base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
    620           break;
    621         }
    622         case base::Value::TYPE_DICTIONARY: {
    623           base::DictionaryValue* tmp = new base::DictionaryValue();
    624           GenerateParam(tmp, generator);
    625           p->SetWithoutPathExpansion(property, tmp);
    626           break;
    627         }
    628         case base::Value::TYPE_LIST: {
    629           base::ListValue* tmp = new base::ListValue();
    630           GenerateParam(tmp, generator);
    631           p->SetWithoutPathExpansion(property, tmp);
    632           break;
    633         }
    634         case base::Value::TYPE_NULL:
    635         default:
    636           break;
    637       }
    638     }
    639     --g_depth;
    640     return true;
    641   }
    642 };
    643 
    644 template <>
    645 struct GenerateTraits<GURL> {
    646   static bool Generate(GURL *p, Generator* generator) {
    647     const char url_chars[] = "Ahtp0:/.?+\%&#";
    648     size_t count = RandInRange(100);
    649     std::string random_url;
    650     for (size_t i = 0; i < count; ++i)
    651       random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
    652     int selector = RandInRange(10);
    653     if (selector == 0)
    654       random_url = std::string("http://") + random_url;
    655     else if (selector == 1)
    656       random_url = std::string("file://") + random_url;
    657     else if (selector == 2)
    658       random_url = std::string("javascript:") + random_url;
    659     else if (selector == 2)
    660       random_url = std::string("data:") + random_url;
    661     *p = GURL(random_url);
    662     return true;
    663   }
    664 };
    665 
    666 // FIXME: Actually generate something.
    667 template <>
    668 struct GenerateTraits<SkBitmap> {
    669   static bool Generate(SkBitmap* p, Generator* generator) {
    670     *p = SkBitmap();
    671     return true;
    672   }
    673 };
    674 
    675 template <>
    676 struct GenerateTraits<IPC::ChannelHandle> {
    677   static bool Generate(IPC::ChannelHandle* p, Generator* generator) {
    678     return
    679         GenerateParam(&p->name, generator) &&
    680         GenerateParam(&p->socket, generator);
    681   }
    682 };
    683 
    684 template <>
    685 struct GenerateTraits<cc::CompositorFrame> {
    686   // FIXME: this should actually generate something
    687   static bool Generate(cc::CompositorFrame* p, Generator* generator) {
    688     return true;
    689   }
    690 };
    691 
    692 template <>
    693 struct GenerateTraits<cc::CompositorFrameAck> {
    694   // FIXME: this should actually generate something
    695   static bool Generate(cc::CompositorFrameAck* p, Generator* generator) {
    696     return true;
    697   }
    698 };
    699 
    700 template <>
    701 struct GenerateTraits<content::IndexedDBKey> {
    702   static bool Generate(content::IndexedDBKey* p, Generator* generator) {
    703     ++g_depth;
    704     blink::WebIDBKeyType web_type =
    705         static_cast<blink::WebIDBKeyType>(RandInRange(7));
    706     switch (web_type)
    707     {
    708       case blink::WebIDBKeyTypeArray: {
    709         size_t length = g_depth > 3 ? 0 : RandInRange(4);
    710         std::vector<content::IndexedDBKey> array;
    711         array.resize(length);
    712         for (size_t i = 0; i < length; ++i) {
    713           if (!GenerateParam(&array[i], generator))
    714             return false;
    715         }
    716         *p = content::IndexedDBKey(array);
    717         return true;
    718       }
    719       case blink::WebIDBKeyTypeBinary: {
    720         std::string binary;
    721         if (!GenerateParam(&binary, generator))
    722           return false;
    723         *p = content::IndexedDBKey(binary);
    724         return true;
    725       }
    726       case blink::WebIDBKeyTypeString: {
    727         base::string16 string;
    728         if (!GenerateParam(&string, generator))
    729           return false;
    730         *p = content::IndexedDBKey(string);
    731         return true;
    732       }
    733       case blink::WebIDBKeyTypeDate:
    734       case blink::WebIDBKeyTypeNumber: {
    735         double number;
    736         if (!GenerateParam(&number, generator))
    737           return false;
    738         *p = content::IndexedDBKey(number, web_type);
    739         return true;
    740       }
    741       case blink::WebIDBKeyTypeInvalid:
    742       case blink::WebIDBKeyTypeNull: {
    743         *p = content::IndexedDBKey(web_type);
    744         return true;
    745       }
    746       default:
    747         NOTREACHED();
    748         return false;
    749     }
    750     --g_depth;
    751     return true;
    752   }
    753 };
    754 
    755 template <>
    756 struct GenerateTraits<content::IndexedDBKeyRange> {
    757   static bool Generate(content::IndexedDBKeyRange *p, Generator* generator) {
    758     content::IndexedDBKey lower;
    759     content::IndexedDBKey upper;
    760     bool lower_open;
    761     bool upper_open;
    762     if (!GenerateParam(&lower, generator))
    763       return false;
    764     if (!GenerateParam(&upper, generator))
    765       return false;
    766     if (!GenerateParam(&lower_open, generator))
    767       return false;
    768     if (!GenerateParam(&upper_open, generator))
    769       return false;
    770     *p = content::IndexedDBKeyRange(lower, upper, lower_open, upper_open);
    771     return true;
    772   }
    773 };
    774 
    775 template <>
    776 struct GenerateTraits<content::IndexedDBKeyPath> {
    777   static bool Generate(content::IndexedDBKeyPath *p, Generator* generator) {
    778     switch (RandInRange(3)) {
    779       case 0: {
    780         std::vector<base::string16> array;
    781         if (!GenerateParam(&array, generator))
    782           return false;
    783         *p = content::IndexedDBKeyPath(array);
    784         break;
    785       }
    786       case 1: {
    787         base::string16 string;
    788         if (!GenerateParam(&string, generator))
    789           return false;
    790         *p = content::IndexedDBKeyPath(string);
    791         break;
    792       }
    793       case 2: {
    794         *p = content::IndexedDBKeyPath();
    795         break;
    796       }
    797     }
    798     return true;
    799   }
    800 };
    801 
    802 template <>
    803 struct GenerateTraits<content::PageState> {
    804   static bool Generate(content::PageState *p, Generator* generator) {
    805     std::string junk;
    806     if (!GenerateParam(&junk, generator))
    807       return false;
    808     *p = content::PageState::CreateFromEncodedData(junk);
    809     return true;
    810   }
    811 };
    812 
    813 template <>
    814 struct GenerateTraits<gpu::Mailbox> {
    815   static bool Generate(gpu::Mailbox *p, Generator* generator) {
    816     generator->GenerateBytes(p->name, sizeof(p->name));
    817     return true;
    818   }
    819 };
    820 
    821 template <>
    822 struct GenerateTraits<media::AudioParameters> {
    823   static bool Generate(media::AudioParameters *p, Generator* generator) {
    824     int format;
    825     int channel_layout;
    826     int sample_rate;
    827     int bits_per_sample;
    828     int frames_per_buffer;
    829     int channels;
    830     int effects;
    831     if (!GenerateParam(&format, generator))
    832       return false;
    833     if (!GenerateParam(&channel_layout, generator))
    834       return false;
    835     if (!GenerateParam(&sample_rate, generator))
    836       return false;
    837     if (!GenerateParam(&bits_per_sample, generator))
    838       return false;
    839     if (!GenerateParam(&frames_per_buffer, generator))
    840       return false;
    841     if (!GenerateParam(&channels, generator))
    842       return false;
    843     if (!GenerateParam(&effects, generator))
    844       return false;
    845     media::AudioParameters params(
    846         static_cast<media::AudioParameters::Format>(format),
    847         static_cast<media::ChannelLayout>(channel_layout),
    848         channels,
    849         sample_rate,
    850         bits_per_sample,
    851         frames_per_buffer,
    852         effects);
    853     *p = params;
    854     return true;
    855   }
    856 };
    857 
    858 template <>
    859 struct GenerateTraits<media::VideoCaptureFormat> {
    860   static bool Generate(media::VideoCaptureFormat *p, Generator* generator) {
    861     int frame_size_width;
    862     int frame_size_height;
    863     int pixel_format;
    864     if (!GenerateParam(&frame_size_height, generator))
    865       return false;
    866     if (!GenerateParam(&frame_size_width, generator))
    867       return false;
    868     if (!GenerateParam(&pixel_format, generator))
    869       return false;
    870     if (!GenerateParam(&p->frame_rate, generator))
    871       return false;
    872     p->frame_size.SetSize(frame_size_width, frame_size_height);
    873     p->pixel_format = static_cast<media::VideoPixelFormat>(pixel_format);
    874     return true;
    875   }
    876 };
    877 
    878 
    879 template <>
    880 struct GenerateTraits<net::LoadTimingInfo> {
    881   static bool Generate(net::LoadTimingInfo *p, Generator* generator) {
    882     return
    883         GenerateParam(&p->socket_log_id, generator) &&
    884         GenerateParam(&p->socket_reused, generator) &&
    885         GenerateParam(&p->request_start_time, generator) &&
    886         GenerateParam(&p->request_start, generator) &&
    887         GenerateParam(&p->proxy_resolve_start, generator) &&
    888         GenerateParam(&p->proxy_resolve_end, generator) &&
    889         GenerateParam(&p->connect_timing.dns_start, generator) &&
    890         GenerateParam(&p->connect_timing.dns_end, generator) &&
    891         GenerateParam(&p->connect_timing.connect_start, generator) &&
    892         GenerateParam(&p->connect_timing.connect_end, generator) &&
    893         GenerateParam(&p->connect_timing.ssl_start, generator) &&
    894         GenerateParam(&p->connect_timing.ssl_end, generator) &&
    895         GenerateParam(&p->send_start, generator) &&
    896         GenerateParam(&p->send_end, generator) &&
    897         GenerateParam(&p->receive_headers_end, generator);
    898   }
    899 };
    900 
    901 template <>
    902 struct GenerateTraits<net::HostPortPair> {
    903   static bool Generate(net::HostPortPair *p, Generator* generator) {
    904     std::string host;
    905     uint16 port;
    906     if (!GenerateParam(&host, generator))
    907       return false;
    908     if (!GenerateParam(&port, generator))
    909       return false;
    910     p->set_host(host);
    911     p->set_port(port);
    912     return true;
    913   }
    914 };
    915 
    916 template <>
    917 struct GenerateTraits<net::IPEndPoint> {
    918   static bool Generate(net::IPEndPoint *p, Generator* generator) {
    919     net::IPAddressNumber address;
    920     int port;
    921     if (!GenerateParam(&address, generator))
    922       return false;
    923     if (!GenerateParam(&port, generator))
    924       return false;
    925     net::IPEndPoint ip_endpoint(address, port);
    926     *p = ip_endpoint;
    927     return true;
    928   }
    929 };
    930 
    931 template <>
    932 struct GenerateTraits<gfx::Point> {
    933   static bool Generate(gfx::Point *p, Generator* generator) {
    934     int x;
    935     int y;
    936     if (!GenerateParam(&x, generator))
    937       return false;
    938     if (!GenerateParam(&y, generator))
    939       return false;
    940     p->SetPoint(x, y);
    941     return true;
    942   }
    943 };
    944 
    945 template <>
    946 struct GenerateTraits<gfx::PointF> {
    947   static bool Generate(gfx::PointF *p, Generator* generator) {
    948     float x;
    949     float y;
    950     if (!GenerateParam(&x, generator))
    951       return false;
    952     if (!GenerateParam(&y, generator))
    953       return false;
    954     p->SetPoint(x, y);
    955     return true;
    956   }
    957 };
    958 
    959 template <>
    960 struct GenerateTraits<gfx::Size> {
    961   static bool Generate(gfx::Size *p, Generator* generator) {
    962     int w;
    963     int h;
    964     if (!GenerateParam(&w, generator))
    965       return false;
    966     if (!GenerateParam(&h, generator))
    967       return false;
    968     p->SetSize(w, h);
    969     return true;
    970   }
    971 };
    972 
    973 template <>
    974 struct GenerateTraits<gfx::SizeF> {
    975   static bool Generate(gfx::SizeF *p, Generator* generator) {
    976     float w;
    977     float h;
    978     if (!GenerateParam(&w, generator))
    979       return false;
    980     if (!GenerateParam(&h, generator))
    981       return false;
    982     p->SetSize(w, h);
    983     return true;
    984   }
    985 };
    986 
    987 template <>
    988 struct GenerateTraits<gfx::Rect> {
    989   static bool Generate(gfx::Rect *p, Generator* generator) {
    990     gfx::Point origin;
    991     gfx::Size  size;
    992     if (!GenerateParam(&origin, generator))
    993       return false;
    994     if (!GenerateParam(&size, generator))
    995       return false;
    996     p->set_origin(origin);
    997     p->set_size(size);
    998     return true;
    999   }
   1000 };
   1001 
   1002 template <>
   1003 struct GenerateTraits<gfx::RectF> {
   1004   static bool Generate(gfx::RectF *p, Generator* generator) {
   1005     gfx::PointF origin;
   1006     gfx::SizeF  size;
   1007     if (!GenerateParam(&origin, generator))
   1008       return false;
   1009     if (!GenerateParam(&size, generator))
   1010       return false;
   1011     p->set_origin(origin);
   1012     p->set_size(size);
   1013     return true;
   1014   }
   1015 };
   1016 
   1017 template <>
   1018 struct GenerateTraits<gfx::Range> {
   1019   static bool Generate(gfx::Range *p, Generator* generator) {
   1020     size_t start;
   1021     size_t end;
   1022     if (!GenerateParam(&start, generator))
   1023       return false;
   1024     if (!GenerateParam(&end, generator))
   1025       return false;
   1026     *p = gfx::Range(start, end);
   1027     return true;
   1028   }
   1029 };
   1030 
   1031 template <>
   1032 struct GenerateTraits<gfx::Vector2d> {
   1033   static bool Generate(gfx::Vector2d *p, Generator* generator) {
   1034     int x;
   1035     int y;
   1036     if (!GenerateParam(&x, generator))
   1037       return false;
   1038     if (!GenerateParam(&y, generator))
   1039       return false;
   1040     *p = gfx::Vector2d(x, y);
   1041     return true;
   1042   }
   1043 };
   1044 
   1045 template <>
   1046 struct GenerateTraits<gfx::Vector2dF> {
   1047   static bool Generate(gfx::Vector2dF *p, Generator* generator) {
   1048     float x;
   1049     float y;
   1050     if (!GenerateParam(&x, generator))
   1051       return false;
   1052     if (!GenerateParam(&y, generator))
   1053       return false;
   1054     *p = gfx::Vector2dF(x, y);
   1055     return true;
   1056   }
   1057 };
   1058 
   1059 // PP_ traits.
   1060 template <>
   1061 struct GenerateTraits<PP_Bool> {
   1062   static bool Generate(PP_Bool *p, Generator* generator) {
   1063     bool tmp;
   1064     if (!GenerateParam(&tmp, generator))
   1065       return false;
   1066     *p = PP_FromBool(tmp);
   1067     return true;
   1068   }
   1069 };
   1070 
   1071 template <>
   1072 struct GenerateTraits<PP_NetAddress_Private> {
   1073   static bool Generate(PP_NetAddress_Private *p, Generator* generator) {
   1074     p->size = RandInRange(sizeof(p->data) + 1);
   1075     generator->GenerateBytes(&p->data, p->size);
   1076     return true;
   1077   }
   1078 };
   1079 
   1080 template <>
   1081 struct GenerateTraits<ppapi::HostResource> {
   1082   static bool Generate(ppapi::HostResource *p, Generator* generator) {
   1083     PP_Instance instance;
   1084     PP_Resource resource;
   1085     if (!GenerateParam(&instance, generator))
   1086       return false;
   1087     if (!GenerateParam(&resource, generator))
   1088       return false;
   1089     p->SetHostResource(instance, resource);
   1090     return true;
   1091   }
   1092 };
   1093 
   1094 template <>
   1095 struct GenerateTraits<ppapi::PepperFilePath> {
   1096   static bool Generate(ppapi::PepperFilePath *p, Generator* generator) {
   1097     unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
   1098     base::FilePath path;
   1099     if (!GenerateParam(&path, generator))
   1100       return false;
   1101     *p = ppapi::PepperFilePath(
   1102         static_cast<ppapi::PepperFilePath::Domain>(domain), path);
   1103     return true;
   1104   }
   1105 };
   1106 
   1107 template <>
   1108 struct GenerateTraits<ppapi::PpapiPermissions> {
   1109   static bool Generate(ppapi::PpapiPermissions *p, Generator* generator) {
   1110     uint32_t bits;
   1111     if (!GenerateParam(&bits, generator))
   1112       return false;
   1113     *p = ppapi::PpapiPermissions(bits);
   1114     return true;
   1115   }
   1116 };
   1117 
   1118 template <>
   1119 struct GenerateTraits<ppapi::SocketOptionData> {
   1120   static bool Generate(ppapi::SocketOptionData *p, Generator* generator) {
   1121     // FIXME: we can do better here.
   1122     int32 temp;
   1123     if (!GenerateParam(&temp, generator))
   1124       return false;
   1125     p->SetInt32(temp);
   1126     return true;
   1127   }
   1128 };
   1129 
   1130 // Redefine macros to generate generating from traits declarations.
   1131 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
   1132 #undef IPC_STRUCT_BEGIN
   1133 #undef IPC_STRUCT_BEGIN_WITH_PARENT
   1134 #undef IPC_STRUCT_MEMBER
   1135 #undef IPC_STRUCT_END
   1136 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
   1137   IPC_STRUCT_BEGIN(struct_name)
   1138 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
   1139 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
   1140 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
   1141 
   1142 // Set up so next include will generate generate trait classes.
   1143 #undef IPC_STRUCT_TRAITS_BEGIN
   1144 #undef IPC_STRUCT_TRAITS_MEMBER
   1145 #undef IPC_STRUCT_TRAITS_PARENT
   1146 #undef IPC_STRUCT_TRAITS_END
   1147 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
   1148   template <> \
   1149   struct GenerateTraits<struct_name> { \
   1150     static bool Generate(struct_name *p, Generator* generator) {
   1151 
   1152 #define IPC_STRUCT_TRAITS_MEMBER(name) \
   1153       if (!GenerateParam(&p->name, generator)) \
   1154         return false;
   1155 
   1156 #define IPC_STRUCT_TRAITS_PARENT(type) \
   1157       if (!GenerateParam(static_cast<type*>(p), generator)) \
   1158         return false;
   1159 
   1160 #define IPC_STRUCT_TRAITS_END() \
   1161       return true; \
   1162     } \
   1163   };
   1164 
   1165 // If |condition| isn't met, the messsge will fail to serialize. Try
   1166 // increasingly smaller ranges until we find one that happens to meet
   1167 // the condition, or fail trying.
   1168 #undef IPC_ENUM_TRAITS_VALIDATE
   1169 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition)             \
   1170   template <>                                                      \
   1171   struct GenerateTraits<enum_name> {                               \
   1172     static bool Generate(enum_name* p, Generator* generator) {     \
   1173       for (int shift = 30; shift; --shift) {                       \
   1174         for (int tries = 0; tries < 2; ++tries) {                  \
   1175           int value = RandInRange(1 << shift);                     \
   1176           if (condition) {                                         \
   1177             *reinterpret_cast<int*>(p) = value;                    \
   1178             return true;                                           \
   1179           }                                                        \
   1180         }                                                          \
   1181       }                                                            \
   1182       std::cerr << "failed to satisfy " << #condition << "\n";     \
   1183       return false;                                                \
   1184     }                                                              \
   1185   };
   1186 
   1187 // Bring them into existence.
   1188 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
   1189 #include "ipc/ipc_message_null_macros.h"
   1190 
   1191 // Redefine macros to generate generating funtions
   1192 #undef IPC_MESSAGE_DECL
   1193 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist)       \
   1194   IPC_##kind##_##type##_GENERATE(name, in, out, ilist, olist)
   1195 
   1196 #define IPC_EMPTY_CONTROL_GENERATE(name, in, out, ilist, olist)         \
   1197   IPC::Message* generator_for_##name(Generator* generator) {            \
   1198     return new name();                                                  \
   1199   }
   1200 
   1201 #define IPC_EMPTY_ROUTED_GENERATE(name, in, out, ilist, olist)          \
   1202   IPC::Message* generator_for_##name(Generator* generator) {            \
   1203     return new name(RandInRange(MAX_FAKE_ROUTING_ID));                  \
   1204   }
   1205 
   1206 #define IPC_ASYNC_CONTROL_GENERATE(name, in, out, ilist, olist)         \
   1207   IPC::Message* generator_for_##name(Generator* generator) {            \
   1208     IPC_TUPLE_IN_##in ilist p;                                          \
   1209     if (GenerateParam(&p, generator)) {                                 \
   1210       return new name(IPC_MEMBERS_IN_##in(p));                          \
   1211     }                                                                   \
   1212     std::cerr << "Don't know how to generate " << #name << "\n";        \
   1213     return 0;                                                           \
   1214   }
   1215 
   1216 #define IPC_ASYNC_ROUTED_GENERATE(name, in, out, ilist, olist)          \
   1217   IPC::Message* generator_for_##name(Generator* generator) {            \
   1218     IPC_TUPLE_IN_##in ilist p;                                          \
   1219     if (GenerateParam(&p, generator)) {                                 \
   1220       return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
   1221                       IPC_COMMA_##in                                    \
   1222                       IPC_MEMBERS_IN_##in(p));                          \
   1223     }                                                                   \
   1224     std::cerr << "Don't know how to generate " << #name << "\n";        \
   1225     return 0;                                                           \
   1226   }
   1227 
   1228 #define IPC_SYNC_CONTROL_GENERATE(name, in, out, ilist, olist)          \
   1229   IPC::Message* generator_for_##name(Generator* generator) {            \
   1230     IPC_TUPLE_IN_##in ilist p;                                          \
   1231     if (GenerateParam(&p, generator)) {                                 \
   1232       return new name(IPC_MEMBERS_IN_##in(p)                            \
   1233                       IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
   1234                       IPC_MEMBERS_OUT_##out());                         \
   1235     }                                                                   \
   1236     std::cerr << "Don't know how to generate " << #name << "\n";        \
   1237     return 0;                                                           \
   1238   }
   1239 
   1240 #define IPC_SYNC_ROUTED_GENERATE(name, in, out, ilist, olist)           \
   1241   IPC::Message* generator_for_##name(Generator* generator) {            \
   1242     IPC_TUPLE_IN_##in ilist p;                                          \
   1243     if (GenerateParam(&p, generator)) {                                 \
   1244       return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
   1245                       IPC_COMMA_OR_##out(IPC_COMMA_##in)                \
   1246                       IPC_MEMBERS_IN_##in(p)                            \
   1247                       IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
   1248                       IPC_MEMBERS_OUT_##out());                         \
   1249     }                                                                   \
   1250     std::cerr << "Don't know how to generate " << #name << "\n";        \
   1251     return 0;                                                           \
   1252   }
   1253 
   1254 #define MAX_FAKE_ROUTING_ID 15
   1255 
   1256 #define IPC_MEMBERS_IN_0(p)
   1257 #define IPC_MEMBERS_IN_1(p) p.a
   1258 #define IPC_MEMBERS_IN_2(p) p.a, p.b
   1259 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
   1260 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
   1261 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e
   1262 
   1263 #define IPC_MEMBERS_OUT_0()
   1264 #define IPC_MEMBERS_OUT_1() NULL
   1265 #define IPC_MEMBERS_OUT_2() NULL, NULL
   1266 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL
   1267 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL
   1268 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL
   1269 
   1270 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
   1271 #include "ipc/ipc_message_null_macros.h"
   1272 
   1273 typedef IPC::Message* (*GeneratorFunction)(Generator*);
   1274 typedef std::vector<GeneratorFunction> GeneratorFunctionVector;
   1275 
   1276 void PopulateGeneratorFunctionVector(
   1277     GeneratorFunctionVector *function_vector) {
   1278 #undef IPC_MESSAGE_DECL
   1279 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
   1280   function_vector->push_back(generator_for_##name);
   1281 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
   1282 }
   1283 
   1284 static const char kCountSwitch[] = "count";
   1285 static const char kHelpSwitch[] = "help";
   1286 
   1287 int GenerateMain(int argc, char** argv) {
   1288   CommandLine::Init(argc, argv);
   1289   CommandLine* cmd = CommandLine::ForCurrentProcess();
   1290   CommandLine::StringVector args = cmd->GetArgs();
   1291 
   1292   if (args.size() != 1 || cmd->HasSwitch(kHelpSwitch)) {
   1293     std::cerr << "Usage: ipc_fuzzer_generate [--help] [--count=n] outfile\n";
   1294     return EXIT_FAILURE;
   1295   }
   1296   std::string output_file_name = args[0];
   1297 
   1298   int message_count = 1000;
   1299   if (cmd->HasSwitch(kCountSwitch))
   1300     message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
   1301 
   1302   InitRand();
   1303 
   1304   GeneratorFunctionVector function_vector;
   1305   PopulateGeneratorFunctionVector(&function_vector);
   1306   std::cerr << "Counted " << function_vector.size()
   1307             << " distinct messages present in chrome.\n";
   1308 
   1309   Generator* generator = new GeneratorImpl();
   1310   MessageVector message_vector;
   1311 
   1312   int bad_count = 0;
   1313   if (message_count < 0) {
   1314     // Enumerate them all.
   1315     for (size_t i = 0; i < function_vector.size(); ++i) {
   1316       if (IPC::Message* new_message = (*function_vector[i])(generator))
   1317         message_vector.push_back(new_message);
   1318       else
   1319         bad_count += 1;
   1320     }
   1321   } else {
   1322     // Generate a random batch.
   1323     for (int i = 0; i < message_count; ++i) {
   1324       size_t index = RandInRange(function_vector.size());
   1325       if (IPC::Message* new_message = (*function_vector[index])(generator))
   1326         message_vector.push_back(new_message);
   1327       else
   1328         bad_count += 1;
   1329     }
   1330   }
   1331 
   1332   std::cerr << "Failed to generate " << bad_count << " messages.\n";
   1333 
   1334   if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
   1335     return EXIT_FAILURE;
   1336 
   1337   return EXIT_SUCCESS;
   1338 }
   1339 
   1340 }  // namespace ipc_fuzzer
   1341 
   1342 int main(int argc, char** argv) {
   1343   return ipc_fuzzer::GenerateMain(argc, argv);
   1344 }
   1345