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.
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"
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"
39 // For breaking deep recursion.
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.
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;
68 void GenerateIntegralType(T
* value
) {
69 switch (RandInRange(16)) {
83 *value
= static_cast<T
>(RandU64());
89 void GenerateFloatingType(T
* value
) {
90 *value
= RandDouble();
94 void GenerateStringType(T
* value
) {
96 size_t length
= RandInRange(300);
97 for (size_t i
= 0; i
< length
; ++i
)
98 temp_string
+= RandInRange(256);
102 class GeneratorImpl
: public Generator
{
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.
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
176 std::cerr
<< "Can't handle " << __PRETTY_FUNCTION__
<< "\n";
181 // Template function to invoke partially-specialized class method.
183 static bool GenerateParam(P
* p
, Generator
* generator
) {
184 return GenerateTraits
<P
>::Generate(p
, generator
);
187 // Specializations to generate primitive types.
189 struct GenerateTraits
<bool> {
190 static bool Generate(bool* p
, Generator
* generator
) {
191 generator
->GenerateBool(p
);
197 struct GenerateTraits
<int> {
198 static bool Generate(int* p
, Generator
* generator
) {
199 generator
->GenerateInt(p
);
205 struct GenerateTraits
<unsigned int> {
206 static bool Generate(unsigned int* p
, Generator
* generator
) {
207 generator
->GenerateInt(reinterpret_cast<int*>(p
));
213 struct GenerateTraits
<long> {
214 static bool Generate(long* p
, Generator
* generator
) {
215 generator
->GenerateLong(p
);
221 struct GenerateTraits
<unsigned long> {
222 static bool Generate(unsigned long* p
, Generator
* generator
) {
223 generator
->GenerateLong(reinterpret_cast<long*>(p
));
229 struct GenerateTraits
<long long> {
230 static bool Generate(long long* p
, Generator
* generator
) {
231 generator
->GenerateInt64(reinterpret_cast<int64
*>(p
));
237 struct GenerateTraits
<unsigned long long> {
238 static bool Generate(unsigned long long* p
, Generator
* generator
) {
239 generator
->GenerateInt64(reinterpret_cast<int64
*>(p
));
245 struct GenerateTraits
<short> {
246 static bool Generate(short* p
, Generator
* generator
) {
247 generator
->GenerateUInt16(reinterpret_cast<uint16
*>(p
));
253 struct GenerateTraits
<unsigned short> {
254 static bool Generate(unsigned short* p
, Generator
* generator
) {
255 generator
->GenerateUInt16(reinterpret_cast<uint16
*>(p
));
261 struct GenerateTraits
<char> {
262 static bool Generate(char* p
, Generator
* generator
) {
263 generator
->GenerateUChar(reinterpret_cast<unsigned char*>(p
));
269 struct GenerateTraits
<unsigned char> {
270 static bool Generate(unsigned char* p
, Generator
* generator
) {
271 generator
->GenerateUChar(p
);
277 struct GenerateTraits
<float> {
278 static bool Generate(float* p
, Generator
* generator
) {
279 generator
->GenerateFloat(p
);
285 struct GenerateTraits
<double> {
286 static bool Generate(double* p
, Generator
* generator
) {
287 generator
->GenerateDouble(p
);
293 struct GenerateTraits
<std::string
> {
294 static bool Generate(std::string
* p
, Generator
* generator
) {
295 generator
->GenerateString(p
);
301 struct GenerateTraits
<base::string16
> {
302 static bool Generate(base::string16
* p
, Generator
* generator
) {
303 generator
->GenerateString16(p
);
308 // Specializations to generate tuples.
310 struct GenerateTraits
<Tuple0
> {
311 static bool Generate(Tuple0
* p
, Generator
* generator
) {
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
) {
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
) {
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
) {
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
) {
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.
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);
371 for (size_t i
= 0; i
< count
; ++i
) {
372 if (!GenerateParam(&p
->at(i
), generator
)) {
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);
388 for (size_t i
= 0; i
< count
; ++i
) {
389 if (!GenerateParam(&a
, generator
)) {
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
)) {
412 p
->insert(place_holder
);
419 template <class A
, class B
>
420 struct GenerateTraits
<std::pair
<A
, B
> > {
421 static bool Generate(std::pair
<A
, B
>* p
, Generator
* generator
) {
423 GenerateParam(&p
->first
, generator
) &&
424 GenerateParam(&p
->second
, generator
);
428 // Specializations to generate hand-coded tyoes
430 struct GenerateTraits
<base::NullableString16
> {
431 static bool Generate(base::NullableString16
* p
, Generator
* generator
) {
432 *p
= base::NullableString16();
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.
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
);
460 struct GenerateTraits
<base::File::Error
> {
461 static bool Generate(base::File::Error
* p
, Generator
* generator
) {
463 if (!GenerateParam(&temporary
, generator
))
465 *p
= static_cast<base::File::Error
>(temporary
);
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
))
478 if (!GenerateParam(&p
->is_directory
, generator
))
480 if (!GenerateParam(&last_modified
, generator
))
482 if (GenerateParam(&last_accessed
, generator
))
484 if (GenerateParam(&creation_time
, generator
))
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
);
494 struct GenerateTraits
<base::Time
> {
495 static bool Generate(base::Time
* p
, Generator
* generator
) {
496 *p
= base::Time::FromInternalValue(RandU64());
502 struct GenerateTraits
<base::TimeDelta
> {
503 static bool Generate(base::TimeDelta
* p
, Generator
* generator
) {
504 *p
= base::TimeDelta::FromInternalValue(RandU64());
510 struct GenerateTraits
<base::TimeTicks
> {
511 static bool Generate(base::TimeTicks
* p
, Generator
* generator
) {
512 *p
= base::TimeTicks::FromInternalValue(RandU64());
518 struct GenerateTraits
<base::PlatformFileInfo
> {
519 static bool Generate(base::PlatformFileInfo
* p
, Generator
* generator
) {
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
);
531 struct GenerateTraits
<base::ListValue
> {
532 static bool Generate(base::ListValue
* p
, Generator
* generator
) {
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
: {
540 generator
->GenerateBool(&tmp
);
541 p
->Set(index
, new base::FundamentalValue(tmp
));
544 case base::Value::TYPE_INTEGER
: {
546 generator
->GenerateInt(&tmp
);
547 p
->Set(index
, new base::FundamentalValue(tmp
));
550 case base::Value::TYPE_DOUBLE
: {
552 generator
->GenerateDouble(&tmp
);
553 p
->Set(index
, new base::FundamentalValue(tmp
));
556 case base::Value::TYPE_STRING
: {
558 generator
->GenerateString(&tmp
);
559 p
->Set(index
, new base::StringValue(tmp
));
562 case base::Value::TYPE_BINARY
: {
564 size_t bin_length
= RandInRange(sizeof(tmp
));
565 generator
->GenerateData(tmp
, bin_length
);
567 base::BinaryValue::CreateWithCopiedBuffer(tmp
, bin_length
));
570 case base::Value::TYPE_DICTIONARY
: {
571 base::DictionaryValue
* tmp
= new base::DictionaryValue();
572 GenerateParam(tmp
, generator
);
576 case base::Value::TYPE_LIST
: {
577 base::ListValue
* tmp
= new base::ListValue();
578 GenerateParam(tmp
, generator
);
582 case base::Value::TYPE_NULL
:
593 struct GenerateTraits
<base::DictionaryValue
> {
594 static bool Generate(base::DictionaryValue
* p
, Generator
* generator
) {
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
: {
604 generator
->GenerateBool(&tmp
);
605 p
->SetWithoutPathExpansion(property
, new base::FundamentalValue(tmp
));
608 case base::Value::TYPE_INTEGER
: {
610 generator
->GenerateInt(&tmp
);
611 p
->SetWithoutPathExpansion(property
, new base::FundamentalValue(tmp
));
614 case base::Value::TYPE_DOUBLE
: {
616 generator
->GenerateDouble(&tmp
);
617 p
->SetWithoutPathExpansion(property
, new base::FundamentalValue(tmp
));
620 case base::Value::TYPE_STRING
: {
622 generator
->GenerateString(&tmp
);
623 p
->SetWithoutPathExpansion(property
, new base::StringValue(tmp
));
626 case base::Value::TYPE_BINARY
: {
628 size_t bin_length
= RandInRange(sizeof(tmp
));
629 generator
->GenerateData(tmp
, bin_length
);
630 p
->SetWithoutPathExpansion(
632 base::BinaryValue::CreateWithCopiedBuffer(tmp
, bin_length
));
635 case base::Value::TYPE_DICTIONARY
: {
636 base::DictionaryValue
* tmp
= new base::DictionaryValue();
637 GenerateParam(tmp
, generator
);
638 p
->SetWithoutPathExpansion(property
, tmp
);
641 case base::Value::TYPE_LIST
: {
642 base::ListValue
* tmp
= new base::ListValue();
643 GenerateParam(tmp
, generator
);
644 p
->SetWithoutPathExpansion(property
, tmp
);
647 case base::Value::TYPE_NULL
:
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);
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
);
679 // FIXME: Actually generate something.
681 struct GenerateTraits
<SkBitmap
> {
682 static bool Generate(SkBitmap
* p
, Generator
* generator
) {
689 struct GenerateTraits
<IPC::ChannelHandle
> {
690 static bool Generate(IPC::ChannelHandle
* p
, Generator
* generator
) {
692 GenerateParam(&p
->name
, generator
) &&
693 GenerateParam(&p
->socket
, generator
);
698 struct GenerateTraits
<cc::CompositorFrame
> {
699 // FIXME: this should actually generate something
700 static bool Generate(cc::CompositorFrame
* p
, Generator
* generator
) {
706 struct GenerateTraits
<cc::CompositorFrameAck
> {
707 // FIXME: this should actually generate something
708 static bool Generate(cc::CompositorFrameAck
* p
, Generator
* generator
) {
714 struct GenerateTraits
<content::IndexedDBKey
> {
715 static bool Generate(content::IndexedDBKey
* p
, Generator
* generator
) {
717 blink::WebIDBKeyType web_type
=
718 static_cast<blink::WebIDBKeyType
>(RandInRange(7));
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
))
729 *p
= content::IndexedDBKey(array
);
732 case blink::WebIDBKeyTypeBinary
: {
734 if (!GenerateParam(&binary
, generator
))
736 *p
= content::IndexedDBKey(binary
);
739 case blink::WebIDBKeyTypeString
: {
740 base::string16 string
;
741 if (!GenerateParam(&string
, generator
))
743 *p
= content::IndexedDBKey(string
);
746 case blink::WebIDBKeyTypeDate
:
747 case blink::WebIDBKeyTypeNumber
: {
749 if (!GenerateParam(&number
, generator
))
751 *p
= content::IndexedDBKey(number
, web_type
);
754 case blink::WebIDBKeyTypeInvalid
:
755 case blink::WebIDBKeyTypeNull
: {
756 *p
= content::IndexedDBKey(web_type
);
769 struct GenerateTraits
<content::IndexedDBKeyRange
> {
770 static bool Generate(content::IndexedDBKeyRange
*p
, Generator
* generator
) {
771 content::IndexedDBKey lower
;
772 content::IndexedDBKey upper
;
775 if (!GenerateParam(&lower
, generator
))
777 if (!GenerateParam(&upper
, generator
))
779 if (!GenerateParam(&lower_open
, generator
))
781 if (!GenerateParam(&upper_open
, generator
))
783 *p
= content::IndexedDBKeyRange(lower
, upper
, lower_open
, upper_open
);
789 struct GenerateTraits
<content::IndexedDBKeyPath
> {
790 static bool Generate(content::IndexedDBKeyPath
*p
, Generator
* generator
) {
791 switch (RandInRange(3)) {
793 std::vector
<base::string16
> array
;
794 if (!GenerateParam(&array
, generator
))
796 *p
= content::IndexedDBKeyPath(array
);
800 base::string16 string
;
801 if (!GenerateParam(&string
, generator
))
803 *p
= content::IndexedDBKeyPath(string
);
807 *p
= content::IndexedDBKeyPath();
816 struct GenerateTraits
<content::PageState
> {
817 static bool Generate(content::PageState
*p
, Generator
* generator
) {
819 if (!GenerateParam(&junk
, generator
))
821 *p
= content::PageState::CreateFromEncodedData(junk
);
827 struct GenerateTraits
<gpu::Mailbox
> {
828 static bool Generate(gpu::Mailbox
*p
, Generator
* generator
) {
829 generator
->GenerateBytes(p
->name
, sizeof(p
->name
));
835 struct GenerateTraits
<media::AudioParameters
> {
836 static bool Generate(media::AudioParameters
*p
, Generator
* generator
) {
843 int frames_per_buffer
;
845 if (!GenerateParam(&format
, generator
))
847 if (!GenerateParam(&channel_layout
, generator
))
849 if (!GenerateParam(&channels
, generator
))
851 if (!GenerateParam(&input_channels
, generator
))
853 if (!GenerateParam(&sample_rate
, generator
))
855 if (!GenerateParam(&bits_per_sample
, generator
))
857 if (!GenerateParam(&frames_per_buffer
, generator
))
859 if (!GenerateParam(&effects
, generator
))
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
);
872 struct GenerateTraits
<media::VideoCaptureFormat
> {
873 static bool Generate(media::VideoCaptureFormat
*p
, Generator
* generator
) {
874 int frame_size_width
;
875 int frame_size_height
;
877 if (!GenerateParam(&frame_size_height
, generator
))
879 if (!GenerateParam(&frame_size_width
, generator
))
881 if (!GenerateParam(&pixel_format
, generator
))
883 if (!GenerateParam(&p
->frame_rate
, generator
))
885 p
->frame_size
.SetSize(frame_size_width
, frame_size_height
);
886 p
->pixel_format
= static_cast<media::VideoPixelFormat
>(pixel_format
);
893 struct GenerateTraits
<net::LoadTimingInfo
> {
894 static bool Generate(net::LoadTimingInfo
*p
, Generator
* generator
) {
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
);
915 struct GenerateTraits
<net::HostPortPair
> {
916 static bool Generate(net::HostPortPair
*p
, Generator
* generator
) {
919 if (!GenerateParam(&host
, generator
))
921 if (!GenerateParam(&port
, generator
))
930 struct GenerateTraits
<net::IPEndPoint
> {
931 static bool Generate(net::IPEndPoint
*p
, Generator
* generator
) {
932 net::IPAddressNumber address
;
934 if (!GenerateParam(&address
, generator
))
936 if (!GenerateParam(&port
, generator
))
938 net::IPEndPoint
ip_endpoint(address
, port
);
945 struct GenerateTraits
<gfx::Point
> {
946 static bool Generate(gfx::Point
*p
, Generator
* generator
) {
949 if (!GenerateParam(&x
, generator
))
951 if (!GenerateParam(&y
, generator
))
959 struct GenerateTraits
<gfx::PointF
> {
960 static bool Generate(gfx::PointF
*p
, Generator
* generator
) {
963 if (!GenerateParam(&x
, generator
))
965 if (!GenerateParam(&y
, generator
))
973 struct GenerateTraits
<gfx::Size
> {
974 static bool Generate(gfx::Size
*p
, Generator
* generator
) {
977 if (!GenerateParam(&w
, generator
))
979 if (!GenerateParam(&h
, generator
))
987 struct GenerateTraits
<gfx::SizeF
> {
988 static bool Generate(gfx::SizeF
*p
, Generator
* generator
) {
991 if (!GenerateParam(&w
, generator
))
993 if (!GenerateParam(&h
, generator
))
1001 struct GenerateTraits
<gfx::Rect
> {
1002 static bool Generate(gfx::Rect
*p
, Generator
* generator
) {
1005 if (!GenerateParam(&origin
, generator
))
1007 if (!GenerateParam(&size
, generator
))
1009 p
->set_origin(origin
);
1016 struct GenerateTraits
<gfx::RectF
> {
1017 static bool Generate(gfx::RectF
*p
, Generator
* generator
) {
1020 if (!GenerateParam(&origin
, generator
))
1022 if (!GenerateParam(&size
, generator
))
1024 p
->set_origin(origin
);
1031 struct GenerateTraits
<gfx::Range
> {
1032 static bool Generate(gfx::Range
*p
, Generator
* generator
) {
1035 if (!GenerateParam(&start
, generator
))
1037 if (!GenerateParam(&end
, generator
))
1039 *p
= gfx::Range(start
, end
);
1045 struct GenerateTraits
<gfx::Vector2d
> {
1046 static bool Generate(gfx::Vector2d
*p
, Generator
* generator
) {
1049 if (!GenerateParam(&x
, generator
))
1051 if (!GenerateParam(&y
, generator
))
1053 *p
= gfx::Vector2d(x
, y
);
1059 struct GenerateTraits
<gfx::Vector2dF
> {
1060 static bool Generate(gfx::Vector2dF
*p
, Generator
* generator
) {
1063 if (!GenerateParam(&x
, generator
))
1065 if (!GenerateParam(&y
, generator
))
1067 *p
= gfx::Vector2dF(x
, y
);
1074 struct GenerateTraits
<PP_Bool
> {
1075 static bool Generate(PP_Bool
*p
, Generator
* generator
) {
1077 if (!GenerateParam(&tmp
, generator
))
1079 *p
= PP_FromBool(tmp
);
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
);
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
))
1100 if (!GenerateParam(&resource
, generator
))
1102 p
->SetHostResource(instance
, resource
);
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
))
1114 *p
= ppapi::PepperFilePath(
1115 static_cast<ppapi::PepperFilePath::Domain
>(domain
), path
);
1121 struct GenerateTraits
<ppapi::PpapiPermissions
> {
1122 static bool Generate(ppapi::PpapiPermissions
*p
, Generator
* generator
) {
1124 if (!GenerateParam(&bits
, generator
))
1126 *p
= ppapi::PpapiPermissions(bits
);
1132 struct GenerateTraits
<ppapi::SocketOptionData
> {
1133 static bool Generate(ppapi::SocketOptionData
*p
, Generator
* generator
) {
1134 // FIXME: we can do better here.
1136 if (!GenerateParam(&temp
, generator
))
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) \
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)) \
1169 #define IPC_STRUCT_TRAITS_PARENT(type) \
1170 if (!GenerateParam(static_cast<type*>(p), generator)) \
1173 #define IPC_STRUCT_TRAITS_END() \
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) \
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); \
1190 *reinterpret_cast<int*>(p) = value; \
1195 std::cerr << "failed to satisfy " << #condition << "\n"; \
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"; \
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) \
1235 IPC_MEMBERS_IN_##in(p)); \
1237 std::cerr << "Don't know how to generate " << #name << "\n"; \
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"; \
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"; \
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());
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
;
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
);
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
);
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
);