1 // Copyright (c) 2012 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 <algorithm> 6 #include <ostream> 7 #include <set> 8 #include <vector> 9 10 #include "base/command_line.h" 11 #include "base/containers/hash_tables.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/singleton.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/pickle.h" 16 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_util.h" 18 #include "base/strings/utf_string_conversions.h" 19 #include "base/threading/thread.h" 20 #include "base/time/time.h" 21 #include "chrome/common/all_messages.h" 22 #include "content/common/all_messages.h" 23 #include "ipc/ipc_message.h" 24 #include "ipc/ipc_message_utils.h" 25 #include "ipc/ipc_switches.h" 26 #include "ipc/ipc_sync_channel.h" 27 #include "ipc/ipc_sync_message.h" 28 29 #if defined(OS_POSIX) 30 #include <unistd.h> 31 #endif 32 33 namespace IPC { 34 class Message; 35 36 // Interface implemented by those who fuzz basic types. The types all 37 // correspond to the types which a pickle from base/pickle.h can pickle, 38 // plus the floating point types. 39 class Fuzzer { 40 public: 41 // Select a message for fuzzing. 42 virtual bool FuzzThisMessage(const IPC::Message *msg) = 0; 43 44 // Tweak individual values within a message. 45 virtual void FuzzBool(bool* value) = 0; 46 virtual void FuzzInt(int* value) = 0; 47 virtual void FuzzLong(long* value) = 0; 48 virtual void FuzzSize(size_t* value) = 0; 49 virtual void FuzzUChar(unsigned char *value) = 0; 50 virtual void FuzzUInt16(uint16* value) = 0; 51 virtual void FuzzUInt32(uint32* value) = 0; 52 virtual void FuzzInt64(int64* value) = 0; 53 virtual void FuzzUInt64(uint64* value) = 0; 54 virtual void FuzzFloat(float *value) = 0; 55 virtual void FuzzDouble(double *value) = 0; 56 virtual void FuzzString(std::string* value) = 0; 57 virtual void FuzzWString(std::wstring* value) = 0; 58 virtual void FuzzString16(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 } // namespace IPC 64 65 namespace { 66 67 template <typename T> 68 void FuzzIntegralType(T* value, unsigned int frequency) { 69 if (rand() % frequency == 0) { 70 switch (rand() % 4) { 71 case 0: (*value) = 0; break; 72 case 1: (*value)--; break; 73 case 2: (*value)++; break; 74 case 3: (*value) ^= rand(); break; 75 } 76 } 77 } 78 79 template <typename T> 80 void FuzzStringType(T* value, unsigned int frequency, 81 const T& literal1, const T& literal2) { 82 if (rand() % frequency == 0) { 83 switch (rand() % 5) { 84 case 4: (*value) = (*value) + (*value); // FALLTHROUGH 85 case 3: (*value) = (*value) + (*value); // FALLTHROUGH 86 case 2: (*value) = (*value) + (*value); break; 87 case 1: (*value) += literal1; break; 88 case 0: (*value) = literal2; break; 89 } 90 } 91 } 92 93 } // namespace 94 95 // One such fuzzer implementation. 96 class DefaultFuzzer : public IPC::Fuzzer { 97 public: 98 static const int DEFAULT_FREQUENCY = 23; 99 100 DefaultFuzzer() : frequency_(DEFAULT_FREQUENCY) { 101 const char *env_var; 102 if ((env_var = getenv("CHROME_IPC_FUZZING_LIST"))) { 103 std::string str = std::string(env_var); 104 size_t pos; 105 while ((pos = str.find_first_of(',')) != std::string::npos) { 106 message_set_.insert(atoi(str.substr(0, pos).c_str())); 107 str = str.substr(pos+1); 108 } 109 message_set_.insert(atoi(str.c_str())); 110 } 111 112 if ((env_var = getenv("CHROME_IPC_FUZZING_SEED"))) { 113 int new_seed = atoi(env_var); 114 if (new_seed) 115 srand(new_seed); 116 } 117 118 if ((env_var = getenv("CHROME_IPC_FUZZING_FREQUENCY"))) { 119 unsigned int new_frequency = atoi(env_var); 120 if (new_frequency) 121 frequency_ = new_frequency; 122 } 123 } 124 125 virtual ~DefaultFuzzer() {} 126 127 virtual bool FuzzThisMessage(const IPC::Message *msg) OVERRIDE { 128 return (message_set_.empty() || 129 std::find(message_set_.begin(), 130 message_set_.end(), 131 msg->type()) != message_set_.end()); 132 } 133 134 virtual void FuzzBool(bool* value) OVERRIDE { 135 if (rand() % frequency_ == 0) 136 (*value) = !(*value); 137 } 138 139 virtual void FuzzInt(int* value) OVERRIDE { 140 FuzzIntegralType<int>(value, frequency_); 141 } 142 143 virtual void FuzzLong(long* value) OVERRIDE { 144 FuzzIntegralType<long>(value, frequency_); 145 } 146 147 virtual void FuzzSize(size_t* value) OVERRIDE { 148 FuzzIntegralType<size_t>(value, frequency_); 149 } 150 151 virtual void FuzzUChar(unsigned char* value) OVERRIDE { 152 FuzzIntegralType<unsigned char>(value, frequency_); 153 } 154 155 virtual void FuzzUInt16(uint16* value) OVERRIDE { 156 FuzzIntegralType<uint16>(value, frequency_); 157 } 158 159 virtual void FuzzUInt32(uint32* value) OVERRIDE { 160 FuzzIntegralType<uint32>(value, frequency_); 161 } 162 163 virtual void FuzzInt64(int64* value) OVERRIDE { 164 FuzzIntegralType<int64>(value, frequency_); 165 } 166 167 virtual void FuzzUInt64(uint64* value) OVERRIDE { 168 FuzzIntegralType<uint64>(value, frequency_); 169 } 170 171 virtual void FuzzFloat(float* value) OVERRIDE { 172 if (rand() % frequency_ == 0) 173 (*value) *= rand() / 1000000.0; 174 } 175 176 virtual void FuzzDouble(double* value) OVERRIDE { 177 if (rand() % frequency_ == 0) 178 (*value) *= rand() / 1000000.0; 179 } 180 181 virtual void FuzzString(std::string* value) OVERRIDE { 182 FuzzStringType<std::string>(value, frequency_, "BORKED", std::string()); 183 } 184 185 virtual void FuzzWString(std::wstring* value) OVERRIDE { 186 FuzzStringType<std::wstring>(value, frequency_, L"BORKED", std::wstring()); 187 } 188 189 virtual void FuzzString16(string16* value) OVERRIDE { 190 FuzzStringType<string16>(value, frequency_, 191 WideToUTF16(L"BORKED"), 192 WideToUTF16(std::wstring())); 193 } 194 195 virtual void FuzzData(char* data, int length) OVERRIDE { 196 if (rand() % frequency_ == 0) { 197 for (int i = 0; i < length; ++i) { 198 FuzzIntegralType<char>(&data[i], frequency_); 199 } 200 } 201 } 202 203 virtual void FuzzBytes(void* data, int data_len) OVERRIDE { 204 FuzzData(static_cast<char*>(data), data_len); 205 } 206 207 private: 208 std::set<int> message_set_; 209 unsigned int frequency_; 210 }; 211 212 213 // No-op fuzzer. Rewrites each message unchanged to check if the message 214 // re-assembly is legit. 215 class NoOpFuzzer : public IPC::Fuzzer { 216 public: 217 NoOpFuzzer() {} 218 virtual ~NoOpFuzzer() {} 219 220 virtual bool FuzzThisMessage(const IPC::Message *msg) OVERRIDE { 221 return true; 222 } 223 224 virtual void FuzzBool(bool* value) OVERRIDE {} 225 virtual void FuzzInt(int* value) OVERRIDE {} 226 virtual void FuzzLong(long* value) OVERRIDE {} 227 virtual void FuzzSize(size_t* value) OVERRIDE {} 228 virtual void FuzzUChar(unsigned char* value) OVERRIDE {} 229 virtual void FuzzUInt16(uint16* value) OVERRIDE {} 230 virtual void FuzzUInt32(uint32* value) OVERRIDE {} 231 virtual void FuzzInt64(int64* value) OVERRIDE {} 232 virtual void FuzzUInt64(uint64* value) OVERRIDE {} 233 virtual void FuzzFloat(float* value) OVERRIDE {} 234 virtual void FuzzDouble(double* value) OVERRIDE {} 235 virtual void FuzzString(std::string* value) OVERRIDE {} 236 virtual void FuzzWString(std::wstring* value) OVERRIDE {} 237 virtual void FuzzString16(string16* value) OVERRIDE {} 238 virtual void FuzzData(char* data, int length) OVERRIDE {} 239 virtual void FuzzBytes(void* data, int data_len) OVERRIDE {} 240 }; 241 242 class FuzzerFactory { 243 public: 244 static IPC::Fuzzer *NewFuzzer(const std::string& name) { 245 if (name == "no-op") 246 return new NoOpFuzzer(); 247 else 248 return new DefaultFuzzer(); 249 } 250 }; 251 252 // Partially-specialized class that knows how to fuzz a given type. 253 template <class P> 254 struct FuzzTraits { 255 static void Fuzz(P* p, IPC::Fuzzer *fuzzer) {} 256 }; 257 258 // Template function to invoke partially-specialized class method. 259 template <class P> 260 static void FuzzParam(P* p, IPC::Fuzzer* fuzzer) { 261 FuzzTraits<P>::Fuzz(p, fuzzer); 262 } 263 264 // Specializations to fuzz primitive types. 265 template <> 266 struct FuzzTraits<bool> { 267 static void Fuzz(bool* p, IPC::Fuzzer* fuzzer) { 268 fuzzer->FuzzBool(p); 269 } 270 }; 271 272 template <> 273 struct FuzzTraits<int> { 274 static void Fuzz(int* p, IPC::Fuzzer* fuzzer) { 275 fuzzer->FuzzInt(p); 276 } 277 }; 278 279 template <> 280 struct FuzzTraits<unsigned int> { 281 static void Fuzz(unsigned int* p, IPC::Fuzzer* fuzzer) { 282 fuzzer->FuzzInt(reinterpret_cast<int*>(p)); 283 } 284 }; 285 286 template <> 287 struct FuzzTraits<long> { 288 static void Fuzz(long* p, IPC::Fuzzer* fuzzer) { 289 fuzzer->FuzzLong(p); 290 } 291 }; 292 293 template <> 294 struct FuzzTraits<unsigned long> { 295 static void Fuzz(unsigned long* p, IPC::Fuzzer* fuzzer) { 296 fuzzer->FuzzLong(reinterpret_cast<long*>(p)); 297 } 298 }; 299 300 template <> 301 struct FuzzTraits<long long> { 302 static void Fuzz(long long* p, IPC::Fuzzer* fuzzer) { 303 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 304 } 305 }; 306 307 template <> 308 struct FuzzTraits<unsigned long long> { 309 static void Fuzz(unsigned long long* p, IPC::Fuzzer* fuzzer) { 310 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); 311 } 312 }; 313 314 template <> 315 struct FuzzTraits<short> { 316 static void Fuzz(short* p, IPC::Fuzzer* fuzzer) { 317 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 318 } 319 }; 320 321 template <> 322 struct FuzzTraits<unsigned short> { 323 static void Fuzz(unsigned short* p, IPC::Fuzzer* fuzzer) { 324 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); 325 } 326 }; 327 328 template <> 329 struct FuzzTraits<char> { 330 static void Fuzz(char* p, IPC::Fuzzer* fuzzer) { 331 fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p)); 332 } 333 }; 334 335 template <> 336 struct FuzzTraits<unsigned char> { 337 static void Fuzz(unsigned char* p, IPC::Fuzzer* fuzzer) { 338 fuzzer->FuzzUChar(p); 339 } 340 }; 341 342 template <> 343 struct FuzzTraits<float> { 344 static void Fuzz(float* p, IPC::Fuzzer* fuzzer) { 345 fuzzer->FuzzFloat(p); 346 } 347 }; 348 349 template <> 350 struct FuzzTraits<double> { 351 static void Fuzz(double* p, IPC::Fuzzer* fuzzer) { 352 fuzzer->FuzzDouble(p); 353 } 354 }; 355 356 template <> 357 struct FuzzTraits<std::string> { 358 static void Fuzz(std::string* p, IPC::Fuzzer* fuzzer) { 359 fuzzer->FuzzString(p); 360 } 361 }; 362 363 template <> 364 struct FuzzTraits<std::wstring> { 365 static void Fuzz(std::wstring* p, IPC::Fuzzer* fuzzer) { 366 fuzzer->FuzzWString(p); 367 } 368 }; 369 370 template <> 371 struct FuzzTraits<string16> { 372 static void Fuzz(string16* p, IPC::Fuzzer* fuzzer) { 373 fuzzer->FuzzString16(p); 374 } 375 }; 376 377 // Specializations to fuzz tuples. 378 template <class A> 379 struct FuzzTraits<Tuple1<A> > { 380 static void Fuzz(Tuple1<A>* p, IPC::Fuzzer* fuzzer) { 381 FuzzParam(&p->a, fuzzer); 382 } 383 }; 384 385 template <class A, class B> 386 struct FuzzTraits<Tuple2<A, B> > { 387 static void Fuzz(Tuple2<A, B>* p, IPC::Fuzzer* fuzzer) { 388 FuzzParam(&p->a, fuzzer); 389 FuzzParam(&p->b, fuzzer); 390 } 391 }; 392 393 template <class A, class B, class C> 394 struct FuzzTraits<Tuple3<A, B, C> > { 395 static void Fuzz(Tuple3<A, B, C>* p, IPC::Fuzzer* fuzzer) { 396 FuzzParam(&p->a, fuzzer); 397 FuzzParam(&p->b, fuzzer); 398 FuzzParam(&p->c, fuzzer); 399 } 400 }; 401 402 template <class A, class B, class C, class D> 403 struct FuzzTraits<Tuple4<A, B, C, D> > { 404 static void Fuzz(Tuple4<A, B, C, D>* p, IPC::Fuzzer* fuzzer) { 405 FuzzParam(&p->a, fuzzer); 406 FuzzParam(&p->b, fuzzer); 407 FuzzParam(&p->c, fuzzer); 408 FuzzParam(&p->d, fuzzer); 409 } 410 }; 411 412 template <class A, class B, class C, class D, class E> 413 struct FuzzTraits<Tuple5<A, B, C, D, E> > { 414 static void Fuzz(Tuple5<A, B, C, D, E>* p, IPC::Fuzzer* fuzzer) { 415 FuzzParam(&p->a, fuzzer); 416 FuzzParam(&p->b, fuzzer); 417 FuzzParam(&p->c, fuzzer); 418 FuzzParam(&p->d, fuzzer); 419 FuzzParam(&p->e, fuzzer); 420 } 421 }; 422 423 // Specializations to fuzz containers. 424 template <class A> 425 struct FuzzTraits<std::vector<A> > { 426 static void Fuzz(std::vector<A>* p, IPC::Fuzzer* fuzzer) { 427 for (size_t i = 0; i < p->size(); ++i) { 428 FuzzParam(&p->at(i), fuzzer); 429 } 430 } 431 }; 432 433 template <class A, class B> 434 struct FuzzTraits<std::map<A, B> > { 435 static void Fuzz(std::map<A, B>* p, IPC::Fuzzer* fuzzer) { 436 typename std::map<A, B>::iterator it; 437 for (it = p->begin(); it != p->end(); ++it) { 438 FuzzParam(&it->second, fuzzer); 439 } 440 } 441 }; 442 443 template <class A, class B> 444 struct FuzzTraits<std::pair<A, B> > { 445 static void Fuzz(std::pair<A, B>* p, IPC::Fuzzer* fuzzer) { 446 FuzzParam(&p->second, fuzzer); 447 } 448 }; 449 450 // Specializations to fuzz hand-coded tyoes 451 template <> 452 struct FuzzTraits<base::FileDescriptor> { 453 static void Fuzz(base::FileDescriptor* p, IPC::Fuzzer* fuzzer) { 454 FuzzParam(&p->fd, fuzzer); 455 } 456 }; 457 458 template <> 459 struct FuzzTraits<GURL> { 460 static void Fuzz(GURL *p, IPC::Fuzzer* fuzzer) { 461 FuzzParam(&p->possibly_invalid_spec(), fuzzer); 462 } 463 }; 464 465 template <> 466 struct FuzzTraits<gfx::Point> { 467 static void Fuzz(gfx::Point *p, IPC::Fuzzer* fuzzer) { 468 int x = p->x(); 469 int y = p->y(); 470 FuzzParam(&x, fuzzer); 471 FuzzParam(&y, fuzzer); 472 p->SetPoint(x, y); 473 } 474 }; 475 476 template <> 477 struct FuzzTraits<gfx::Size> { 478 static void Fuzz(gfx::Size *p, IPC::Fuzzer* fuzzer) { 479 int w = p->width(); 480 int h = p->height(); 481 FuzzParam(&w, fuzzer); 482 FuzzParam(&h, fuzzer); 483 p->SetSize(w, h); 484 } 485 }; 486 487 template <> 488 struct FuzzTraits<gfx::Rect> { 489 static void Fuzz(gfx::Rect *p, IPC::Fuzzer* fuzzer) { 490 gfx::Point origin = p->origin(); 491 gfx::Size size = p->size(); 492 FuzzParam(&origin, fuzzer); 493 FuzzParam(&size, fuzzer); 494 p->set_origin(origin); 495 p->set_size(size); 496 } 497 }; 498 499 // Means for updating message id in pickles. 500 class PickleCracker : public Pickle { 501 public: 502 static void CopyMessageID(PickleCracker *dst, PickleCracker *src) { 503 memcpy(dst->mutable_payload(), src->payload(), sizeof(int)); 504 } 505 }; 506 507 // Redefine macros to generate fuzzing from traits declarations. 508 // Null out all the macros that need nulling. 509 #include "ipc/ipc_message_null_macros.h" 510 511 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur. 512 #undef IPC_STRUCT_BEGIN_WITH_PARENT 513 #undef IPC_STRUCT_MEMBER 514 #undef IPC_STRUCT_END 515 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent)\ 516 IPC_STRUCT_TRAITS_BEGIN(struct_name) 517 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name) 518 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END() 519 520 // Set up so next include will generate fuzz trait classes. 521 #undef IPC_STRUCT_TRAITS_BEGIN 522 #undef IPC_STRUCT_TRAITS_MEMBER 523 #undef IPC_STRUCT_TRAITS_PARENT 524 #undef IPC_STRUCT_TRAITS_END 525 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \ 526 template <> \ 527 struct FuzzTraits<struct_name> { \ 528 static void Fuzz(struct_name *p, IPC::Fuzzer* fuzzer) { \ 529 530 #define IPC_STRUCT_TRAITS_MEMBER(name) \ 531 FuzzParam(&p->name, fuzzer); 532 533 #define IPC_STRUCT_TRAITS_PARENT(type) \ 534 FuzzParam(static_cast<type*>(p), fuzzer); 535 536 #define IPC_STRUCT_TRAITS_END() \ 537 } \ 538 }; 539 540 #undef IPC_ENUM_TRAITS_VALIDATE 541 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \ 542 template <> \ 543 struct FuzzTraits<enum_name> { \ 544 static void Fuzz(enum_name* p, IPC::Fuzzer* fuzzer) { \ 545 FuzzParam(reinterpret_cast<int*>(p), fuzzer); \ 546 } \ 547 }; 548 549 // Bring them into existence. 550 #include "chrome/common/all_messages.h" 551 #include "content/common/all_messages.h" 552 553 // Redefine macros to generate fuzzing funtions 554 #include "ipc/ipc_message_null_macros.h" 555 #undef IPC_MESSAGE_DECL 556 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ 557 IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist) 558 559 #define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \ 560 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 561 return NULL; \ 562 } 563 564 #define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \ 565 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 566 return NULL; \ 567 } 568 569 #define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ 570 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 571 name* real_msg = static_cast<name*>(msg); \ 572 IPC_TUPLE_IN_##in ilist p; \ 573 name::Read(real_msg, &p); \ 574 FuzzParam(&p, fuzzer); \ 575 return new name(IPC_MEMBERS_IN_##in(p)); \ 576 } 577 578 #define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ 579 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 580 name* real_msg = static_cast<name*>(msg); \ 581 IPC_TUPLE_IN_##in ilist p; \ 582 name::Read(real_msg, &p); \ 583 FuzzParam(&p, fuzzer); \ 584 return new name(msg->routing_id() \ 585 IPC_COMMA_##in \ 586 IPC_MEMBERS_IN_##in(p)); \ 587 } 588 589 #define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ 590 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 591 name* real_msg = static_cast<name*>(msg); \ 592 IPC_TUPLE_IN_##in ilist p; \ 593 name::ReadSendParam(real_msg, &p); \ 594 FuzzParam(&p, fuzzer); \ 595 name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \ 596 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ 597 IPC_MEMBERS_OUT_##out()); \ 598 PickleCracker::CopyMessageID( \ 599 reinterpret_cast<PickleCracker *>(new_msg), \ 600 reinterpret_cast<PickleCracker *>(real_msg)); \ 601 return new_msg; \ 602 } 603 604 605 #define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ 606 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ 607 name* real_msg = static_cast<name*>(msg); \ 608 IPC_TUPLE_IN_##in ilist p; \ 609 name::ReadSendParam(real_msg, &p); \ 610 FuzzParam(&p, fuzzer); \ 611 name* new_msg = new name(msg->routing_id() \ 612 IPC_COMMA_OR_##out(IPC_COMMA_##in) \ 613 IPC_MEMBERS_IN_##in(p) \ 614 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ 615 IPC_MEMBERS_OUT_##out()); \ 616 PickleCracker::CopyMessageID( \ 617 reinterpret_cast<PickleCracker *>(new_msg), \ 618 reinterpret_cast<PickleCracker *>(real_msg)); \ 619 return new_msg; \ 620 } 621 622 #define IPC_MEMBERS_IN_0(p) 623 #define IPC_MEMBERS_IN_1(p) p.a 624 #define IPC_MEMBERS_IN_2(p) p.a, p.b 625 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c 626 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d 627 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e 628 629 #define IPC_MEMBERS_OUT_0() 630 #define IPC_MEMBERS_OUT_1() NULL 631 #define IPC_MEMBERS_OUT_2() NULL, NULL 632 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL 633 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL 634 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL 635 636 #include "chrome/common/all_messages.h" 637 #include "content/common/all_messages.h" 638 639 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, IPC::Fuzzer*); 640 typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap; 641 642 // Redefine macros to register fuzzing functions into map. 643 #include "ipc/ipc_message_null_macros.h" 644 #undef IPC_MESSAGE_DECL 645 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ 646 (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name; 647 648 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) { 649 #include "chrome/common/all_messages.h" 650 #include "content/common/all_messages.h" 651 } 652 653 class ipcfuzz : public IPC::ChannelProxy::OutgoingMessageFilter { 654 public: 655 ipcfuzz() { 656 const char* env_var = getenv("CHROME_IPC_FUZZING_KIND"); 657 fuzzer_ = FuzzerFactory::NewFuzzer(env_var ? env_var : ""); 658 PopulateFuzzFunctionMap(&fuzz_function_map_); 659 } 660 661 virtual IPC::Message* Rewrite(IPC::Message* message) OVERRIDE { 662 if (fuzzer_ && fuzzer_->FuzzThisMessage(message)) { 663 FuzzFunctionMap::iterator it = fuzz_function_map_.find(message->type()); 664 if (it != fuzz_function_map_.end()) { 665 IPC::Message* fuzzed_message = (*it->second)(message, fuzzer_); 666 if (fuzzed_message) { 667 delete message; 668 message = fuzzed_message; 669 } 670 } 671 } 672 return message; 673 } 674 675 private: 676 IPC::Fuzzer* fuzzer_; 677 FuzzFunctionMap fuzz_function_map_; 678 }; 679 680 ipcfuzz g_ipcfuzz; 681 682 // Entry point avoiding mangled names. 683 extern "C" { 684 __attribute__((visibility("default"))) 685 IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void); 686 } 687 688 IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void) { 689 return &g_ipcfuzz; 690 } 691