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