| OLD | NEW |
| (Empty) |
| 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 void FuzzBool(bool* value) override { | |
| 98 if (RandEvent(frequency_)) | |
| 99 (*value) = !(*value); | |
| 100 } | |
| 101 | |
| 102 void FuzzInt(int* value) override { | |
| 103 FuzzIntegralType<int>(value, frequency_); | |
| 104 } | |
| 105 | |
| 106 void FuzzLong(long* value) override { | |
| 107 FuzzIntegralType<long>(value, frequency_); | |
| 108 } | |
| 109 | |
| 110 void FuzzSize(size_t* value) override { | |
| 111 FuzzIntegralType<size_t>(value, frequency_); | |
| 112 } | |
| 113 | |
| 114 void FuzzUChar(unsigned char* value) override { | |
| 115 FuzzIntegralType<unsigned char>(value, frequency_); | |
| 116 } | |
| 117 | |
| 118 void FuzzUInt16(uint16* value) override { | |
| 119 FuzzIntegralType<uint16>(value, frequency_); | |
| 120 } | |
| 121 | |
| 122 void FuzzUInt32(uint32* value) override { | |
| 123 FuzzIntegralType<uint32>(value, frequency_); | |
| 124 } | |
| 125 | |
| 126 void FuzzInt64(int64* value) override { | |
| 127 FuzzIntegralType<int64>(value, frequency_); | |
| 128 } | |
| 129 | |
| 130 void FuzzUInt64(uint64* value) override { | |
| 131 FuzzIntegralType<uint64>(value, frequency_); | |
| 132 } | |
| 133 | |
| 134 void FuzzFloat(float* value) override { | |
| 135 if (RandEvent(frequency_)) | |
| 136 *value = RandDouble(); | |
| 137 } | |
| 138 | |
| 139 void FuzzDouble(double* value) override { | |
| 140 if (RandEvent(frequency_)) | |
| 141 *value = RandDouble(); | |
| 142 } | |
| 143 | |
| 144 void FuzzString(std::string* value) override { | |
| 145 FuzzStringType<std::string>(value, frequency_, "BORKED", std::string()); | |
| 146 } | |
| 147 | |
| 148 void FuzzString16(base::string16* value) override { | |
| 149 FuzzStringType<base::string16>(value, frequency_, | |
| 150 base::WideToUTF16(L"BORKED"), | |
| 151 base::WideToUTF16(L"")); | |
| 152 } | |
| 153 | |
| 154 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 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 void FuzzBool(bool* value) override {} | |
| 179 void FuzzInt(int* value) override {} | |
| 180 void FuzzLong(long* value) override {} | |
| 181 void FuzzSize(size_t* value) override {} | |
| 182 void FuzzUChar(unsigned char* value) override {} | |
| 183 void FuzzUInt16(uint16* value) override {} | |
| 184 void FuzzUInt32(uint32* value) override {} | |
| 185 void FuzzInt64(int64* value) override {} | |
| 186 void FuzzUInt64(uint64* value) override {} | |
| 187 void FuzzFloat(float* value) override {} | |
| 188 void FuzzDouble(double* value) override {} | |
| 189 void FuzzString(std::string* value) override {} | |
| 190 void FuzzString16(base::string16* value) override {} | |
| 191 void FuzzData(char* data, int length) override {} | |
| 192 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<Tuple<A>> { | |
| 334 static void Fuzz(Tuple<A>* p, Fuzzer* fuzzer) { | |
| 335 FuzzParam(&get<0>(*p), fuzzer); | |
| 336 } | |
| 337 }; | |
| 338 | |
| 339 template <class A, class B> | |
| 340 struct FuzzTraits<Tuple<A, B>> { | |
| 341 static void Fuzz(Tuple<A, B>* p, Fuzzer* fuzzer) { | |
| 342 FuzzParam(&get<0>(*p), fuzzer); | |
| 343 FuzzParam(&get<1>(*p), fuzzer); | |
| 344 } | |
| 345 }; | |
| 346 | |
| 347 template <class A, class B, class C> | |
| 348 struct FuzzTraits<Tuple<A, B, C>> { | |
| 349 static void Fuzz(Tuple<A, B, C>* p, Fuzzer* fuzzer) { | |
| 350 FuzzParam(&get<0>(*p), fuzzer); | |
| 351 FuzzParam(&get<1>(*p), fuzzer); | |
| 352 FuzzParam(&get<2>(*p), fuzzer); | |
| 353 } | |
| 354 }; | |
| 355 | |
| 356 template <class A, class B, class C, class D> | |
| 357 struct FuzzTraits<Tuple<A, B, C, D>> { | |
| 358 static void Fuzz(Tuple<A, B, C, D>* p, Fuzzer* fuzzer) { | |
| 359 FuzzParam(&get<0>(*p), fuzzer); | |
| 360 FuzzParam(&get<1>(*p), fuzzer); | |
| 361 FuzzParam(&get<2>(*p), fuzzer); | |
| 362 FuzzParam(&get<3>(*p), fuzzer); | |
| 363 } | |
| 364 }; | |
| 365 | |
| 366 template <class A, class B, class C, class D, class E> | |
| 367 struct FuzzTraits<Tuple<A, B, C, D, E>> { | |
| 368 static void Fuzz(Tuple<A, B, C, D, E>* p, Fuzzer* fuzzer) { | |
| 369 FuzzParam(&get<0>(*p), fuzzer); | |
| 370 FuzzParam(&get<1>(*p), fuzzer); | |
| 371 FuzzParam(&get<2>(*p), fuzzer); | |
| 372 FuzzParam(&get<3>(*p), fuzzer); | |
| 373 FuzzParam(&get<4>(*p), 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 types. | |
| 405 #if defined(OS_POSIX) | |
| 406 template <> | |
| 407 struct FuzzTraits<base::FileDescriptor> { | |
| 408 static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) { | |
| 409 FuzzParam(&p->fd, fuzzer); | |
| 410 } | |
| 411 }; | |
| 412 #endif | |
| 413 | |
| 414 template <> | |
| 415 struct FuzzTraits<GURL> { | |
| 416 static void Fuzz(GURL *p, Fuzzer* fuzzer) { | |
| 417 FuzzParam(&p->possibly_invalid_spec(), fuzzer); | |
| 418 } | |
| 419 }; | |
| 420 | |
| 421 template <> | |
| 422 struct FuzzTraits<gfx::Point> { | |
| 423 static void Fuzz(gfx::Point *p, Fuzzer* fuzzer) { | |
| 424 int x = p->x(); | |
| 425 int y = p->y(); | |
| 426 FuzzParam(&x, fuzzer); | |
| 427 FuzzParam(&y, fuzzer); | |
| 428 p->SetPoint(x, y); | |
| 429 } | |
| 430 }; | |
| 431 | |
| 432 template <> | |
| 433 struct FuzzTraits<gfx::Size> { | |
| 434 static void Fuzz(gfx::Size *p, Fuzzer* fuzzer) { | |
| 435 int w = p->width(); | |
| 436 int h = p->height(); | |
| 437 FuzzParam(&w, fuzzer); | |
| 438 FuzzParam(&h, fuzzer); | |
| 439 p->SetSize(w, h); | |
| 440 } | |
| 441 }; | |
| 442 | |
| 443 template <> | |
| 444 struct FuzzTraits<gfx::Rect> { | |
| 445 static void Fuzz(gfx::Rect *p, Fuzzer* fuzzer) { | |
| 446 gfx::Point origin = p->origin(); | |
| 447 gfx::Size size = p->size(); | |
| 448 FuzzParam(&origin, fuzzer); | |
| 449 FuzzParam(&size, fuzzer); | |
| 450 p->set_origin(origin); | |
| 451 p->set_size(size); | |
| 452 } | |
| 453 }; | |
| 454 | |
| 455 // Redefine macros to generate fuzzing from traits declarations. | |
| 456 // Null out all the macros that need nulling. | |
| 457 #include "ipc/ipc_message_null_macros.h" | |
| 458 | |
| 459 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur. | |
| 460 #undef IPC_STRUCT_BEGIN | |
| 461 #undef IPC_STRUCT_BEGIN_WITH_PARENT | |
| 462 #undef IPC_STRUCT_MEMBER | |
| 463 #undef IPC_STRUCT_END | |
| 464 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \ | |
| 465 IPC_STRUCT_BEGIN(struct_name) | |
| 466 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name) | |
| 467 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name) | |
| 468 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END() | |
| 469 | |
| 470 // Set up so next include will generate fuzz trait classes. | |
| 471 #undef IPC_STRUCT_TRAITS_BEGIN | |
| 472 #undef IPC_STRUCT_TRAITS_MEMBER | |
| 473 #undef IPC_STRUCT_TRAITS_PARENT | |
| 474 #undef IPC_STRUCT_TRAITS_END | |
| 475 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \ | |
| 476 template <> \ | |
| 477 struct FuzzTraits<struct_name> { \ | |
| 478 static void Fuzz(struct_name *p, Fuzzer* fuzzer) { | |
| 479 | |
| 480 #define IPC_STRUCT_TRAITS_MEMBER(name) \ | |
| 481 FuzzParam(&p->name, fuzzer); | |
| 482 | |
| 483 #define IPC_STRUCT_TRAITS_PARENT(type) \ | |
| 484 FuzzParam(static_cast<type*>(p), fuzzer); | |
| 485 | |
| 486 #define IPC_STRUCT_TRAITS_END() \ | |
| 487 } \ | |
| 488 }; | |
| 489 | |
| 490 // TODO(tsepez): Make sure to end up with an enum that meets |condition|. | |
| 491 #undef IPC_ENUM_TRAITS_VALIDATE | |
| 492 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, conditon) \ | |
| 493 template <> \ | |
| 494 struct FuzzTraits<enum_name> { \ | |
| 495 static void Fuzz(enum_name* p, Fuzzer* fuzzer) { \ | |
| 496 FuzzParam(reinterpret_cast<int*>(p), fuzzer); \ | |
| 497 } \ | |
| 498 }; | |
| 499 | |
| 500 // Bring them into existence. | |
| 501 #include "tools/ipc_fuzzer/message_lib/all_messages.h" | |
| 502 | |
| 503 // Redefine macros to generate fuzzing funtions | |
| 504 #include "ipc/ipc_message_null_macros.h" | |
| 505 #undef IPC_MESSAGE_DECL | |
| 506 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ | |
| 507 IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist) | |
| 508 | |
| 509 #define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \ | |
| 510 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 511 return NULL; \ | |
| 512 } | |
| 513 | |
| 514 #define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \ | |
| 515 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 516 return NULL; \ | |
| 517 } | |
| 518 | |
| 519 #define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ | |
| 520 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 521 name* real_msg = static_cast<name*>(msg); \ | |
| 522 IPC_TUPLE_IN_##in ilist p; \ | |
| 523 name::Read(real_msg, &p); \ | |
| 524 FuzzParam(&p, fuzzer); \ | |
| 525 return new name(IPC_MEMBERS_IN_##in(p)); \ | |
| 526 } | |
| 527 | |
| 528 #define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ | |
| 529 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 530 name* real_msg = static_cast<name*>(msg); \ | |
| 531 IPC_TUPLE_IN_##in ilist p; \ | |
| 532 name::Read(real_msg, &p); \ | |
| 533 FuzzParam(&p, fuzzer); \ | |
| 534 return new name(msg->routing_id() \ | |
| 535 IPC_COMMA_##in \ | |
| 536 IPC_MEMBERS_IN_##in(p)); \ | |
| 537 } | |
| 538 | |
| 539 #define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ | |
| 540 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 541 name* real_msg = static_cast<name*>(msg); \ | |
| 542 IPC_TUPLE_IN_##in ilist p; \ | |
| 543 name::ReadSendParam(real_msg, &p); \ | |
| 544 FuzzParam(&p, fuzzer); \ | |
| 545 name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \ | |
| 546 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ | |
| 547 IPC_MEMBERS_OUT_##out()); \ | |
| 548 MessageCracker::CopyMessageID(new_msg, real_msg); \ | |
| 549 return new_msg; \ | |
| 550 } | |
| 551 | |
| 552 | |
| 553 #define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ | |
| 554 IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) { \ | |
| 555 name* real_msg = static_cast<name*>(msg); \ | |
| 556 IPC_TUPLE_IN_##in ilist p; \ | |
| 557 name::ReadSendParam(real_msg, &p); \ | |
| 558 FuzzParam(&p, fuzzer); \ | |
| 559 name* new_msg = new name(msg->routing_id() \ | |
| 560 IPC_COMMA_OR_##out(IPC_COMMA_##in) \ | |
| 561 IPC_MEMBERS_IN_##in(p) \ | |
| 562 IPC_COMMA_AND_##out(IPC_COMMA_##in) \ | |
| 563 IPC_MEMBERS_OUT_##out()); \ | |
| 564 MessageCracker::CopyMessageID(new_msg, real_msg); \ | |
| 565 return new_msg; \ | |
| 566 } | |
| 567 | |
| 568 #define IPC_MEMBERS_IN_0(p) | |
| 569 #define IPC_MEMBERS_IN_1(p) get<0>(p) | |
| 570 #define IPC_MEMBERS_IN_2(p) get<0>(p), get<1>(p) | |
| 571 #define IPC_MEMBERS_IN_3(p) get<0>(p), get<1>(p), get<2>(p) | |
| 572 #define IPC_MEMBERS_IN_4(p) get<0>(p), get<1>(p), get<2>(p), get<3>(p) | |
| 573 #define IPC_MEMBERS_IN_5(p) get<0>(p), get<1>(p), get<2>(p), get<3>(p), \ | |
| 574 get<4>(p) | |
| 575 | |
| 576 #define IPC_MEMBERS_OUT_0() | |
| 577 #define IPC_MEMBERS_OUT_1() NULL | |
| 578 #define IPC_MEMBERS_OUT_2() NULL, NULL | |
| 579 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL | |
| 580 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL | |
| 581 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL | |
| 582 | |
| 583 #include "tools/ipc_fuzzer/message_lib/all_messages.h" | |
| 584 | |
| 585 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, Fuzzer*); | |
| 586 typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap; | |
| 587 | |
| 588 // Redefine macros to register fuzzing functions into map. | |
| 589 #include "ipc/ipc_message_null_macros.h" | |
| 590 #undef IPC_MESSAGE_DECL | |
| 591 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ | |
| 592 (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name; | |
| 593 | |
| 594 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) { | |
| 595 #include "tools/ipc_fuzzer/message_lib/all_messages.h" | |
| 596 } | |
| 597 | |
| 598 static IPC::Message* RewriteMessage( | |
| 599 IPC::Message* message, | |
| 600 Fuzzer* fuzzer, | |
| 601 FuzzFunctionMap* map) { | |
| 602 FuzzFunctionMap::iterator it = map->find(message->type()); | |
| 603 if (it == map->end()) { | |
| 604 // This usually indicates a missing message file in all_messages.h, or | |
| 605 // that the message dump file is taken from a different revision of | |
| 606 // chromium from this executable. | |
| 607 std::cerr << "Unknown message type: [" | |
| 608 << IPC_MESSAGE_ID_CLASS(message->type()) << ", " | |
| 609 << IPC_MESSAGE_ID_LINE(message->type()) << "].\n"; | |
| 610 return 0; | |
| 611 } | |
| 612 | |
| 613 return (*it->second)(message, fuzzer); | |
| 614 } | |
| 615 | |
| 616 namespace { | |
| 617 | |
| 618 const char kHelpSwitch[] = "help"; | |
| 619 const char kHelpSwitchHelp[] = | |
| 620 "show this message"; | |
| 621 | |
| 622 const char kFrequencySwitch[] = "frequency"; | |
| 623 const char kFrequencySwitchHelp[] = | |
| 624 "probability of mutation; tweak every 1/|q| times."; | |
| 625 | |
| 626 const char kFuzzerNameSwitch[] = "fuzzer-name"; | |
| 627 const char kFuzzerNameSwitchHelp[] = | |
| 628 "select default or no-op fuzzer."; | |
| 629 | |
| 630 const char kPermuteSwitch[] = "permute"; | |
| 631 const char kPermuteSwitchHelp[] = | |
| 632 "Randomly shuffle the order of all messages."; | |
| 633 | |
| 634 const char kTypeListSwitch[] = "type-list"; | |
| 635 const char kTypeListSwitchHelp[] = | |
| 636 "explicit list of the only message-ids to mutate."; | |
| 637 | |
| 638 void usage() { | |
| 639 std::cerr << "Mutate messages from an exiting message file.\n"; | |
| 640 | |
| 641 std::cerr << "Usage:\n" | |
| 642 << " ipc_fuzzer_mutate" | |
| 643 << " [--" << kHelpSwitch << "]" | |
| 644 << " [--" << kFuzzerNameSwitch << "=f]" | |
| 645 << " [--" << kFrequencySwitch << "=q]" | |
| 646 << " [--" << kTypeListSwitch << "=x,y,z...]" | |
| 647 << " [--" << kPermuteSwitch << "]" | |
| 648 << " infile outfile\n"; | |
| 649 | |
| 650 std::cerr | |
| 651 << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n" | |
| 652 << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n" | |
| 653 << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n" | |
| 654 << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n" | |
| 655 << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n"; | |
| 656 } | |
| 657 | |
| 658 } // namespace | |
| 659 | |
| 660 int MutateMain(int argc, char** argv) { | |
| 661 base::CommandLine::Init(argc, argv); | |
| 662 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); | |
| 663 base::CommandLine::StringVector args = cmd->GetArgs(); | |
| 664 | |
| 665 if (args.size() != 2 || cmd->HasSwitch(kHelpSwitch)) { | |
| 666 usage(); | |
| 667 return EXIT_FAILURE; | |
| 668 } | |
| 669 | |
| 670 base::FilePath::StringType input_file_name = args[0]; | |
| 671 base::FilePath::StringType output_file_name = args[1]; | |
| 672 | |
| 673 bool permute = cmd->HasSwitch(kPermuteSwitch); | |
| 674 | |
| 675 std::string fuzzer_name = "default"; | |
| 676 if (cmd->HasSwitch(kFuzzerNameSwitch)) | |
| 677 fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch); | |
| 678 | |
| 679 int frequency = 23; | |
| 680 if (cmd->HasSwitch(kFrequencySwitch)) | |
| 681 frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str()); | |
| 682 | |
| 683 std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch); | |
| 684 std::vector<std::string> type_string_vector; | |
| 685 base::SplitString(type_string_list, ',', &type_string_vector); | |
| 686 std::set<uint32> type_set; | |
| 687 for (size_t i = 0; i < type_string_vector.size(); ++i) { | |
| 688 type_set.insert(atoi(type_string_vector[i].c_str())); | |
| 689 } | |
| 690 | |
| 691 InitRand(); | |
| 692 | |
| 693 Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency); | |
| 694 if (!fuzzer) | |
| 695 return EXIT_FAILURE; | |
| 696 | |
| 697 FuzzFunctionMap fuzz_function_map; | |
| 698 PopulateFuzzFunctionMap(&fuzz_function_map); | |
| 699 | |
| 700 MessageVector message_vector; | |
| 701 if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector)) | |
| 702 return EXIT_FAILURE; | |
| 703 | |
| 704 for (size_t i = 0; i < message_vector.size(); ++i) { | |
| 705 IPC::Message* msg = message_vector[i]; | |
| 706 if (!type_set.empty() && type_set.end() == std::find( | |
| 707 type_set.begin(), type_set.end(), msg->type())) { | |
| 708 continue; | |
| 709 } | |
| 710 IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map); | |
| 711 if (new_message) { | |
| 712 delete message_vector[i]; | |
| 713 message_vector[i] = new_message; | |
| 714 } | |
| 715 } | |
| 716 | |
| 717 if (permute) { | |
| 718 std::random_shuffle(message_vector.begin(), message_vector.end(), | |
| 719 RandInRange); | |
| 720 } | |
| 721 | |
| 722 if (!MessageFile::Write(base::FilePath(output_file_name), message_vector)) | |
| 723 return EXIT_FAILURE; | |
| 724 | |
| 725 return EXIT_SUCCESS; | |
| 726 } | |
| 727 | |
| 728 } // namespace ipc_fuzzer | |
| 729 | |
| 730 int main(int argc, char** argv) { | |
| 731 return ipc_fuzzer::MutateMain(argc, argv); | |
| 732 } | |
| OLD | NEW |