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 <string> 12#include <vector> 13 14#include "base/command_line.h" 15#include "base/pickle.h" 16#include "base/strings/string_split.h" 17#include "base/strings/string_util.h" 18#include "base/strings/string_number_conversions.h" 19#include "base/strings/utf_string_conversions.h" 20#include "ipc/ipc_message.h" 21#include "ipc/ipc_message_utils.h" 22#include "ipc/ipc_switches.h" 23#include "ipc/ipc_sync_channel.h" 24#include "ipc/ipc_sync_message.h" 25#include "tools/ipc_fuzzer/message_lib/all_messages.h" 26#include "tools/ipc_fuzzer/message_lib/message_cracker.h" 27#include "tools/ipc_fuzzer/message_lib/message_file.h" 28#include "tools/ipc_fuzzer/mutate/rand_util.h" 29 30#if defined(OS_POSIX) 31#include <unistd.h> 32#endif 33 34namespace IPC { 35class Message; 36} // namespace IPC 37 38namespace ipc_fuzzer { 39 40// Interface implemented by those who fuzz basic types. The types all 41// correspond to the types which a pickle from base/pickle.h can pickle, 42// plus the floating point types. 43class Fuzzer { 44 public: 45 // Tweak individual values within a message. 46 virtual void FuzzBool(bool* value) = 0; 47 virtual void FuzzInt(int* value) = 0; 48 virtual void FuzzLong(long* value) = 0; 49 virtual void FuzzSize(size_t* value) = 0; 50 virtual void FuzzUChar(unsigned char *value) = 0; 51 virtual void FuzzUInt16(uint16* value) = 0; 52 virtual void FuzzUInt32(uint32* value) = 0; 53 virtual void FuzzInt64(int64* value) = 0; 54 virtual void FuzzUInt64(uint64* value) = 0; 55 virtual void FuzzFloat(float *value) = 0; 56 virtual void FuzzDouble(double *value) = 0; 57 virtual void FuzzString(std::string* value) = 0; 58 virtual void FuzzString16(base::string16* value) = 0; 59 virtual void FuzzData(char* data, int length) = 0; 60 virtual void FuzzBytes(void* data, int data_len) = 0; 61}; 62 63template <typename T> 64void FuzzIntegralType(T* value, unsigned int frequency) { 65 if (RandEvent(frequency)) { 66 switch (RandInRange(4)) { 67 case 0: (*value) = 0; break; 68 case 1: (*value)--; break; 69 case 2: (*value)++; break; 70 case 3: (*value) = RandU64(); break; 71 } 72 } 73} 74 75template <typename T> 76void FuzzStringType(T* value, unsigned int frequency, 77 const T& literal1, const T& literal2) { 78 if (RandEvent(frequency)) { 79 switch (RandInRange(5)) { 80 case 4: (*value) = (*value) + (*value); // FALLTHROUGH 81 case 3: (*value) = (*value) + (*value); // FALLTHROUGH 82 case 2: (*value) = (*value) + (*value); break; 83 case 1: (*value) += literal1; break; 84 case 0: (*value) = literal2; break; 85 } 86 } 87} 88 89// One such fuzzer implementation. 90class DefaultFuzzer : public Fuzzer { 91 public: 92 DefaultFuzzer(int frequency) : frequency_(frequency) { 93 } 94 95 virtual ~DefaultFuzzer() {} 96 97 virtual void FuzzBool(bool* value) OVERRIDE { 98 if (RandEvent(frequency_)) 99 (*value) = !(*value); 100 } 101 102 virtual void FuzzInt(int* value) OVERRIDE { 103 FuzzIntegralType<int>(value, frequency_); 104 } 105 106 virtual void FuzzLong(long* value) OVERRIDE { 107 FuzzIntegralType<long>(value, frequency_); 108 } 109 110 virtual void FuzzSize(size_t* value) OVERRIDE { 111 FuzzIntegralType<size_t>(value, frequency_); 112 } 113 114 virtual void FuzzUChar(unsigned char* value) OVERRIDE { 115 FuzzIntegralType<unsigned char>(value, frequency_); 116 } 117 118 virtual void FuzzUInt16(uint16* value) OVERRIDE { 119 FuzzIntegralType<uint16>(value, frequency_); 120 } 121 122 virtual void FuzzUInt32(uint32* value) OVERRIDE { 123 FuzzIntegralType<uint32>(value, frequency_); 124 } 125 126 virtual void FuzzInt64(int64* value) OVERRIDE { 127 FuzzIntegralType<int64>(value, frequency_); 128 } 129 130 virtual void FuzzUInt64(uint64* value) OVERRIDE { 131 FuzzIntegralType<uint64>(value, frequency_); 132 } 133 134 virtual void FuzzFloat(float* value) OVERRIDE { 135 if (RandEvent(frequency_)) 136 *value = RandDouble(); 137 } 138 139 virtual void FuzzDouble(double* value) OVERRIDE { 140 if (RandEvent(frequency_)) 141 *value = RandDouble(); 142 } 143 144 virtual void FuzzString(std::string* value) OVERRIDE { 145 FuzzStringType<std::string>(value, frequency_, "BORKED", std::string()); 146 } 147 148 virtual void FuzzString16(base::string16* value) OVERRIDE { 149 FuzzStringType<base::string16>(value, frequency_, 150 base::WideToUTF16(L"BORKED"), 151 base::WideToUTF16(L"")); 152 } 153 154 virtual void FuzzData(char* data, int length) OVERRIDE { 155 if (RandEvent(frequency_)) { 156 for (int i = 0; i < length; ++i) { 157 FuzzIntegralType<char>(&data[i], frequency_); 158 } 159 } 160 } 161 162 virtual void FuzzBytes(void* data, int data_len) OVERRIDE { 163 FuzzData(static_cast<char*>(data), data_len); 164 } 165 166 private: 167 unsigned int frequency_; 168}; 169 170 171// No-op fuzzer. Rewrites each message unchanged to check if the message 172// re-assembly is legit. 173class NoOpFuzzer : public Fuzzer { 174 public: 175 NoOpFuzzer() {} 176 virtual ~NoOpFuzzer() {} 177 178 virtual void FuzzBool(bool* value) OVERRIDE {} 179 virtual void FuzzInt(int* value) OVERRIDE {} 180 virtual void FuzzLong(long* value) OVERRIDE {} 181 virtual void FuzzSize(size_t* value) OVERRIDE {} 182 virtual void FuzzUChar(unsigned char* value) OVERRIDE {} 183 virtual void FuzzUInt16(uint16* value) OVERRIDE {} 184 virtual void FuzzUInt32(uint32* value) OVERRIDE {} 185 virtual void FuzzInt64(int64* value) OVERRIDE {} 186 virtual void FuzzUInt64(uint64* value) OVERRIDE {} 187 virtual void FuzzFloat(float* value) OVERRIDE {} 188 virtual void FuzzDouble(double* value) OVERRIDE {} 189 virtual void FuzzString(std::string* value) OVERRIDE {} 190 virtual void FuzzString16(base::string16* value) OVERRIDE {} 191 virtual void FuzzData(char* data, int length) OVERRIDE {} 192 virtual void FuzzBytes(void* data, int data_len) OVERRIDE {} 193}; 194 195class FuzzerFactory { 196 public: 197 static Fuzzer *Create(const std::string& name, int frequency) { 198 if (name == "no-op") 199 return new NoOpFuzzer(); 200 201 if (name == "default") 202 return new DefaultFuzzer(frequency); 203 204 std::cerr << "No such fuzzer: " << name << "\n"; 205 return 0; 206 } 207}; 208 209// Partially-specialized class that knows how to fuzz a given type. 210template <class P> 211struct FuzzTraits { 212 static void Fuzz(P* p, Fuzzer *fuzzer) { 213 // This is the catch-all for types we don't have enough information 214 // to fuzz. It simply does nothing to the type. We might want to 215 // change it to randomly flip a bit in the range (p, p+sizeof(P)). 216 } 217}; 218 219// Template function to invoke partially-specialized class method. 220template <class P> 221static void FuzzParam(P* p, Fuzzer* fuzzer) { 222 FuzzTraits<P>::Fuzz(p, fuzzer); 223} 224 225// Specializations to fuzz primitive types. 226template <> 227struct FuzzTraits<bool> { 228 static void Fuzz(bool* p, Fuzzer* fuzzer) { 229 fuzzer->FuzzBool(p); 230 } 231}; 232 233template <> 234struct FuzzTraits<int> { 235 static void Fuzz(int* p, Fuzzer* fuzzer) { 236 fuzzer->FuzzInt(p); 237 } 238}; 239 240template <> 241struct FuzzTraits<unsigned int> { 242 static void Fuzz(unsigned int* p, Fuzzer* fuzzer) { 243 fuzzer->FuzzInt(reinterpret_cast<int*>(p)); 244 } 245}; 246 247template <> 248struct FuzzTraits<long> { 249 static void Fuzz(long* p, Fuzzer* fuzzer) { 250 fuzzer->FuzzLong(p); 251 } 252}; 253 254template <> 255struct FuzzTraits<unsigned long> { 256 static void Fuzz(unsigned long* p, Fuzzer* fuzzer) { 257 fuzzer->FuzzLong(reinterpret_cast<long*>(p)); 258 } 259}; 260 261template <> 262struct FuzzTraits<long long> { 263 static void Fuzz(long long* p, Fuzzer* fuzzer) { 264 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 265 } 266}; 267 268template <> 269struct FuzzTraits<unsigned long long> { 270 static void Fuzz(unsigned long long* p, Fuzzer* fuzzer) { 271 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 272 } 273}; 274 275template <> 276struct FuzzTraits<short> { 277 static void Fuzz(short* p, Fuzzer* fuzzer) { 278 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 279 } 280}; 281 282template <> 283struct FuzzTraits<unsigned short> { 284 static void Fuzz(unsigned short* p, Fuzzer* fuzzer) { 285 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 286 } 287}; 288 289template <> 290struct FuzzTraits<char> { 291 static void Fuzz(char* p, Fuzzer* fuzzer) { 292 fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p)); 293 } 294}; 295 296template <> 297struct FuzzTraits<unsigned char> { 298 static void Fuzz(unsigned char* p, Fuzzer* fuzzer) { 299 fuzzer->FuzzUChar(p); 300 } 301}; 302 303template <> 304struct FuzzTraits<float> { 305 static void Fuzz(float* p, Fuzzer* fuzzer) { 306 fuzzer->FuzzFloat(p); 307 } 308}; 309 310template <> 311struct FuzzTraits<double> { 312 static void Fuzz(double* p, Fuzzer* fuzzer) { 313 fuzzer->FuzzDouble(p); 314 } 315}; 316 317template <> 318struct FuzzTraits<std::string> { 319 static void Fuzz(std::string* p, Fuzzer* fuzzer) { 320 fuzzer->FuzzString(p); 321 } 322}; 323 324template <> 325struct FuzzTraits<base::string16> { 326 static void Fuzz(base::string16* p, Fuzzer* fuzzer) { 327 fuzzer->FuzzString16(p); 328 } 329}; 330 331// Specializations to fuzz tuples. 332template <class A> 333struct FuzzTraits<Tuple1<A> > { 334 static void Fuzz(Tuple1<A>* p, Fuzzer* fuzzer) { 335 FuzzParam(&p->a, fuzzer); 336 } 337}; 338 339template <class A, class B> 340struct FuzzTraits<Tuple2<A, B> > { 341 static void Fuzz(Tuple2<A, B>* p, Fuzzer* fuzzer) { 342 FuzzParam(&p->a, fuzzer); 343 FuzzParam(&p->b, fuzzer); 344 } 345}; 346 347template <class A, class B, class C> 348struct FuzzTraits<Tuple3<A, B, C> > { 349 static void Fuzz(Tuple3<A, B, C>* p, Fuzzer* fuzzer) { 350 FuzzParam(&p->a, fuzzer); 351 FuzzParam(&p->b, fuzzer); 352 FuzzParam(&p->c, fuzzer); 353 } 354}; 355 356template <class A, class B, class C, class D> 357struct FuzzTraits<Tuple4<A, B, C, D> > { 358 static void Fuzz(Tuple4<A, B, C, D>* p, Fuzzer* fuzzer) { 359 FuzzParam(&p->a, fuzzer); 360 FuzzParam(&p->b, fuzzer); 361 FuzzParam(&p->c, fuzzer); 362 FuzzParam(&p->d, fuzzer); 363 } 364}; 365 366template <class A, class B, class C, class D, class E> 367struct FuzzTraits<Tuple5<A, B, C, D, E> > { 368 static void Fuzz(Tuple5<A, B, C, D, E>* p, Fuzzer* fuzzer) { 369 FuzzParam(&p->a, fuzzer); 370 FuzzParam(&p->b, fuzzer); 371 FuzzParam(&p->c, fuzzer); 372 FuzzParam(&p->d, fuzzer); 373 FuzzParam(&p->e, fuzzer); 374 } 375}; 376 377// Specializations to fuzz containers. 378template <class A> 379struct FuzzTraits<std::vector<A> > { 380 static void Fuzz(std::vector<A>* p, Fuzzer* fuzzer) { 381 for (size_t i = 0; i < p->size(); ++i) { 382 FuzzParam(&p->at(i), fuzzer); 383 } 384 } 385}; 386 387template <class A, class B> 388struct FuzzTraits<std::map<A, B> > { 389 static void Fuzz(std::map<A, B>* p, Fuzzer* fuzzer) { 390 typename std::map<A, B>::iterator it; 391 for (it = p->begin(); it != p->end(); ++it) { 392 FuzzParam(&it->second, fuzzer); 393 } 394 } 395}; 396 397template <class A, class B> 398struct FuzzTraits<std::pair<A, B> > { 399 static void Fuzz(std::pair<A, B>* p, Fuzzer* fuzzer) { 400 FuzzParam(&p->second, fuzzer); 401 } 402}; 403 404// Specializations to fuzz hand-coded tyoes 405template <> 406struct FuzzTraits<base::FileDescriptor> { 407 static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) { 408 FuzzParam(&p->fd, fuzzer); 409 } 410}; 411 412template <> 413struct FuzzTraits<GURL> { 414 static void Fuzz(GURL *p, Fuzzer* fuzzer) { 415 FuzzParam(&p->possibly_invalid_spec(), fuzzer); 416 } 417}; 418 419template <> 420struct FuzzTraits<gfx::Point> { 421 static void Fuzz(gfx::Point *p, Fuzzer* fuzzer) { 422 int x = p->x(); 423 int y = p->y(); 424 FuzzParam(&x, fuzzer); 425 FuzzParam(&y, fuzzer); 426 p->SetPoint(x, y); 427 } 428}; 429 430template <> 431struct FuzzTraits<gfx::Size> { 432 static void Fuzz(gfx::Size *p, Fuzzer* fuzzer) { 433 int w = p->width(); 434 int h = p->height(); 435 FuzzParam(&w, fuzzer); 436 FuzzParam(&h, fuzzer); 437 p->SetSize(w, h); 438 } 439}; 440 441template <> 442struct FuzzTraits<gfx::Rect> { 443 static void Fuzz(gfx::Rect *p, Fuzzer* fuzzer) { 444 gfx::Point origin = p->origin(); 445 gfx::Size size = p->size(); 446 FuzzParam(&origin, fuzzer); 447 FuzzParam(&size, fuzzer); 448 p->set_origin(origin); 449 p->set_size(size); 450 } 451}; 452 453// Redefine macros to generate fuzzing from traits declarations. 454// Null out all the macros that need nulling. 455#include "ipc/ipc_message_null_macros.h" 456 457// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur. 458#undef IPC_STRUCT_BEGIN 459#undef IPC_STRUCT_BEGIN_WITH_PARENT 460#undef IPC_STRUCT_MEMBER 461#undef IPC_STRUCT_END 462#define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \ 463 IPC_STRUCT_BEGIN(struct_name) 464#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name) 465#define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name) 466#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END() 467 468// Set up so next include will generate fuzz trait classes. 469#undef IPC_STRUCT_TRAITS_BEGIN 470#undef IPC_STRUCT_TRAITS_MEMBER 471#undef IPC_STRUCT_TRAITS_PARENT 472#undef IPC_STRUCT_TRAITS_END 473#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \ 474 template <> \ 475 struct FuzzTraits<struct_name> { \ 476 static void Fuzz(struct_name *p, Fuzzer* fuzzer) { 477 478#define IPC_STRUCT_TRAITS_MEMBER(name) \ 479 FuzzParam(&p->name, fuzzer); 480 481#define IPC_STRUCT_TRAITS_PARENT(type) \ 482 FuzzParam(static_cast<type*>(p), fuzzer); 483 484#define IPC_STRUCT_TRAITS_END() \ 485 } \ 486 }; 487 488// TODO(tsepez): Make sure to end up with an enum that meets |condition|. 489#undef IPC_ENUM_TRAITS_VALIDATE 490#define IPC_ENUM_TRAITS_VALIDATE(enum_name, conditon) \ 491 template <> \ 492 struct FuzzTraits<enum_name> { \ 493 static void Fuzz(enum_name* p, Fuzzer* fuzzer) { \ 494 FuzzParam(reinterpret_cast<int*>(p), fuzzer); \ 495 } \ 496 }; 497 498// Bring them into existence. 499#include "tools/ipc_fuzzer/message_lib/all_messages.h" 500 501// Redefine macros to generate fuzzing funtions 502#include "ipc/ipc_message_null_macros.h" 503#undef IPC_MESSAGE_DECL 504#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ 505 IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist) 506 507#define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \ 508 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 509 return NULL; \ 510 } 511 512#define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \ 513 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 514 return NULL; \ 515 } 516 517#define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ 518 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 519 name* real_msg = static_cast<name*>(msg); \ 520 IPC_TUPLE_IN_##in ilist p; \ 521 name::Read(real_msg, &p); \ 522 FuzzParam(&p, fuzzer); \ 523 return new name(IPC_MEMBERS_IN_##in(p)); \ 524 } 525 526#define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ 527 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 528 name* real_msg = static_cast<name*>(msg); \ 529 IPC_TUPLE_IN_##in ilist p; \ 530 name::Read(real_msg, &p); \ 531 FuzzParam(&p, fuzzer); \ 532 return new name(msg->routing_id() \ 533 IPC_COMMA_##in \ 534 IPC_MEMBERS_IN_##in(p)); \ 535 } 536 537#define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ 538 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 539 name* real_msg = static_cast<name*>(msg); \ 540 IPC_TUPLE_IN_##in ilist p; \ 541 name::ReadSendParam(real_msg, &p); \ 542 FuzzParam(&p, fuzzer); \ 543 name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \ 544 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ 545 IPC_MEMBERS_OUT_##out()); \ 546 MessageCracker::CopyMessageID(new_msg, real_msg); \ 547 return new_msg; \ 548 } 549 550 551#define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ 552 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ 553 name* real_msg = static_cast<name*>(msg); \ 554 IPC_TUPLE_IN_##in ilist p; \ 555 name::ReadSendParam(real_msg, &p); \ 556 FuzzParam(&p, fuzzer); \ 557 name* new_msg = new name(msg->routing_id() \ 558 IPC_COMMA_OR_##out(IPC_COMMA_##in) \ 559 IPC_MEMBERS_IN_##in(p) \ 560 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ 561 IPC_MEMBERS_OUT_##out()); \ 562 MessageCracker::CopyMessageID(new_msg, real_msg); \ 563 return new_msg; \ 564 } 565 566#define IPC_MEMBERS_IN_0(p) 567#define IPC_MEMBERS_IN_1(p) p.a 568#define IPC_MEMBERS_IN_2(p) p.a, p.b 569#define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c 570#define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d 571#define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e 572 573#define IPC_MEMBERS_OUT_0() 574#define IPC_MEMBERS_OUT_1() NULL 575#define IPC_MEMBERS_OUT_2() NULL, NULL 576#define IPC_MEMBERS_OUT_3() NULL, NULL, NULL 577#define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL 578#define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL 579 580#include "tools/ipc_fuzzer/message_lib/all_messages.h" 581 582typedef IPC::Message* (*FuzzFunction)(IPC::Message*, Fuzzer*); 583typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap; 584 585// Redefine macros to register fuzzing functions into map. 586#include "ipc/ipc_message_null_macros.h" 587#undef IPC_MESSAGE_DECL 588#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ 589 (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name; 590 591void PopulateFuzzFunctionMap(FuzzFunctionMap *map) { 592#include "tools/ipc_fuzzer/message_lib/all_messages.h" 593} 594 595static IPC::Message* RewriteMessage( 596 IPC::Message* message, 597 Fuzzer* fuzzer, 598 FuzzFunctionMap* map) { 599 FuzzFunctionMap::iterator it = map->find(message->type()); 600 if (it == map->end()) { 601 // This usually indicates a missing message file in all_messages.h, or 602 // that the message dump file is taken from a different revision of 603 // chromium from this executable. 604 std::cerr << "Unknown message type: [" 605 << IPC_MESSAGE_ID_CLASS(message->type()) << ", " 606 << IPC_MESSAGE_ID_LINE(message->type()) << "].\n"; 607 return 0; 608 } 609 610 return (*it->second)(message, fuzzer); 611} 612 613namespace { 614 615const char kHelpSwitch[] = "help"; 616const char kHelpSwitchHelp[] = 617 "show this message"; 618 619const char kFrequencySwitch[] = "frequency"; 620const char kFrequencySwitchHelp[] = 621 "probability of mutation; tweak every 1/|q| times."; 622 623const char kFuzzerNameSwitch[] = "fuzzer-name"; 624const char kFuzzerNameSwitchHelp[] = 625 "select default or no-op fuzzer."; 626 627const char kPermuteSwitch[] = "permute"; 628const char kPermuteSwitchHelp[] = 629 "Randomly shuffle the order of all messages."; 630 631const char kTypeListSwitch[] = "type-list"; 632const char kTypeListSwitchHelp[] = 633 "explicit list of the only message-ids to mutate."; 634 635void usage() { 636 std::cerr << "Mutate messages from an exiting message file.\n"; 637 638 std::cerr << "Usage:\n" 639 << " ipc_fuzzer_mutate" 640 << " [--" << kHelpSwitch << "]" 641 << " [--" << kFuzzerNameSwitch << "=f]" 642 << " [--" << kFrequencySwitch << "=q]" 643 << " [--" << kTypeListSwitch << "=x,y,z...]" 644 << " [--" << kPermuteSwitch << "]" 645 << " infile outfile\n"; 646 647 std::cerr 648 << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n" 649 << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n" 650 << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n" 651 << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n" 652 << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n"; 653} 654 655} // namespace 656 657int MutateMain(int argc, char** argv) { 658 CommandLine::Init(argc, argv); 659 CommandLine* cmd = CommandLine::ForCurrentProcess(); 660 CommandLine::StringVector args = cmd->GetArgs(); 661 662 if (args.size() != 2 || cmd->HasSwitch(kHelpSwitch)) { 663 usage(); 664 return EXIT_FAILURE; 665 } 666 667 std::string input_file_name = args[0]; 668 std::string output_file_name = args[1]; 669 670 bool permute = cmd->HasSwitch(kPermuteSwitch); 671 672 std::string fuzzer_name = "default"; 673 if (cmd->HasSwitch(kFuzzerNameSwitch)) 674 fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch); 675 676 int frequency = 23; 677 if (cmd->HasSwitch(kFrequencySwitch)) 678 frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str()); 679 680 std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch); 681 std::vector<std::string> type_string_vector; 682 base::SplitString(type_string_list, ',', &type_string_vector); 683 std::set<int> type_set; 684 for (size_t i = 0; i < type_string_vector.size(); ++i) { 685 type_set.insert(atoi(type_string_vector[i].c_str())); 686 } 687 688 InitRand(); 689 690 Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency); 691 if (!fuzzer) 692 return EXIT_FAILURE; 693 694 FuzzFunctionMap fuzz_function_map; 695 PopulateFuzzFunctionMap(&fuzz_function_map); 696 697 MessageVector message_vector; 698 if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector)) 699 return EXIT_FAILURE; 700 701 for (size_t i = 0; i < message_vector.size(); ++i) { 702 IPC::Message* msg = message_vector[i]; 703 if (!type_set.empty() && type_set.end() == std::find( 704 type_set.begin(), type_set.end(), msg->type())) { 705 continue; 706 } 707 IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map); 708 if (new_message) { 709 delete message_vector[i]; 710 message_vector[i] = new_message; 711 } 712 } 713 714 if (permute) { 715 std::random_shuffle(message_vector.begin(), message_vector.end(), 716 RandInRange); 717 } 718 719 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector)) 720 return EXIT_FAILURE; 721 722 return EXIT_SUCCESS; 723} 724 725} // namespace ipc_fuzzer 726 727int main(int argc, char** argv) { 728 return ipc_fuzzer::MutateMain(argc, argv); 729} 730