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
34namespace IPC {
35class Message;
36}  // namespace IPC
37
38namespace {
39// For breaking deep recursion.
40int g_depth = 0;
41}  // namespace
42
43namespace 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.
48class 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
67template <typename T>
68void 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
88template <typename T>
89void GenerateFloatingType(T* value) {
90  *value = RandDouble();
91}
92
93template <typename T>
94void 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
102class 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.
171template <class P>
172struct 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.
182template <class P>
183static bool GenerateParam(P* p, Generator* generator) {
184  return GenerateTraits<P>::Generate(p, generator);
185}
186
187// Specializations to generate primitive types.
188template <>
189struct GenerateTraits<bool> {
190  static bool Generate(bool* p, Generator* generator) {
191    generator->GenerateBool(p);
192    return true;
193  }
194};
195
196template <>
197struct GenerateTraits<int> {
198  static bool Generate(int* p, Generator* generator) {
199    generator->GenerateInt(p);
200    return true;
201  }
202};
203
204template <>
205struct 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
212template <>
213struct GenerateTraits<long> {
214  static bool Generate(long* p, Generator* generator) {
215    generator->GenerateLong(p);
216    return true;
217  }
218};
219
220template <>
221struct 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
228template <>
229struct 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
236template <>
237struct 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
244template <>
245struct GenerateTraits<short> {
246  static bool Generate(short* p, Generator* generator) {
247    generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
248    return true;
249  }
250};
251
252template <>
253struct 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
260template <>
261struct GenerateTraits<char> {
262  static bool Generate(char* p, Generator* generator) {
263    generator->GenerateUChar(reinterpret_cast<unsigned char*>(p));
264    return true;
265  }
266};
267
268template <>
269struct GenerateTraits<unsigned char> {
270  static bool Generate(unsigned char* p, Generator* generator) {
271    generator->GenerateUChar(p);
272    return true;
273  }
274};
275
276template <>
277struct GenerateTraits<float> {
278  static bool Generate(float* p, Generator* generator) {
279    generator->GenerateFloat(p);
280    return true;
281  }
282};
283
284template <>
285struct GenerateTraits<double> {
286  static bool Generate(double* p, Generator* generator) {
287    generator->GenerateDouble(p);
288    return true;
289  }
290};
291
292template <>
293struct GenerateTraits<std::string> {
294  static bool Generate(std::string* p, Generator* generator) {
295    generator->GenerateString(p);
296    return true;
297  }
298};
299
300template <>
301struct 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.
309template <>
310struct GenerateTraits<Tuple0> {
311  static bool Generate(Tuple0* p, Generator* generator) {
312    return true;
313  }
314};
315
316template <class A>
317struct GenerateTraits<Tuple1<A> > {
318  static bool Generate(Tuple1<A>* p, Generator* generator) {
319    return GenerateParam(&p->a, generator);
320  }
321};
322
323template <class A, class B>
324struct 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
332template <class A, class B, class C>
333struct 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
342template <class A, class B, class C, class D>
343struct 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
353template <class A, class B, class C, class D, class E>
354struct 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.
366template <class A>
367struct 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
382template <class A>
383struct 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
401template <class A, class B>
402struct 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
419template <class A, class B>
420struct 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
429template <>
430struct GenerateTraits<base::NullableString16> {
431  static bool Generate(base::NullableString16* p, Generator* generator) {
432    *p = base::NullableString16();
433    return true;
434  }
435};
436
437template <>
438struct 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
446template <>
447struct 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
459template <>
460struct 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
470template <>
471struct 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
493template <>
494struct GenerateTraits<base::Time> {
495  static bool Generate(base::Time* p, Generator* generator) {
496    *p = base::Time::FromInternalValue(RandU64());
497    return true;
498  }
499};
500
501template <>
502struct GenerateTraits<base::TimeDelta> {
503  static bool Generate(base::TimeDelta* p, Generator* generator) {
504    *p = base::TimeDelta::FromInternalValue(RandU64());
505    return true;
506  }
507};
508
509template <>
510struct GenerateTraits<base::TimeTicks> {
511  static bool Generate(base::TimeTicks* p, Generator* generator) {
512    *p = base::TimeTicks::FromInternalValue(RandU64());
513    return true;
514  }
515};
516
517template <>
518struct 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
579template <>
580struct 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
644template <>
645struct 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.
667template <>
668struct GenerateTraits<SkBitmap> {
669  static bool Generate(SkBitmap* p, Generator* generator) {
670    *p = SkBitmap();
671    return true;
672  }
673};
674
675template <>
676struct 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
684template <>
685struct 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
692template <>
693struct 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
700template <>
701struct 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
755template <>
756struct 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
775template <>
776struct 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
802template <>
803struct 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
813template <>
814struct 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
821template <>
822struct 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
858template <>
859struct 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
879template <>
880struct 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
901template <>
902struct 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
916template <>
917struct 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
931template <>
932struct 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
945template <>
946struct 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
959template <>
960struct 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
973template <>
974struct 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
987template <>
988struct 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
1002template <>
1003struct 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
1017template <>
1018struct 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
1031template <>
1032struct 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
1045template <>
1046struct 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.
1060template <>
1061struct 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
1071template <>
1072struct 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
1080template <>
1081struct 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
1094template <>
1095struct 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
1107template <>
1108struct 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
1118template <>
1119struct 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
1273typedef IPC::Message* (*GeneratorFunction)(Generator*);
1274typedef std::vector<GeneratorFunction> GeneratorFunctionVector;
1275
1276void 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
1284static const char kCountSwitch[] = "count";
1285static const char kHelpSwitch[] = "help";
1286
1287int 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
1342int main(int argc, char** argv) {
1343  return ipc_fuzzer::GenerateMain(argc, argv);
1344}
1345