Blink roll 174933:174969
[chromium-blink-merge.git] / tools / ipc_fuzzer / mutate / generate.cc
blob9ed43b78dc0452b1d35f6a5e7ec3eb1681b47743
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.
5 #include <stdlib.h>
7 #include <algorithm>
8 #include <iostream>
9 #include <ostream>
10 #include <set>
11 #include <vector>
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"
26 #if defined(OS_POSIX)
27 #include <unistd.h>
28 #endif
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"
34 namespace IPC {
35 class Message;
36 } // namespace IPC
38 namespace {
39 // For breaking deep recursion.
40 int g_depth = 0;
41 } // namespace
43 namespace ipc_fuzzer {
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;
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;
88 template <typename T>
89 void GenerateFloatingType(T* value) {
90 *value = RandDouble();
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;
102 class GeneratorImpl : public Generator {
103 public:
104 GeneratorImpl() {}
105 virtual ~GeneratorImpl() {}
107 virtual void GenerateBool(bool* value) OVERRIDE {
108 *value = RandInRange(2);
111 virtual void GenerateInt(int* value) OVERRIDE {
112 GenerateIntegralType<int>(value);
115 virtual void GenerateLong(long* value) OVERRIDE {
116 GenerateIntegralType<long>(value);
119 virtual void GenerateSize(size_t* value) OVERRIDE {
120 GenerateIntegralType<size_t>(value);
123 virtual void GenerateUChar(unsigned char* value) OVERRIDE {
124 GenerateIntegralType<unsigned char>(value);
127 virtual void GenerateUInt16(uint16* value) OVERRIDE {
128 GenerateIntegralType<uint16>(value);
131 virtual void GenerateUInt32(uint32* value) OVERRIDE {
132 GenerateIntegralType<uint32>(value);
135 virtual void GenerateInt64(int64* value) OVERRIDE {
136 GenerateIntegralType<int64>(value);
139 virtual void GenerateUInt64(uint64* value) OVERRIDE {
140 GenerateIntegralType<uint64>(value);
143 virtual void GenerateFloat(float* value) OVERRIDE {
144 GenerateFloatingType<float>(value);
147 virtual void GenerateDouble(double* value) OVERRIDE {
148 GenerateFloatingType<double>(value);
151 virtual void GenerateString(std::string* value) OVERRIDE {
152 GenerateStringType<std::string>(value);
155 virtual void GenerateString16(base::string16* value) OVERRIDE {
156 GenerateStringType<base::string16>(value);
159 virtual void GenerateData(char* data, int length) OVERRIDE {
160 for (int i = 0; i < length; ++i) {
161 GenerateIntegralType<char>(&data[i]);
165 virtual void GenerateBytes(void* data, int data_len) OVERRIDE {
166 GenerateData(static_cast<char*>(data), data_len);
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;
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);
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;
196 template <>
197 struct GenerateTraits<int> {
198 static bool Generate(int* p, Generator* generator) {
199 generator->GenerateInt(p);
200 return true;
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;
212 template <>
213 struct GenerateTraits<long> {
214 static bool Generate(long* p, Generator* generator) {
215 generator->GenerateLong(p);
216 return true;
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;
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;
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;
244 template <>
245 struct GenerateTraits<short> {
246 static bool Generate(short* p, Generator* generator) {
247 generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
248 return true;
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;
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;
268 template <>
269 struct GenerateTraits<unsigned char> {
270 static bool Generate(unsigned char* p, Generator* generator) {
271 generator->GenerateUChar(p);
272 return true;
276 template <>
277 struct GenerateTraits<float> {
278 static bool Generate(float* p, Generator* generator) {
279 generator->GenerateFloat(p);
280 return true;
284 template <>
285 struct GenerateTraits<double> {
286 static bool Generate(double* p, Generator* generator) {
287 generator->GenerateDouble(p);
288 return true;
292 template <>
293 struct GenerateTraits<std::string> {
294 static bool Generate(std::string* p, Generator* generator) {
295 generator->GenerateString(p);
296 return true;
300 template <>
301 struct GenerateTraits<base::string16> {
302 static bool Generate(base::string16* p, Generator* generator) {
303 generator->GenerateString16(p);
304 return true;
308 // Specializations to generate tuples.
309 template <>
310 struct GenerateTraits<Tuple0> {
311 static bool Generate(Tuple0* p, Generator* generator) {
312 return true;
316 template <class A>
317 struct GenerateTraits<Tuple1<A> > {
318 static bool Generate(Tuple1<A>* p, Generator* generator) {
319 return GenerateParam(&p->a, generator);
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);
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);
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);
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);
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;
377 --g_depth;
378 return true;
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;
393 p->insert(a);
395 --g_depth;
396 return true;
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;
412 p->insert(place_holder);
414 --g_depth;
415 return true;
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);
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;
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;
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;
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;
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;
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;
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;
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;
517 template <>
518 struct GenerateTraits<base::PlatformFileInfo> {
519 static bool Generate(base::PlatformFileInfo* p, Generator* generator) {
520 return
521 GenerateParam(&p->size, generator) &&
522 GenerateParam(&p->is_directory, generator) &&
523 GenerateParam(&p->last_modified, generator) &&
524 GenerateParam(&p->last_accessed, generator) &&
525 GenerateParam(&p->creation_time, generator);
530 template <>
531 struct GenerateTraits<base::ListValue> {
532 static bool Generate(base::ListValue* p, Generator* generator) {
533 ++g_depth;
534 size_t list_length = g_depth > 3 ? 0 : RandInRange(8);
535 for (size_t index = 0; index < list_length; ++index) {
536 switch (RandInRange(8))
538 case base::Value::TYPE_BOOLEAN: {
539 bool tmp;
540 generator->GenerateBool(&tmp);
541 p->Set(index, new base::FundamentalValue(tmp));
542 break;
544 case base::Value::TYPE_INTEGER: {
545 int tmp;
546 generator->GenerateInt(&tmp);
547 p->Set(index, new base::FundamentalValue(tmp));
548 break;
550 case base::Value::TYPE_DOUBLE: {
551 double tmp;
552 generator->GenerateDouble(&tmp);
553 p->Set(index, new base::FundamentalValue(tmp));
554 break;
556 case base::Value::TYPE_STRING: {
557 std::string tmp;
558 generator->GenerateString(&tmp);
559 p->Set(index, new base::StringValue(tmp));
560 break;
562 case base::Value::TYPE_BINARY: {
563 char tmp[200];
564 size_t bin_length = RandInRange(sizeof(tmp));
565 generator->GenerateData(tmp, bin_length);
566 p->Set(index,
567 base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
568 break;
570 case base::Value::TYPE_DICTIONARY: {
571 base::DictionaryValue* tmp = new base::DictionaryValue();
572 GenerateParam(tmp, generator);
573 p->Set(index, tmp);
574 break;
576 case base::Value::TYPE_LIST: {
577 base::ListValue* tmp = new base::ListValue();
578 GenerateParam(tmp, generator);
579 p->Set(index, tmp);
580 break;
582 case base::Value::TYPE_NULL:
583 default:
584 break;
587 --g_depth;
588 return true;
592 template <>
593 struct GenerateTraits<base::DictionaryValue> {
594 static bool Generate(base::DictionaryValue* p, Generator* generator) {
595 ++g_depth;
596 size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
597 for (size_t index = 0; index < dict_length; ++index) {
598 std::string property;
599 generator->GenerateString(&property);
600 switch (RandInRange(8))
602 case base::Value::TYPE_BOOLEAN: {
603 bool tmp;
604 generator->GenerateBool(&tmp);
605 p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
606 break;
608 case base::Value::TYPE_INTEGER: {
609 int tmp;
610 generator->GenerateInt(&tmp);
611 p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
612 break;
614 case base::Value::TYPE_DOUBLE: {
615 double tmp;
616 generator->GenerateDouble(&tmp);
617 p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
618 break;
620 case base::Value::TYPE_STRING: {
621 std::string tmp;
622 generator->GenerateString(&tmp);
623 p->SetWithoutPathExpansion(property, new base::StringValue(tmp));
624 break;
626 case base::Value::TYPE_BINARY: {
627 char tmp[200];
628 size_t bin_length = RandInRange(sizeof(tmp));
629 generator->GenerateData(tmp, bin_length);
630 p->SetWithoutPathExpansion(
631 property,
632 base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
633 break;
635 case base::Value::TYPE_DICTIONARY: {
636 base::DictionaryValue* tmp = new base::DictionaryValue();
637 GenerateParam(tmp, generator);
638 p->SetWithoutPathExpansion(property, tmp);
639 break;
641 case base::Value::TYPE_LIST: {
642 base::ListValue* tmp = new base::ListValue();
643 GenerateParam(tmp, generator);
644 p->SetWithoutPathExpansion(property, tmp);
645 break;
647 case base::Value::TYPE_NULL:
648 default:
649 break;
652 --g_depth;
653 return true;
657 template <>
658 struct GenerateTraits<GURL> {
659 static bool Generate(GURL *p, Generator* generator) {
660 const char url_chars[] = "Ahtp0:/.?+\%&#";
661 size_t count = RandInRange(100);
662 std::string random_url;
663 for (size_t i = 0; i < count; ++i)
664 random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
665 int selector = RandInRange(10);
666 if (selector == 0)
667 random_url = std::string("http://") + random_url;
668 else if (selector == 1)
669 random_url = std::string("file://") + random_url;
670 else if (selector == 2)
671 random_url = std::string("javascript:") + random_url;
672 else if (selector == 2)
673 random_url = std::string("data:") + random_url;
674 *p = GURL(random_url);
675 return true;
679 // FIXME: Actually generate something.
680 template <>
681 struct GenerateTraits<SkBitmap> {
682 static bool Generate(SkBitmap* p, Generator* generator) {
683 *p = SkBitmap();
684 return true;
688 template <>
689 struct GenerateTraits<IPC::ChannelHandle> {
690 static bool Generate(IPC::ChannelHandle* p, Generator* generator) {
691 return
692 GenerateParam(&p->name, generator) &&
693 GenerateParam(&p->socket, generator);
697 template <>
698 struct GenerateTraits<cc::CompositorFrame> {
699 // FIXME: this should actually generate something
700 static bool Generate(cc::CompositorFrame* p, Generator* generator) {
701 return true;
705 template <>
706 struct GenerateTraits<cc::CompositorFrameAck> {
707 // FIXME: this should actually generate something
708 static bool Generate(cc::CompositorFrameAck* p, Generator* generator) {
709 return true;
713 template <>
714 struct GenerateTraits<content::IndexedDBKey> {
715 static bool Generate(content::IndexedDBKey* p, Generator* generator) {
716 ++g_depth;
717 blink::WebIDBKeyType web_type =
718 static_cast<blink::WebIDBKeyType>(RandInRange(7));
719 switch (web_type)
721 case blink::WebIDBKeyTypeArray: {
722 size_t length = g_depth > 3 ? 0 : RandInRange(4);
723 std::vector<content::IndexedDBKey> array;
724 array.resize(length);
725 for (size_t i = 0; i < length; ++i) {
726 if (!GenerateParam(&array[i], generator))
727 return false;
729 *p = content::IndexedDBKey(array);
730 return true;
732 case blink::WebIDBKeyTypeBinary: {
733 std::string binary;
734 if (!GenerateParam(&binary, generator))
735 return false;
736 *p = content::IndexedDBKey(binary);
737 return true;
739 case blink::WebIDBKeyTypeString: {
740 base::string16 string;
741 if (!GenerateParam(&string, generator))
742 return false;
743 *p = content::IndexedDBKey(string);
744 return true;
746 case blink::WebIDBKeyTypeDate:
747 case blink::WebIDBKeyTypeNumber: {
748 double number;
749 if (!GenerateParam(&number, generator))
750 return false;
751 *p = content::IndexedDBKey(number, web_type);
752 return true;
754 case blink::WebIDBKeyTypeInvalid:
755 case blink::WebIDBKeyTypeNull: {
756 *p = content::IndexedDBKey(web_type);
757 return true;
759 default:
760 NOTREACHED();
761 return false;
763 --g_depth;
764 return true;
768 template <>
769 struct GenerateTraits<content::IndexedDBKeyRange> {
770 static bool Generate(content::IndexedDBKeyRange *p, Generator* generator) {
771 content::IndexedDBKey lower;
772 content::IndexedDBKey upper;
773 bool lower_open;
774 bool upper_open;
775 if (!GenerateParam(&lower, generator))
776 return false;
777 if (!GenerateParam(&upper, generator))
778 return false;
779 if (!GenerateParam(&lower_open, generator))
780 return false;
781 if (!GenerateParam(&upper_open, generator))
782 return false;
783 *p = content::IndexedDBKeyRange(lower, upper, lower_open, upper_open);
784 return true;
788 template <>
789 struct GenerateTraits<content::IndexedDBKeyPath> {
790 static bool Generate(content::IndexedDBKeyPath *p, Generator* generator) {
791 switch (RandInRange(3)) {
792 case 0: {
793 std::vector<base::string16> array;
794 if (!GenerateParam(&array, generator))
795 return false;
796 *p = content::IndexedDBKeyPath(array);
797 break;
799 case 1: {
800 base::string16 string;
801 if (!GenerateParam(&string, generator))
802 return false;
803 *p = content::IndexedDBKeyPath(string);
804 break;
806 case 2: {
807 *p = content::IndexedDBKeyPath();
808 break;
811 return true;
815 template <>
816 struct GenerateTraits<content::PageState> {
817 static bool Generate(content::PageState *p, Generator* generator) {
818 std::string junk;
819 if (!GenerateParam(&junk, generator))
820 return false;
821 *p = content::PageState::CreateFromEncodedData(junk);
822 return true;
826 template <>
827 struct GenerateTraits<gpu::Mailbox> {
828 static bool Generate(gpu::Mailbox *p, Generator* generator) {
829 generator->GenerateBytes(p->name, sizeof(p->name));
830 return true;
834 template <>
835 struct GenerateTraits<media::AudioParameters> {
836 static bool Generate(media::AudioParameters *p, Generator* generator) {
837 int format;
838 int channel_layout;
839 int channels;
840 int input_channels;
841 int sample_rate;
842 int bits_per_sample;
843 int frames_per_buffer;
844 int effects;
845 if (!GenerateParam(&format, generator))
846 return false;
847 if (!GenerateParam(&channel_layout, generator))
848 return false;
849 if (!GenerateParam(&channels, generator))
850 return false;
851 if (!GenerateParam(&input_channels, generator))
852 return false;
853 if (!GenerateParam(&sample_rate, generator))
854 return false;
855 if (!GenerateParam(&bits_per_sample, generator))
856 return false;
857 if (!GenerateParam(&frames_per_buffer, generator))
858 return false;
859 if (!GenerateParam(&effects, generator))
860 return false;
861 media::AudioParameters params(
862 static_cast<media::AudioParameters::Format>(format),
863 static_cast<media::ChannelLayout>(channel_layout),
864 channels, input_channels, sample_rate,
865 bits_per_sample, frames_per_buffer, effects);
866 *p = params;
867 return true;
871 template <>
872 struct GenerateTraits<media::VideoCaptureFormat> {
873 static bool Generate(media::VideoCaptureFormat *p, Generator* generator) {
874 int frame_size_width;
875 int frame_size_height;
876 int pixel_format;
877 if (!GenerateParam(&frame_size_height, generator))
878 return false;
879 if (!GenerateParam(&frame_size_width, generator))
880 return false;
881 if (!GenerateParam(&pixel_format, generator))
882 return false;
883 if (!GenerateParam(&p->frame_rate, generator))
884 return false;
885 p->frame_size.SetSize(frame_size_width, frame_size_height);
886 p->pixel_format = static_cast<media::VideoPixelFormat>(pixel_format);
887 return true;
892 template <>
893 struct GenerateTraits<net::LoadTimingInfo> {
894 static bool Generate(net::LoadTimingInfo *p, Generator* generator) {
895 return
896 GenerateParam(&p->socket_log_id, generator) &&
897 GenerateParam(&p->socket_reused, generator) &&
898 GenerateParam(&p->request_start_time, generator) &&
899 GenerateParam(&p->request_start, generator) &&
900 GenerateParam(&p->proxy_resolve_start, generator) &&
901 GenerateParam(&p->proxy_resolve_end, generator) &&
902 GenerateParam(&p->connect_timing.dns_start, generator) &&
903 GenerateParam(&p->connect_timing.dns_end, generator) &&
904 GenerateParam(&p->connect_timing.connect_start, generator) &&
905 GenerateParam(&p->connect_timing.connect_end, generator) &&
906 GenerateParam(&p->connect_timing.ssl_start, generator) &&
907 GenerateParam(&p->connect_timing.ssl_end, generator) &&
908 GenerateParam(&p->send_start, generator) &&
909 GenerateParam(&p->send_end, generator) &&
910 GenerateParam(&p->receive_headers_end, generator);
914 template <>
915 struct GenerateTraits<net::HostPortPair> {
916 static bool Generate(net::HostPortPair *p, Generator* generator) {
917 std::string host;
918 uint16 port;
919 if (!GenerateParam(&host, generator))
920 return false;
921 if (!GenerateParam(&port, generator))
922 return false;
923 p->set_host(host);
924 p->set_port(port);
925 return true;
929 template <>
930 struct GenerateTraits<net::IPEndPoint> {
931 static bool Generate(net::IPEndPoint *p, Generator* generator) {
932 net::IPAddressNumber address;
933 int port;
934 if (!GenerateParam(&address, generator))
935 return false;
936 if (!GenerateParam(&port, generator))
937 return false;
938 net::IPEndPoint ip_endpoint(address, port);
939 *p = ip_endpoint;
940 return true;
944 template <>
945 struct GenerateTraits<gfx::Point> {
946 static bool Generate(gfx::Point *p, Generator* generator) {
947 int x;
948 int y;
949 if (!GenerateParam(&x, generator))
950 return false;
951 if (!GenerateParam(&y, generator))
952 return false;
953 p->SetPoint(x, y);
954 return true;
958 template <>
959 struct GenerateTraits<gfx::PointF> {
960 static bool Generate(gfx::PointF *p, Generator* generator) {
961 float x;
962 float y;
963 if (!GenerateParam(&x, generator))
964 return false;
965 if (!GenerateParam(&y, generator))
966 return false;
967 p->SetPoint(x, y);
968 return true;
972 template <>
973 struct GenerateTraits<gfx::Size> {
974 static bool Generate(gfx::Size *p, Generator* generator) {
975 int w;
976 int h;
977 if (!GenerateParam(&w, generator))
978 return false;
979 if (!GenerateParam(&h, generator))
980 return false;
981 p->SetSize(w, h);
982 return true;
986 template <>
987 struct GenerateTraits<gfx::SizeF> {
988 static bool Generate(gfx::SizeF *p, Generator* generator) {
989 float w;
990 float h;
991 if (!GenerateParam(&w, generator))
992 return false;
993 if (!GenerateParam(&h, generator))
994 return false;
995 p->SetSize(w, h);
996 return true;
1000 template <>
1001 struct GenerateTraits<gfx::Rect> {
1002 static bool Generate(gfx::Rect *p, Generator* generator) {
1003 gfx::Point origin;
1004 gfx::Size size;
1005 if (!GenerateParam(&origin, generator))
1006 return false;
1007 if (!GenerateParam(&size, generator))
1008 return false;
1009 p->set_origin(origin);
1010 p->set_size(size);
1011 return true;
1015 template <>
1016 struct GenerateTraits<gfx::RectF> {
1017 static bool Generate(gfx::RectF *p, Generator* generator) {
1018 gfx::PointF origin;
1019 gfx::SizeF size;
1020 if (!GenerateParam(&origin, generator))
1021 return false;
1022 if (!GenerateParam(&size, generator))
1023 return false;
1024 p->set_origin(origin);
1025 p->set_size(size);
1026 return true;
1030 template <>
1031 struct GenerateTraits<gfx::Range> {
1032 static bool Generate(gfx::Range *p, Generator* generator) {
1033 size_t start;
1034 size_t end;
1035 if (!GenerateParam(&start, generator))
1036 return false;
1037 if (!GenerateParam(&end, generator))
1038 return false;
1039 *p = gfx::Range(start, end);
1040 return true;
1044 template <>
1045 struct GenerateTraits<gfx::Vector2d> {
1046 static bool Generate(gfx::Vector2d *p, Generator* generator) {
1047 int x;
1048 int y;
1049 if (!GenerateParam(&x, generator))
1050 return false;
1051 if (!GenerateParam(&y, generator))
1052 return false;
1053 *p = gfx::Vector2d(x, y);
1054 return true;
1058 template <>
1059 struct GenerateTraits<gfx::Vector2dF> {
1060 static bool Generate(gfx::Vector2dF *p, Generator* generator) {
1061 float x;
1062 float y;
1063 if (!GenerateParam(&x, generator))
1064 return false;
1065 if (!GenerateParam(&y, generator))
1066 return false;
1067 *p = gfx::Vector2dF(x, y);
1068 return true;
1072 // PP_ traits.
1073 template <>
1074 struct GenerateTraits<PP_Bool> {
1075 static bool Generate(PP_Bool *p, Generator* generator) {
1076 bool tmp;
1077 if (!GenerateParam(&tmp, generator))
1078 return false;
1079 *p = PP_FromBool(tmp);
1080 return true;
1084 template <>
1085 struct GenerateTraits<PP_NetAddress_Private> {
1086 static bool Generate(PP_NetAddress_Private *p, Generator* generator) {
1087 p->size = RandInRange(sizeof(p->data) + 1);
1088 generator->GenerateBytes(&p->data, p->size);
1089 return true;
1093 template <>
1094 struct GenerateTraits<ppapi::HostResource> {
1095 static bool Generate(ppapi::HostResource *p, Generator* generator) {
1096 PP_Instance instance;
1097 PP_Resource resource;
1098 if (!GenerateParam(&instance, generator))
1099 return false;
1100 if (!GenerateParam(&resource, generator))
1101 return false;
1102 p->SetHostResource(instance, resource);
1103 return true;
1107 template <>
1108 struct GenerateTraits<ppapi::PepperFilePath> {
1109 static bool Generate(ppapi::PepperFilePath *p, Generator* generator) {
1110 unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
1111 base::FilePath path;
1112 if (!GenerateParam(&path, generator))
1113 return false;
1114 *p = ppapi::PepperFilePath(
1115 static_cast<ppapi::PepperFilePath::Domain>(domain), path);
1116 return true;
1120 template <>
1121 struct GenerateTraits<ppapi::PpapiPermissions> {
1122 static bool Generate(ppapi::PpapiPermissions *p, Generator* generator) {
1123 uint32_t bits;
1124 if (!GenerateParam(&bits, generator))
1125 return false;
1126 *p = ppapi::PpapiPermissions(bits);
1127 return true;
1131 template <>
1132 struct GenerateTraits<ppapi::SocketOptionData> {
1133 static bool Generate(ppapi::SocketOptionData *p, Generator* generator) {
1134 // FIXME: we can do better here.
1135 int32 temp;
1136 if (!GenerateParam(&temp, generator))
1137 return false;
1138 p->SetInt32(temp);
1139 return true;
1143 // Redefine macros to generate generating from traits declarations.
1144 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
1145 #undef IPC_STRUCT_BEGIN
1146 #undef IPC_STRUCT_BEGIN_WITH_PARENT
1147 #undef IPC_STRUCT_MEMBER
1148 #undef IPC_STRUCT_END
1149 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
1150 IPC_STRUCT_BEGIN(struct_name)
1151 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
1152 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
1153 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
1155 // Set up so next include will generate generate trait classes.
1156 #undef IPC_STRUCT_TRAITS_BEGIN
1157 #undef IPC_STRUCT_TRAITS_MEMBER
1158 #undef IPC_STRUCT_TRAITS_PARENT
1159 #undef IPC_STRUCT_TRAITS_END
1160 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
1161 template <> \
1162 struct GenerateTraits<struct_name> { \
1163 static bool Generate(struct_name *p, Generator* generator) {
1165 #define IPC_STRUCT_TRAITS_MEMBER(name) \
1166 if (!GenerateParam(&p->name, generator)) \
1167 return false;
1169 #define IPC_STRUCT_TRAITS_PARENT(type) \
1170 if (!GenerateParam(static_cast<type*>(p), generator)) \
1171 return false;
1173 #define IPC_STRUCT_TRAITS_END() \
1174 return true; \
1178 // If |condition| isn't met, the messsge will fail to serialize. Try
1179 // increasingly smaller ranges until we find one that happens to meet
1180 // the condition, or fail trying.
1181 #undef IPC_ENUM_TRAITS_VALIDATE
1182 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition) \
1183 template <> \
1184 struct GenerateTraits<enum_name> { \
1185 static bool Generate(enum_name* p, Generator* generator) { \
1186 for (int shift = 30; shift; --shift) { \
1187 for (int tries = 0; tries < 2; ++tries) { \
1188 int value = RandInRange(1 << shift); \
1189 if (condition) { \
1190 *reinterpret_cast<int*>(p) = value; \
1191 return true; \
1195 std::cerr << "failed to satisfy " << #condition << "\n"; \
1196 return false; \
1200 // Bring them into existence.
1201 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1202 #include "ipc/ipc_message_null_macros.h"
1204 // Redefine macros to generate generating funtions
1205 #undef IPC_MESSAGE_DECL
1206 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
1207 IPC_##kind##_##type##_GENERATE(name, in, out, ilist, olist)
1209 #define IPC_EMPTY_CONTROL_GENERATE(name, in, out, ilist, olist) \
1210 IPC::Message* generator_for_##name(Generator* generator) { \
1211 return new name(); \
1214 #define IPC_EMPTY_ROUTED_GENERATE(name, in, out, ilist, olist) \
1215 IPC::Message* generator_for_##name(Generator* generator) { \
1216 return new name(RandInRange(MAX_FAKE_ROUTING_ID)); \
1219 #define IPC_ASYNC_CONTROL_GENERATE(name, in, out, ilist, olist) \
1220 IPC::Message* generator_for_##name(Generator* generator) { \
1221 IPC_TUPLE_IN_##in ilist p; \
1222 if (GenerateParam(&p, generator)) { \
1223 return new name(IPC_MEMBERS_IN_##in(p)); \
1225 std::cerr << "Don't know how to generate " << #name << "\n"; \
1226 return 0; \
1229 #define IPC_ASYNC_ROUTED_GENERATE(name, in, out, ilist, olist) \
1230 IPC::Message* generator_for_##name(Generator* generator) { \
1231 IPC_TUPLE_IN_##in ilist p; \
1232 if (GenerateParam(&p, generator)) { \
1233 return new name(RandInRange(MAX_FAKE_ROUTING_ID) \
1234 IPC_COMMA_##in \
1235 IPC_MEMBERS_IN_##in(p)); \
1237 std::cerr << "Don't know how to generate " << #name << "\n"; \
1238 return 0; \
1241 #define IPC_SYNC_CONTROL_GENERATE(name, in, out, ilist, olist) \
1242 IPC::Message* generator_for_##name(Generator* generator) { \
1243 IPC_TUPLE_IN_##in ilist p; \
1244 if (GenerateParam(&p, generator)) { \
1245 return new name(IPC_MEMBERS_IN_##in(p) \
1246 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
1247 IPC_MEMBERS_OUT_##out()); \
1249 std::cerr << "Don't know how to generate " << #name << "\n"; \
1250 return 0; \
1253 #define IPC_SYNC_ROUTED_GENERATE(name, in, out, ilist, olist) \
1254 IPC::Message* generator_for_##name(Generator* generator) { \
1255 IPC_TUPLE_IN_##in ilist p; \
1256 if (GenerateParam(&p, generator)) { \
1257 return new name(RandInRange(MAX_FAKE_ROUTING_ID) \
1258 IPC_COMMA_OR_##out(IPC_COMMA_##in) \
1259 IPC_MEMBERS_IN_##in(p) \
1260 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
1261 IPC_MEMBERS_OUT_##out()); \
1263 std::cerr << "Don't know how to generate " << #name << "\n"; \
1264 return 0; \
1267 #define MAX_FAKE_ROUTING_ID 15
1269 #define IPC_MEMBERS_IN_0(p)
1270 #define IPC_MEMBERS_IN_1(p) p.a
1271 #define IPC_MEMBERS_IN_2(p) p.a, p.b
1272 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
1273 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
1274 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e
1276 #define IPC_MEMBERS_OUT_0()
1277 #define IPC_MEMBERS_OUT_1() NULL
1278 #define IPC_MEMBERS_OUT_2() NULL, NULL
1279 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL
1280 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL
1281 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL
1283 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1284 #include "ipc/ipc_message_null_macros.h"
1286 typedef IPC::Message* (*GeneratorFunction)(Generator*);
1287 typedef std::vector<GeneratorFunction> GeneratorFunctionVector;
1289 void PopulateGeneratorFunctionVector(
1290 GeneratorFunctionVector *function_vector) {
1291 #undef IPC_MESSAGE_DECL
1292 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
1293 function_vector->push_back(generator_for_##name);
1294 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1297 static const char kCountSwitch[] = "count";
1298 static const char kHelpSwitch[] = "help";
1300 int GenerateMain(int argc, char** argv) {
1301 CommandLine::Init(argc, argv);
1302 CommandLine* cmd = CommandLine::ForCurrentProcess();
1303 CommandLine::StringVector args = cmd->GetArgs();
1305 if (args.size() != 1 || cmd->HasSwitch(kHelpSwitch)) {
1306 std::cerr << "Usage: ipc_fuzzer_generate [--help] [--count=n] outfile\n";
1307 return EXIT_FAILURE;
1309 std::string output_file_name = args[0];
1311 int message_count = 1000;
1312 if (cmd->HasSwitch(kCountSwitch))
1313 message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
1315 InitRand();
1317 GeneratorFunctionVector function_vector;
1318 PopulateGeneratorFunctionVector(&function_vector);
1319 std::cerr << "Counted " << function_vector.size()
1320 << " distinct messages present in chrome.\n";
1322 Generator* generator = new GeneratorImpl();
1323 MessageVector message_vector;
1325 int bad_count = 0;
1326 if (message_count < 0) {
1327 // Enumerate them all.
1328 for (size_t i = 0; i < function_vector.size(); ++i) {
1329 if (IPC::Message* new_message = (*function_vector[i])(generator))
1330 message_vector.push_back(new_message);
1331 else
1332 bad_count += 1;
1334 } else {
1335 // Generate a random batch.
1336 for (int i = 0; i < message_count; ++i) {
1337 size_t index = RandInRange(function_vector.size());
1338 if (IPC::Message* new_message = (*function_vector[index])(generator))
1339 message_vector.push_back(new_message);
1340 else
1341 bad_count += 1;
1345 std::cerr << "Failed to generate " << bad_count << " messages.\n";
1347 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
1348 return EXIT_FAILURE;
1350 return EXIT_SUCCESS;
1353 } // namespace ipc_fuzzer
1355 int main(int argc, char** argv) {
1356 return ipc_fuzzer::GenerateMain(argc, argv);