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