Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / ipc_fuzzer / mutate / generate.cc
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 }