Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(518)

Side by Side Diff: chrome/tools/ipclist/ipcfuzz.cc

Issue 6711024: Example of how to interpose yourself in a message stream. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <iostream>
7 #include <set>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/hash_tables.h"
12 #include "base/memory/singleton.h"
13 #include "base/message_loop.h"
14 #include "base/process_util.h"
15 #include "base/scoped_ptr.h"
16 #include "base/string_number_conversions.h"
17 #include "base/string_util.h"
18 #include "base/threading/thread.h"
19 #include "base/time.h"
20 #include "base/utf_string_conversions.h"
21 #include "chrome/tools/ipclist/all_messages.h"
22 #include "ipc/ipc_message.h"
23 #include "ipc/ipc_message_utils.h"
24 #include "ipc/ipc_switches.h"
25 #include "ipc/ipc_sync_channel.h"
26 #include "ipc/ipc_sync_message.h"
27
28 #if defined(OS_POSIX)
29 #include <unistd.h>
30 #endif
31
32 namespace IPC {
33 class Message;
34
35 // Interface implemented by those who select messages for fuzzing.
36 class Selector {
37 public:
38 virtual bool FuzzThisMessage(const IPC::Message *msg) = 0;
39 };
40
41 // Interface implemented by those who fuzz basic types. The types all
42 // correspond to the types which a pickle from base/pickle.h can pickle,
43 // plus the floating point types.
44 class Fuzzer {
45 public:
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 FuzzWString(std::wstring* value) = 0;
59 virtual void FuzzString16(string16* value) = 0;
60 virtual void FuzzData(char* data, int length) = 0;
61 virtual void FuzzBytes(void* data, int data_len) = 0;
62 };
63
64 } // Namespace IPC
65
66
67 #define BLEEN 13
68
69 // One such fuzzer implementation.
70 class DefaultFuzzer : public IPC::Fuzzer, public IPC::Selector {
71 public:
72 DefaultFuzzer() {
73 const char *env_var;
74 if ((env_var = getenv("CHROME_IPC_FUZZING_LIST"))) {
75 std::string str = std::string(env_var);
76 size_t pos;
77 while ((pos = str.find_first_of(',')) != std::string::npos) {
78 message_set_.insert(atoi(str.substr(0, pos).c_str()));
79 str = str.substr(pos+1);
80 }
81 message_set_.insert(atoi(str.c_str()));
82 }
83 if ((env_var = getenv("CHROME_IPC_FUZZING_SEED")))
84 srand(atoi(env_var));
85 }
86
87 virtual ~DefaultFuzzer() {}
88
89 // Interface "fuzzer" methods.
90 virtual void FuzzBool(bool* value) {
91 if (rand() % BLEEN == 0)
92 (*value) = !(*value);
93 }
94
95 virtual void FuzzInt(int* value) {
96 if (rand() % BLEEN == 0)
97 (*value) ^= rand();
98 }
99
100 virtual void FuzzLong(long* value) {
101 if (rand() % BLEEN == 0)
102 (*value) ^= rand();
103 }
104
105 virtual void FuzzSize(size_t* value) {
106 if (rand() % BLEEN == 0)
107 (*value) ^= rand();
108 }
109
110 virtual void FuzzUChar(unsigned char* value) {
111 if (rand() % BLEEN == 0)
112 (*value) ^= rand();
113 }
114
115 virtual void FuzzUInt16(uint16* value) {
116 if (rand() % BLEEN == 0)
117 (*value) ^= rand();
118 }
119
120 virtual void FuzzUInt32(uint32* value) {
121 if (rand() % BLEEN == 0)
122 (*value) ^= rand();
123 }
124
125 virtual void FuzzInt64(int64* value) {
126 if (rand() % BLEEN == 0)
127 (*value) ^= rand();
128 }
129
130 virtual void FuzzUInt64(uint64* value) {
131 if (rand() % BLEEN == 0)
132 (*value) ^= rand();
133 }
134
135 virtual void FuzzFloat(float* value) {
136 if (rand() % BLEEN == 0)
137 (*value) *= rand();
138 }
139
140 virtual void FuzzDouble(double* value) {
141 if (rand() % BLEEN == 0)
142 (*value) *= rand();
143 }
144
145 virtual void FuzzString(std::string* value) {
146 if (rand() % BLEEN == 0)
147 (*value) += "BORKED";
148 }
149
150 virtual void FuzzWString(std::wstring* value) {
151 if (rand() % BLEEN == 0)
152 (*value) += L"BORKED";
153 }
154
155 virtual void FuzzString16(string16* value) {
156 if (rand() % BLEEN == 0)
157 (*value) += WideToUTF16(L"BORKED");
158 }
159
160 virtual void FuzzData(char* data, int length) {
161 if (rand() % BLEEN == 0) {
162 for (int i = 0; i < length; ++i) {
163 data[i] ^= rand();
164 }
165 }
166 }
167
168 virtual void FuzzBytes(void* data, int data_len) {
169 FuzzData(static_cast<char*>(data), data_len);
170 }
171
172 // Interface "selector" methods.
173 virtual bool FuzzThisMessage(const IPC::Message *msg) {
174 return (message_set_.empty() ||
175 std::find(message_set_.begin(),
176 message_set_.end(),
177 msg->type()) != message_set_.end());
178 }
179
180 private:
181 std::set<int> message_set_;
182 };
183
184 // Partially-specialized class that knows how to fuzz a given type.
185 template <class P>
186 struct FuzzTraits {
187 static void Fuzz(P* p, IPC::Fuzzer *fuzzer) {}
188 };
189
190 // Template function to invoke partially-specialized class method.
191 template <class P>
192 static void FuzzParam(P* p, IPC::Fuzzer* fuzzer) {
193 FuzzTraits<P>::Fuzz(p, fuzzer);
194 }
195
196 // Specializations to fuzz primitive types.
197 template <>
198 struct FuzzTraits<bool> {
199 static void Fuzz(bool* p, IPC::Fuzzer* fuzzer) {
200 fuzzer->FuzzBool(p);
201 }
202 };
203
204 template <>
205 struct FuzzTraits<int> {
206 static void Fuzz(int* p, IPC::Fuzzer* fuzzer) {
207 fuzzer->FuzzInt(p);
208 }
209 };
210
211 template <>
212 struct FuzzTraits<unsigned int> {
213 static void Fuzz(unsigned int* p, IPC::Fuzzer* fuzzer) {
214 fuzzer->FuzzInt(reinterpret_cast<int*>(p));
215 }
216 };
217
218 template <>
219 struct FuzzTraits<long> {
220 static void Fuzz(long* p, IPC::Fuzzer* fuzzer) {
221 fuzzer->FuzzLong(p);
222 }
223 };
224
225 template <>
226 struct FuzzTraits<unsigned long> {
227 static void Fuzz(unsigned long* p, IPC::Fuzzer* fuzzer) {
228 fuzzer->FuzzLong(reinterpret_cast<long*>(p));
229 }
230 };
231
232 template <>
233 struct FuzzTraits<long long> {
234 static void Fuzz(long long* p, IPC::Fuzzer* fuzzer) {
235 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
236 }
237 };
238
239 template <>
240 struct FuzzTraits<unsigned long long> {
241 static void Fuzz(unsigned long long* p, IPC::Fuzzer* fuzzer) {
242 fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
243 }
244 };
245
246 template <>
247 struct FuzzTraits<short> {
248 static void Fuzz(short* p, IPC::Fuzzer* fuzzer) {
249 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
250 }
251 };
252
253 template <>
254 struct FuzzTraits<unsigned short> {
255 static void Fuzz(unsigned short* p, IPC::Fuzzer* fuzzer) {
256 fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
257 }
258 };
259
260 template <>
261 struct FuzzTraits<char> {
262 static void Fuzz(char* p, IPC::Fuzzer* fuzzer) {
263 fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
264 }
265 };
266
267 template <>
268 struct FuzzTraits<unsigned char> {
269 static void Fuzz(unsigned char* p, IPC::Fuzzer* fuzzer) {
270 fuzzer->FuzzUChar(p);
271 }
272 };
273
274 template <>
275 struct FuzzTraits<float> {
276 static void Fuzz(float* p, IPC::Fuzzer* fuzzer) {
277 fuzzer->FuzzFloat(p);
278 }
279 };
280
281 template <>
282 struct FuzzTraits<double> {
283 static void Fuzz(double* p, IPC::Fuzzer* fuzzer) {
284 fuzzer->FuzzDouble(p);
285 }
286 };
287
288 template <>
289 struct FuzzTraits<std::string> {
290 static void Fuzz(std::string* p, IPC::Fuzzer* fuzzer) {
291 fuzzer->FuzzString(p);
292 }
293 };
294
295 template <>
296 struct FuzzTraits<std::wstring> {
297 static void Fuzz(std::wstring* p, IPC::Fuzzer* fuzzer) {
298 fuzzer->FuzzWString(p);
299 }
300 };
301
302 template <>
303 struct FuzzTraits<string16> {
304 static void Fuzz(string16* p, IPC::Fuzzer* fuzzer) {
305 fuzzer->FuzzString16(p);
306 }
307 };
308
309 // Specializations to fuzz tuples.
310 template <class A>
311 struct FuzzTraits<Tuple1<A> > {
312 static void Fuzz(Tuple1<A>* p, IPC::Fuzzer* fuzzer) {
313 FuzzParam(&p->a, fuzzer);
314 }
315 };
316
317 template <class A, class B>
318 struct FuzzTraits<Tuple2<A, B> > {
319 static void Fuzz(Tuple2<A, B>* p, IPC::Fuzzer* fuzzer) {
320 FuzzParam(&p->a, fuzzer);
321 FuzzParam(&p->b, fuzzer);
322 }
323 };
324
325 template <class A, class B, class C>
326 struct FuzzTraits<Tuple3<A, B, C> > {
327 static void Fuzz(Tuple3<A, B, C>* p, IPC::Fuzzer* fuzzer) {
328 FuzzParam(&p->a, fuzzer);
329 FuzzParam(&p->b, fuzzer);
330 FuzzParam(&p->c, fuzzer);
331 }
332 };
333
334 template <class A, class B, class C, class D>
335 struct FuzzTraits<Tuple4<A, B, C, D> > {
336 static void Fuzz(Tuple4<A, B, C, D>* p, IPC::Fuzzer* fuzzer) {
337 FuzzParam(&p->a, fuzzer);
338 FuzzParam(&p->b, fuzzer);
339 FuzzParam(&p->c, fuzzer);
340 FuzzParam(&p->d, fuzzer);
341 }
342 };
343
344 template <class A, class B, class C, class D, class E>
345 struct FuzzTraits<Tuple5<A, B, C, D, E> > {
346 static void Fuzz(Tuple5<A, B, C, D, E>* p, IPC::Fuzzer* fuzzer) {
347 FuzzParam(&p->a, fuzzer);
348 FuzzParam(&p->b, fuzzer);
349 FuzzParam(&p->c, fuzzer);
350 FuzzParam(&p->d, fuzzer);
351 FuzzParam(&p->e, fuzzer);
352 }
353 };
354
355 // Specializations to fuzz containers.
356 template <class A>
357 struct FuzzTraits<std::vector<A> > {
358 static void Fuzz(std::vector<A>* p, IPC::Fuzzer* fuzzer) {
359 for (size_t i = 0; i < p->size(); ++i) {
360 FuzzParam(&p->at(i), fuzzer);
361 }
362 }
363 };
364
365 template <class A, class B>
366 struct FuzzTraits<std::map<A, B> > {
367 static void Fuzz(std::map<A, B>* p, IPC::Fuzzer* fuzzer) {
368 typename std::map<A, B>::iterator it;
369 for (it = p->begin(); it != p->end(); ++it) {
370 FuzzParam(&it->second, fuzzer);
371 }
372 }
373 };
374
375 template <class A, class B>
376 struct FuzzTraits<std::pair<A, B> > {
377 static void Fuzz(std::pair<A, B>* p, IPC::Fuzzer* fuzzer) {
378 FuzzParam(&p->second, fuzzer);
379 }
380 };
381
382 // Specializations to fuzz hand-coded tyoes
383 template <>
384 struct FuzzTraits<base::FileDescriptor> {
385 static void Fuzz(base::FileDescriptor* p, IPC::Fuzzer* fuzzer) {
386 FuzzParam(&p->fd, fuzzer);
387 }
388 };
389
390 template <>
391 struct FuzzTraits<GURL> {
392 static void Fuzz(GURL *p, IPC::Fuzzer* fuzzer) {
393 FuzzParam(&p->possibly_invalid_spec(), fuzzer);
394 }
395 };
396
397 template <>
398 struct FuzzTraits<gfx::Point> {
399 static void Fuzz(gfx::Point *p, IPC::Fuzzer* fuzzer) {
400 int x = p->x();
401 int y = p->y();
402 FuzzParam(&x, fuzzer);
403 FuzzParam(&y, fuzzer);
404 p->SetPoint(x, y);
405 }
406 };
407
408 template <>
409 struct FuzzTraits<gfx::Size> {
410 static void Fuzz(gfx::Size *p, IPC::Fuzzer* fuzzer) {
411 int w = p->width();
412 int h = p->height();
413 FuzzParam(&w, fuzzer);
414 FuzzParam(&h, fuzzer);
415 p->SetSize(w, h);
416 }
417 };
418
419 template <>
420 struct FuzzTraits<gfx::Rect> {
421 static void Fuzz(gfx::Rect *p, IPC::Fuzzer* fuzzer) {
422 gfx::Point origin = p->origin();
423 gfx::Size size = p->size();
424 FuzzParam(&origin, fuzzer);
425 FuzzParam(&size, fuzzer);
426 p->set_origin(origin);
427 p->set_size(size);
428 }
429 };
430
431 // Redefine macros to generate fuzzing from traits declarations.
432 // Null out all the macros that need nulling.
433 #include "ipc/ipc_message_null_macros.h"
434
435 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
436 #undef IPC_STRUCT_BEGIN
437 #undef IPC_STRUCT_MEMBER
438 #undef IPC_STRUCT_END
439 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
440 #define IPC_STRUCT_MEMBER(type, name) IPC_STRUCT_TRAITS_MEMBER(name)
441 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
442
443 // Set up so next include will generate fuzz trait classes.
444 #undef IPC_STRUCT_TRAITS_BEGIN
445 #undef IPC_STRUCT_TRAITS_MEMBER
446 #undef IPC_STRUCT_TRAITS_PARENT
447 #undef IPC_STRUCT_TRAITS_END
448 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
449 template <> \
450 struct FuzzTraits<struct_name> { \
451 static void Fuzz(struct_name *p, IPC::Fuzzer* fuzzer) { \
452
453 #define IPC_STRUCT_TRAITS_MEMBER(name) \
454 FuzzParam(&p->name, fuzzer);
455
456 #define IPC_STRUCT_TRAITS_PARENT(type) \
457 FuzzParam(static_cast<type*>(p), fuzzer);
458
459 #define IPC_STRUCT_TRAITS_END() \
460 } \
461 };
462
463 #undef IPC_ENUM_TRAITS
464 #define IPC_ENUM_TRAITS(enum_name) \
465 template <> \
466 struct FuzzTraits<enum_name> { \
467 static void Fuzz(enum_name* p, IPC::Fuzzer* fuzzer) { \
468 FuzzParam(reinterpret_cast<int*>(p), fuzzer); \
469 } \
470 };
471
472 // Bring them into existence.
473 #include "chrome/tools/ipclist/all_messages.h"
474
475 // Redefine macros to generate fuzzing funtions
476 #include "ipc/ipc_message_null_macros.h"
477 #undef IPC_MESSAGE_DECL
478 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
479 IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist)
480
481 #define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \
482 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
483 return NULL; \
484 }
485
486 #define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \
487 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
488 return NULL; \
489 }
490
491 #define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \
492 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
493 name* real_msg = static_cast<name*>(msg); \
494 IPC_TUPLE_IN_##in ilist p; \
495 name::Read(real_msg, &p); \
496 FuzzParam(&p, fuzzer); \
497 return new name(IPC_MEMBERS_IN_##in(p)); \
498 }
499
500 #define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \
501 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
502 name* real_msg = static_cast<name*>(msg); \
503 IPC_TUPLE_IN_##in ilist p; \
504 name::Read(real_msg, &p); \
505 FuzzParam(&p, fuzzer); \
506 return new name(msg->routing_id() \
507 IPC_COMMA_##in \
508 IPC_MEMBERS_IN_##in(p)); \
509 }
510
511 #define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \
512 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
513 name* real_msg = static_cast<name*>(msg); \
514 IPC_TUPLE_IN_##in ilist p; \
515 name::ReadSendParam(real_msg, &p); \
516 FuzzParam(&p, fuzzer); \
517 IPC_TUPLE_OUT_##out olist q = \
518 static_cast<IPC::ParamDeserializer<IPC_TUPLE_OUT_##out olist>*>( \
519 real_msg->GetReplyDeserializer())->out_; \
520 name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \
521 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
522 IPC_MEMBERS_OUT_##out(q)); \
523 return new_msg; \
524 }
525
526
527 #define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \
528 IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \
529 name* real_msg = static_cast<name*>(msg); \
530 IPC_TUPLE_IN_##in ilist p; \
531 name::ReadSendParam(real_msg, &p); \
532 FuzzParam(&p, fuzzer); \
533 IPC_TUPLE_OUT_##out olist q = \
534 static_cast<IPC::ParamDeserializer<IPC_TUPLE_OUT_##out olist>*>( \
535 real_msg->GetReplyDeserializer())->out_; \
536 name* new_msg = new name(msg->routing_id() \
537 IPC_COMMA_OR_##out(IPC_COMMA_##in) \
538 IPC_MEMBERS_IN_##in(p) \
539 IPC_COMMA_AND_##out(IPC_COMMA_##in) \
540 IPC_MEMBERS_OUT_##out(q)); \
541 return new_msg; \
542 }
543
544 #define IPC_MEMBERS_IN_0(p)
545 #define IPC_MEMBERS_IN_1(p) p.a
546 #define IPC_MEMBERS_IN_2(p) p.a, p.b
547 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
548 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
549 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e
550
551 #define IPC_MEMBERS_OUT_0(q)
552 #define IPC_MEMBERS_OUT_1(q) &q.a
553 #define IPC_MEMBERS_OUT_2(q) &q.a, &q.b
554 #define IPC_MEMBERS_OUT_3(q) &q.a, &q.b, &q.c
555 #define IPC_MEMBERS_OUT_4(q) &q.a, &q.b, &q.c, &q.d
556 #define IPC_MEMBERS_OUT_5(q) &q.a, &q.b, &q.c, &q.d, &q.e
557
558 #include "chrome/tools/ipclist/all_messages.h"
559
560 typedef IPC::Message* (*FuzzFunction)(IPC::Message*, IPC::Fuzzer*);
561 typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap;
562
563 // Redefine macros to register fuzzing functions into map.
564 #include "ipc/ipc_message_null_macros.h"
565 #undef IPC_MESSAGE_DECL
566 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
567 (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name;
568
569 void PopulateFuzzFunctionMap(FuzzFunctionMap *map) {
570 #include "chrome/tools/ipclist/all_messages.h"
571 }
572
573 class ipcfuzz : public IPC::SyncChannel::OutgoingMessageFilter {
574 public:
575 ipcfuzz() : fuzzer_(NULL), selector_(NULL) {
576 PopulateFuzzFunctionMap(&fuzz_function_map_);
577 DefaultFuzzer *fuzzer = new DefaultFuzzer();
578 fuzzer_ = fuzzer;
579 selector_ = fuzzer;
580 }
581
582 IPC::Message* Rewrite(IPC::Message* message) {
583 if (fuzzer_ && selector_ && selector_->FuzzThisMessage(message)) {
584 FuzzFunctionMap::iterator it = fuzz_function_map_.find(message->type());
585 if (it != fuzz_function_map_.end()) {
586 IPC::Message* fuzzed_message = (*it->second)(message, fuzzer_);
587 if (fuzzed_message) {
588 delete message;
589 message = fuzzed_message;
590 }
591 }
592 }
593 return message;
594 }
595
596 private:
597 IPC::Fuzzer* fuzzer_;
598 IPC::Selector* selector_;
599 FuzzFunctionMap fuzz_function_map_;
600 };
601
602 ipcfuzz g_ipcfuzz;
603
604 // Entry point avoiding mangled names.
605 extern "C" {
606 __attribute__ ((visibility("default")))
607 IPC::SyncChannel::OutgoingMessageFilter* GetFilter(void);
608 }
609
610 IPC::SyncChannel::OutgoingMessageFilter* GetFilter(void) {
611 return &g_ipcfuzz;
612 }
613
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698