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 34 namespace IPC { 35 class Message; 36 } // namespace IPC 37 38 namespace 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. 43 class 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 63 template <typename T> 64 void 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 75 template <typename T> 76 void 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. 90 class 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. 173 class 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 195 class 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. 210 template <class P> 211 struct 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. 220 template <class P> 221 static void FuzzParam(P* p, Fuzzer* fuzzer) { 222 FuzzTraits<P>::Fuzz(p, fuzzer); 223 } 224 225 // Specializations to fuzz primitive types. 226 template <> 227 struct FuzzTraits<bool> { 228 static void Fuzz(bool* p, Fuzzer* fuzzer) { 229 fuzzer->FuzzBool(p); 230 } 231 }; 232 233 template <> 234 struct FuzzTraits<int> { 235 static void Fuzz(int* p, Fuzzer* fuzzer) { 236 fuzzer->FuzzInt(p); 237 } 238 }; 239 240 template <> 241 struct FuzzTraits<unsigned int> { 242 static void Fuzz(unsigned int* p, Fuzzer* fuzzer) { 243 fuzzer->FuzzInt(reinterpret_cast<int*>(p)); 244 } 245 }; 246 247 template <> 248 struct FuzzTraits<long> { 249 static void Fuzz(long* p, Fuzzer* fuzzer) { 250 fuzzer->FuzzLong(p); 251 } 252 }; 253 254 template <> 255 struct FuzzTraits<unsigned long> { 256 static void Fuzz(unsigned long* p, Fuzzer* fuzzer) { 257 fuzzer->FuzzLong(reinterpret_cast<long*>(p)); 258 } 259 }; 260 261 template <> 262 struct FuzzTraits<long long> { 263 static void Fuzz(long long* p, Fuzzer* fuzzer) { 264 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 265 } 266 }; 267 268 template <> 269 struct FuzzTraits<unsigned long long> { 270 static void Fuzz(unsigned long long* p, Fuzzer* fuzzer) { 271 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 272 } 273 }; 274 275 template <> 276 struct FuzzTraits<short> { 277 static void Fuzz(short* p, Fuzzer* fuzzer) { 278 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 279 } 280 }; 281 282 template <> 283 struct FuzzTraits<unsigned short> { 284 static void Fuzz(unsigned short* p, Fuzzer* fuzzer) { 285 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 286 } 287 }; 288 289 template <> 290 struct FuzzTraits<char> { 291 static void Fuzz(char* p, Fuzzer* fuzzer) { 292 fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p)); 293 } 294 }; 295 296 template <> 297 struct FuzzTraits<unsigned char> { 298 static void Fuzz(unsigned char* p, Fuzzer* fuzzer) { 299 fuzzer->FuzzUChar(p); 300 } 301 }; 302 303 template <> 304 struct FuzzTraits<float> { 305 static void Fuzz(float* p, Fuzzer* fuzzer) { 306 fuzzer->FuzzFloat(p); 307 } 308 }; 309 310 template <> 311 struct FuzzTraits<double> { 312 static void Fuzz(double* p, Fuzzer* fuzzer) { 313 fuzzer->FuzzDouble(p); 314 } 315 }; 316 317 template <> 318 struct FuzzTraits<std::string> { 319 static void Fuzz(std::string* p, Fuzzer* fuzzer) { 320 fuzzer->FuzzString(p); 321 } 322 }; 323 324 template <> 325 struct FuzzTraits<base::string16> { 326 static void Fuzz(base::string16* p, Fuzzer* fuzzer) { 327 fuzzer->FuzzString16(p); 328 } 329 }; 330 331 // Specializations to fuzz tuples. 332 template <class A> 333 struct FuzzTraits<Tuple1<A> > { 334 static void Fuzz(Tuple1<A>* p, Fuzzer* fuzzer) { 335 FuzzParam(&p->a, fuzzer); 336 } 337 }; 338 339 template <class A, class B> 340 struct 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 347 template <class A, class B, class C> 348 struct 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 356 template <class A, class B, class C, class D> 357 struct 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 366 template <class A, class B, class C, class D, class E> 367 struct 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. 378 template <class A> 379 struct 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 387 template <class A, class B> 388 struct 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 397 template <class A, class B> 398 struct 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 405 template <> 406 struct FuzzTraits<base::FileDescriptor> { 407 static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) { 408 FuzzParam(&p->fd, fuzzer); 409 } 410 }; 411 412 template <> 413 struct FuzzTraits<GURL> { 414 static void Fuzz(GURL *p, Fuzzer* fuzzer) { 415 FuzzParam(&p->possibly_invalid_spec(), fuzzer); 416 } 417 }; 418 419 template <> 420 struct 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 430 template <> 431 struct 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 441 template <> 442 struct 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 582 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, Fuzzer*); 583 typedef 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 591 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) { 592 #include "tools/ipc_fuzzer/message_lib/all_messages.h" 593 } 594 595 static 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 613 namespace { 614 615 const char kHelpSwitch[] = "help"; 616 const char kHelpSwitchHelp[] = 617 "show this message"; 618 619 const char kFrequencySwitch[] = "frequency"; 620 const char kFrequencySwitchHelp[] = 621 "probability of mutation; tweak every 1/|q| times."; 622 623 const char kFuzzerNameSwitch[] = "fuzzer-name"; 624 const char kFuzzerNameSwitchHelp[] = 625 "select default or no-op fuzzer."; 626 627 const char kPermuteSwitch[] = "permute"; 628 const char kPermuteSwitchHelp[] = 629 "Randomly shuffle the order of all messages."; 630 631 const char kTypeListSwitch[] = "type-list"; 632 const char kTypeListSwitchHelp[] = 633 "explicit list of the only message-ids to mutate."; 634 635 void 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 657 int 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 727 int main(int argc, char** argv) { 728 return ipc_fuzzer::MutateMain(argc, argv); 729 } 730