Chromium Code Reviews| Index: chrome/tools/ipclist/ipcfuzz.cc |
| =================================================================== |
| --- chrome/tools/ipclist/ipcfuzz.cc (revision 0) |
| +++ chrome/tools/ipclist/ipcfuzz.cc (revision 0) |
| @@ -0,0 +1,688 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <algorithm> |
| +#include <iostream> |
| +#include <set> |
| +#include <vector> |
| + |
| +#include "base/command_line.h" |
| +#include "base/hash_tables.h" |
| +#include "base/memory/singleton.h" |
| +#include "base/message_loop.h" |
| +#include "base/pickle.h" |
| +#include "base/process_util.h" |
| +#include "base/scoped_ptr.h" |
| +#include "base/string_number_conversions.h" |
| +#include "base/string_util.h" |
| +#include "base/threading/thread.h" |
| +#include "base/time.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "chrome/tools/ipclist/all_messages.h" |
| +#include "ipc/ipc_message.h" |
| +#include "ipc/ipc_message_utils.h" |
| +#include "ipc/ipc_switches.h" |
| +#include "ipc/ipc_sync_channel.h" |
| +#include "ipc/ipc_sync_message.h" |
| + |
| +#if defined(OS_POSIX) |
| +#include <unistd.h> |
| +#endif |
| + |
| +namespace IPC { |
| +class Message; |
| + |
| +// Interface implemented by those who fuzz basic types. The types all |
| +// correspond to the types which a pickle from base/pickle.h can pickle, |
| +// plus the floating point types. |
| +class Fuzzer { |
| + public: |
| + // Select a message for fuzzing. |
| + virtual bool FuzzThisMessage(const IPC::Message *msg) = 0; |
| + |
| + // Tweak individual values within a message. |
| + virtual void FuzzBool(bool* value) = 0; |
| + virtual void FuzzInt(int* value) = 0; |
| + virtual void FuzzLong(long* value) = 0; |
| + virtual void FuzzSize(size_t* value) = 0; |
| + virtual void FuzzUChar(unsigned char *value) = 0; |
| + virtual void FuzzUInt16(uint16* value) = 0; |
| + virtual void FuzzUInt32(uint32* value) = 0; |
| + virtual void FuzzInt64(int64* value) = 0; |
| + virtual void FuzzUInt64(uint64* value) = 0; |
| + virtual void FuzzFloat(float *value) = 0; |
| + virtual void FuzzDouble(double *value) = 0; |
| + virtual void FuzzString(std::string* value) = 0; |
| + virtual void FuzzWString(std::wstring* value) = 0; |
| + virtual void FuzzString16(string16* value) = 0; |
| + virtual void FuzzData(char* data, int length) = 0; |
| + virtual void FuzzBytes(void* data, int data_len) = 0; |
| +}; |
| + |
| +} // Namespace IPC |
| + |
| +namespace { |
| + |
| +template <typename T> |
| +void FuzzIntegralType(T* value, unsigned int frequency) { |
| + if (rand() % frequency == 0) { |
| + switch (rand() % 4) { |
| + case 0: (*value) = 0; break; |
| + case 1: (*value)--; break; |
| + case 2: (*value)++; break; |
| + case 3: (*value) ^= rand(); break; |
| + } |
| + } |
| +} |
| + |
| +template <typename T> |
| +void FuzzStringType(T* value, unsigned int frequency, |
| + const T& literal1, const T& literal2) { |
| + if (rand() % frequency == 0) { |
| + switch (rand() % 5) { |
| + case 4: (*value) = (*value) + (*value); // FALLTHROUGH |
| + case 3: (*value) = (*value) + (*value); // FALLTHROUGH |
| + case 2: (*value) = (*value) + (*value); break; |
| + case 1: (*value) += literal1; break; |
| + case 0: (*value) = literal2; break; |
| + } |
| + } |
| +} |
| + |
| +} // Namespace |
| + |
| +// One such fuzzer implementation. |
| +class DefaultFuzzer : public IPC::Fuzzer { |
| + public: |
| + static const int DEFAULT_FREQUENCY = 23; |
| + |
| + DefaultFuzzer() : frequency_(DEFAULT_FREQUENCY) { |
| + const char *env_var; |
| + if ((env_var = getenv("CHROME_IPC_FUZZING_LIST"))) { |
| + std::string str = std::string(env_var); |
| + size_t pos; |
| + while ((pos = str.find_first_of(',')) != std::string::npos) { |
| + message_set_.insert(atoi(str.substr(0, pos).c_str())); |
| + str = str.substr(pos+1); |
| + } |
| + message_set_.insert(atoi(str.c_str())); |
| + } |
| + |
| + if ((env_var = getenv("CHROME_IPC_FUZZING_SEED"))) { |
| + int new_seed = atoi(env_var); |
| + if (new_seed) |
| + srand(new_seed); |
| + } |
| + |
| + if ((env_var = getenv("CHROME_IPC_FUZZING_FREQUENCY"))) |
| + { |
| + unsigned int new_frequency = atoi(env_var); |
| + if (new_frequency) |
| + frequency_ = new_frequency; |
| + } |
| + } |
| + |
| + virtual ~DefaultFuzzer() {} |
| + |
| + virtual bool FuzzThisMessage(const IPC::Message *msg) { |
| + return (message_set_.empty() || |
| + std::find(message_set_.begin(), |
| + message_set_.end(), |
| + msg->type()) != message_set_.end()); |
| + } |
| + |
| + virtual void FuzzBool(bool* value) { |
| + if (rand() % frequency_ == 0) |
| + (*value) = !(*value); |
| + } |
| + |
| + virtual void FuzzInt(int* value) { |
| + FuzzIntegralType<int>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzLong(long* value) { |
| + FuzzIntegralType<long>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzSize(size_t* value) { |
| + FuzzIntegralType<size_t>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzUChar(unsigned char* value) { |
| + FuzzIntegralType<unsigned char>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzUInt16(uint16* value) { |
| + FuzzIntegralType<uint16>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzUInt32(uint32* value) { |
| + FuzzIntegralType<uint32>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzInt64(int64* value) { |
| + FuzzIntegralType<int64>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzUInt64(uint64* value) { |
| + FuzzIntegralType<uint64>(value, frequency_); |
| + } |
| + |
| + virtual void FuzzFloat(float* value) { |
| + if (rand() % frequency_ == 0) |
| + (*value) *= rand() / 1000000.0; |
| + } |
| + |
| + virtual void FuzzDouble(double* value) { |
| + if (rand() % frequency_ == 0) |
| + (*value) *= rand() / 1000000.0; |
| + } |
| + |
| + virtual void FuzzString(std::string* value) { |
| + FuzzStringType<std::string>(value, frequency_, "BORKED", ""); |
| + } |
| + |
| + virtual void FuzzWString(std::wstring* value) { |
| + FuzzStringType<std::wstring>(value, frequency_, L"BORKED", L""); |
| + } |
| + |
| + virtual void FuzzString16(string16* value) { |
| + FuzzStringType<string16>(value, frequency_, |
| + WideToUTF16(L"BORKED"), |
| + WideToUTF16(L"")); |
| + } |
| + |
| + virtual void FuzzData(char* data, int length) { |
| + if (rand() % frequency_ == 0) { |
| + for (int i = 0; i < length; ++i) { |
| + FuzzIntegralType<char>(&data[i], frequency_); |
| + } |
| + } |
| + } |
| + |
| + virtual void FuzzBytes(void* data, int data_len) { |
| + FuzzData(static_cast<char*>(data), data_len); |
| + } |
| + |
| + private: |
| + std::set<int> message_set_; |
| + unsigned int frequency_; |
| +}; |
| + |
| + |
| +// No-op fuzzer. Rewrites each message unchaged to check if the message |
|
jam
2011/05/03 06:39:26
nit: unchanged
|
| +// re-assembly is legit. |
| +class NoOpFuzzer : public IPC::Fuzzer { |
| + public: |
| + NoOpFuzzer() {} |
| + virtual ~NoOpFuzzer() {} |
| + |
| + virtual bool FuzzThisMessage(const IPC::Message *msg) { |
| + return true; |
| + } |
| + |
| + virtual void FuzzBool(bool* value) {} |
| + virtual void FuzzInt(int* value) {} |
| + virtual void FuzzLong(long* value) {} |
| + virtual void FuzzSize(size_t* value) {} |
| + virtual void FuzzUChar(unsigned char* value) {} |
| + virtual void FuzzUInt16(uint16* value) {} |
| + virtual void FuzzUInt32(uint32* value) {} |
| + virtual void FuzzInt64(int64* value) {} |
| + virtual void FuzzUInt64(uint64* value) {} |
| + virtual void FuzzFloat(float* value) {} |
| + virtual void FuzzDouble(double* value) {} |
| + virtual void FuzzString(std::string* value) {} |
| + virtual void FuzzWString(std::wstring* value) {} |
| + virtual void FuzzString16(string16* value) {} |
| + virtual void FuzzData(char* data, int length) {} |
| + virtual void FuzzBytes(void* data, int data_len) {} |
| +}; |
| + |
| +class FuzzerFactory { |
| + public: |
| + static IPC::Fuzzer *NewFuzzer(const std::string& name) { |
| + if (name == "no-op") |
| + return new NoOpFuzzer(); |
| + else |
| + return new DefaultFuzzer(); |
| + } |
| +}; |
| + |
| +// Partially-specialized class that knows how to fuzz a given type. |
| +template <class P> |
| +struct FuzzTraits { |
| + static void Fuzz(P* p, IPC::Fuzzer *fuzzer) {} |
| +}; |
| + |
| +// Template function to invoke partially-specialized class method. |
| +template <class P> |
| +static void FuzzParam(P* p, IPC::Fuzzer* fuzzer) { |
| + FuzzTraits<P>::Fuzz(p, fuzzer); |
| +} |
| + |
| +// Specializations to fuzz primitive types. |
| +template <> |
| +struct FuzzTraits<bool> { |
| + static void Fuzz(bool* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzBool(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<int> { |
| + static void Fuzz(int* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzInt(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<unsigned int> { |
| + static void Fuzz(unsigned int* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzInt(reinterpret_cast<int*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<long> { |
| + static void Fuzz(long* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzLong(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<unsigned long> { |
| + static void Fuzz(unsigned long* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzLong(reinterpret_cast<long*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<long long> { |
| + static void Fuzz(long long* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<unsigned long long> { |
| + static void Fuzz(unsigned long long* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzInt64(reinterpret_cast<int64*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<short> { |
| + static void Fuzz(short* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<unsigned short> { |
| + static void Fuzz(unsigned short* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<char> { |
| + static void Fuzz(char* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p)); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<unsigned char> { |
| + static void Fuzz(unsigned char* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzUChar(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<float> { |
| + static void Fuzz(float* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzFloat(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<double> { |
| + static void Fuzz(double* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzDouble(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<std::string> { |
| + static void Fuzz(std::string* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzString(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<std::wstring> { |
| + static void Fuzz(std::wstring* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzWString(p); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<string16> { |
| + static void Fuzz(string16* p, IPC::Fuzzer* fuzzer) { |
| + fuzzer->FuzzString16(p); |
| + } |
| +}; |
| + |
| +// Specializations to fuzz tuples. |
| +template <class A> |
| +struct FuzzTraits<Tuple1<A> > { |
| + static void Fuzz(Tuple1<A>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->a, fuzzer); |
| + } |
| +}; |
| + |
| +template <class A, class B> |
| +struct FuzzTraits<Tuple2<A, B> > { |
| + static void Fuzz(Tuple2<A, B>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->a, fuzzer); |
| + FuzzParam(&p->b, fuzzer); |
| + } |
| +}; |
| + |
| +template <class A, class B, class C> |
| +struct FuzzTraits<Tuple3<A, B, C> > { |
| + static void Fuzz(Tuple3<A, B, C>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->a, fuzzer); |
| + FuzzParam(&p->b, fuzzer); |
| + FuzzParam(&p->c, fuzzer); |
| + } |
| +}; |
| + |
| +template <class A, class B, class C, class D> |
| +struct FuzzTraits<Tuple4<A, B, C, D> > { |
| + static void Fuzz(Tuple4<A, B, C, D>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->a, fuzzer); |
| + FuzzParam(&p->b, fuzzer); |
| + FuzzParam(&p->c, fuzzer); |
| + FuzzParam(&p->d, fuzzer); |
| + } |
| +}; |
| + |
| +template <class A, class B, class C, class D, class E> |
| +struct FuzzTraits<Tuple5<A, B, C, D, E> > { |
| + static void Fuzz(Tuple5<A, B, C, D, E>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->a, fuzzer); |
| + FuzzParam(&p->b, fuzzer); |
| + FuzzParam(&p->c, fuzzer); |
| + FuzzParam(&p->d, fuzzer); |
| + FuzzParam(&p->e, fuzzer); |
| + } |
| +}; |
| + |
| +// Specializations to fuzz containers. |
| +template <class A> |
| +struct FuzzTraits<std::vector<A> > { |
| + static void Fuzz(std::vector<A>* p, IPC::Fuzzer* fuzzer) { |
| + for (size_t i = 0; i < p->size(); ++i) { |
| + FuzzParam(&p->at(i), fuzzer); |
| + } |
| + } |
| +}; |
| + |
| +template <class A, class B> |
| +struct FuzzTraits<std::map<A, B> > { |
| + static void Fuzz(std::map<A, B>* p, IPC::Fuzzer* fuzzer) { |
| + typename std::map<A, B>::iterator it; |
| + for (it = p->begin(); it != p->end(); ++it) { |
| + FuzzParam(&it->second, fuzzer); |
| + } |
| + } |
| +}; |
| + |
| +template <class A, class B> |
| +struct FuzzTraits<std::pair<A, B> > { |
| + static void Fuzz(std::pair<A, B>* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->second, fuzzer); |
| + } |
| +}; |
| + |
| +// Specializations to fuzz hand-coded tyoes |
| +template <> |
| +struct FuzzTraits<base::FileDescriptor> { |
| + static void Fuzz(base::FileDescriptor* p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->fd, fuzzer); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<GURL> { |
| + static void Fuzz(GURL *p, IPC::Fuzzer* fuzzer) { |
| + FuzzParam(&p->possibly_invalid_spec(), fuzzer); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<gfx::Point> { |
| + static void Fuzz(gfx::Point *p, IPC::Fuzzer* fuzzer) { |
| + int x = p->x(); |
| + int y = p->y(); |
| + FuzzParam(&x, fuzzer); |
| + FuzzParam(&y, fuzzer); |
| + p->SetPoint(x, y); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<gfx::Size> { |
| + static void Fuzz(gfx::Size *p, IPC::Fuzzer* fuzzer) { |
| + int w = p->width(); |
| + int h = p->height(); |
| + FuzzParam(&w, fuzzer); |
| + FuzzParam(&h, fuzzer); |
| + p->SetSize(w, h); |
| + } |
| +}; |
| + |
| +template <> |
| +struct FuzzTraits<gfx::Rect> { |
| + static void Fuzz(gfx::Rect *p, IPC::Fuzzer* fuzzer) { |
| + gfx::Point origin = p->origin(); |
| + gfx::Size size = p->size(); |
| + FuzzParam(&origin, fuzzer); |
| + FuzzParam(&size, fuzzer); |
| + p->set_origin(origin); |
| + p->set_size(size); |
| + } |
| +}; |
| + |
| +// Means for updating message id in pickles. |
| +class PickleCracker : public Pickle { |
| + public: |
| + static void CopyMessageID(PickleCracker *dst, PickleCracker *src) { |
| + memcpy(dst->payload(), src->payload(), sizeof(int)); |
| + } |
| +}; |
| + |
| +// Redefine macros to generate fuzzing from traits declarations. |
| +// Null out all the macros that need nulling. |
| +#include "ipc/ipc_message_null_macros.h" |
| + |
| +// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur. |
| +#undef IPC_STRUCT_BEGIN |
| +#undef IPC_STRUCT_MEMBER |
| +#undef IPC_STRUCT_END |
| +#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name) |
| +#define IPC_STRUCT_MEMBER(type, name) IPC_STRUCT_TRAITS_MEMBER(name) |
| +#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END() |
| + |
| +// Set up so next include will generate fuzz trait classes. |
| +#undef IPC_STRUCT_TRAITS_BEGIN |
| +#undef IPC_STRUCT_TRAITS_MEMBER |
| +#undef IPC_STRUCT_TRAITS_PARENT |
| +#undef IPC_STRUCT_TRAITS_END |
| +#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \ |
| + template <> \ |
| + struct FuzzTraits<struct_name> { \ |
| + static void Fuzz(struct_name *p, IPC::Fuzzer* fuzzer) { \ |
| + |
| +#define IPC_STRUCT_TRAITS_MEMBER(name) \ |
| + FuzzParam(&p->name, fuzzer); |
| + |
| +#define IPC_STRUCT_TRAITS_PARENT(type) \ |
| + FuzzParam(static_cast<type*>(p), fuzzer); |
| + |
| +#define IPC_STRUCT_TRAITS_END() \ |
| + } \ |
| + }; |
| + |
| +#undef IPC_ENUM_TRAITS |
| +#define IPC_ENUM_TRAITS(enum_name) \ |
| + template <> \ |
| + struct FuzzTraits<enum_name> { \ |
| + static void Fuzz(enum_name* p, IPC::Fuzzer* fuzzer) { \ |
| + FuzzParam(reinterpret_cast<int*>(p), fuzzer); \ |
| + } \ |
| + }; |
| + |
| +// Bring them into existence. |
| +#include "chrome/tools/ipclist/all_messages.h" |
| + |
| +// Redefine macros to generate fuzzing funtions |
| +#include "ipc/ipc_message_null_macros.h" |
| +#undef IPC_MESSAGE_DECL |
| +#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ |
| + IPC_##kind##_##type##_FUZZ(name, in, out, ilist, olist) |
| + |
| +#define IPC_EMPTY_CONTROL_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + return NULL; \ |
| + } |
| + |
| +#define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + return NULL; \ |
| + } |
| + |
| +#define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + name* real_msg = static_cast<name*>(msg); \ |
| + IPC_TUPLE_IN_##in ilist p; \ |
| + name::Read(real_msg, &p); \ |
| + FuzzParam(&p, fuzzer); \ |
| + return new name(IPC_MEMBERS_IN_##in(p)); \ |
| + } |
| + |
| +#define IPC_ASYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + name* real_msg = static_cast<name*>(msg); \ |
| + IPC_TUPLE_IN_##in ilist p; \ |
| + name::Read(real_msg, &p); \ |
| + FuzzParam(&p, fuzzer); \ |
| + return new name(msg->routing_id() \ |
| + IPC_COMMA_##in \ |
| + IPC_MEMBERS_IN_##in(p)); \ |
| + } |
| + |
| +#define IPC_SYNC_CONTROL_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + name* real_msg = static_cast<name*>(msg); \ |
| + IPC_TUPLE_IN_##in ilist p; \ |
| + name::ReadSendParam(real_msg, &p); \ |
| + FuzzParam(&p, fuzzer); \ |
| + name* new_msg = new name(IPC_MEMBERS_IN_##in(p) \ |
| + IPC_COMMA_AND_##out(IPC_COMMA_##in) \ |
| + IPC_MEMBERS_OUT_##out()); \ |
| + PickleCracker::CopyMessageID( \ |
| + reinterpret_cast<PickleCracker *>(new_msg), \ |
| + reinterpret_cast<PickleCracker *>(real_msg)); \ |
| + return new_msg; \ |
| + } |
| + |
| + |
| +#define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist) \ |
| + IPC::Message* fuzzer_for_##name(IPC::Message *msg, IPC::Fuzzer* fuzzer) { \ |
| + name* real_msg = static_cast<name*>(msg); \ |
| + IPC_TUPLE_IN_##in ilist p; \ |
| + name::ReadSendParam(real_msg, &p); \ |
| + FuzzParam(&p, fuzzer); \ |
| + name* new_msg = new name(msg->routing_id() \ |
| + IPC_COMMA_OR_##out(IPC_COMMA_##in) \ |
| + IPC_MEMBERS_IN_##in(p) \ |
| + IPC_COMMA_AND_##out(IPC_COMMA_##in) \ |
| + IPC_MEMBERS_OUT_##out()); \ |
| + PickleCracker::CopyMessageID( \ |
| + reinterpret_cast<PickleCracker *>(new_msg), \ |
| + reinterpret_cast<PickleCracker *>(real_msg)); \ |
| + return new_msg; \ |
| + } |
| + |
| +#define IPC_MEMBERS_IN_0(p) |
| +#define IPC_MEMBERS_IN_1(p) p.a |
| +#define IPC_MEMBERS_IN_2(p) p.a, p.b |
| +#define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c |
| +#define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d |
| +#define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e |
| + |
| +#define IPC_MEMBERS_OUT_0() |
| +#define IPC_MEMBERS_OUT_1() NULL |
| +#define IPC_MEMBERS_OUT_2() NULL, NULL |
| +#define IPC_MEMBERS_OUT_3() NULL, NULL, NULL |
| +#define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL |
| +#define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL |
| + |
| +#include "chrome/tools/ipclist/all_messages.h" |
| + |
| +typedef IPC::Message* (*FuzzFunction)(IPC::Message*, IPC::Fuzzer*); |
| +typedef base::hash_map<uint32, FuzzFunction> FuzzFunctionMap; |
| + |
| +// Redefine macros to register fuzzing functions into map. |
| +#include "ipc/ipc_message_null_macros.h" |
| +#undef IPC_MESSAGE_DECL |
| +#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \ |
| + (*map)[static_cast<uint32>(name::ID)] = fuzzer_for_##name; |
| + |
| +void PopulateFuzzFunctionMap(FuzzFunctionMap *map) { |
| +#include "chrome/tools/ipclist/all_messages.h" |
| +} |
| + |
| +class ipcfuzz : public IPC::ChannelProxy::OutgoingMessageFilter { |
| + public: |
| + ipcfuzz() { |
| + const char* env_var = getenv("CHROME_IPC_FUZZING_KIND"); |
| + fuzzer_ = FuzzerFactory::NewFuzzer(env_var ? env_var : ""); |
| + PopulateFuzzFunctionMap(&fuzz_function_map_); |
| + } |
| + |
| + IPC::Message* Rewrite(IPC::Message* message) { |
| + if (fuzzer_ && fuzzer_->FuzzThisMessage(message)) { |
| + FuzzFunctionMap::iterator it = fuzz_function_map_.find(message->type()); |
| + if (it != fuzz_function_map_.end()) { |
| + IPC::Message* fuzzed_message = (*it->second)(message, fuzzer_); |
| + if (fuzzed_message) { |
| + delete message; |
| + message = fuzzed_message; |
| + } |
| + } |
| + } |
| + return message; |
| + } |
| + |
| + private: |
| + IPC::Fuzzer* fuzzer_; |
| + FuzzFunctionMap fuzz_function_map_; |
| +}; |
| + |
| +ipcfuzz g_ipcfuzz; |
| + |
| +// Entry point avoiding mangled names. |
| +extern "C" { |
| + __attribute__((visibility("default"))) |
| + IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void); |
| +} |
| + |
| +IPC::ChannelProxy::OutgoingMessageFilter* GetFilter(void) { |
| + return &g_ipcfuzz; |
| +} |
| + |
| Property changes on: chrome/tools/ipclist/ipcfuzz.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |