root/tools/ipc_fuzzer/mutate/mutate.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FuzzIntegralType
  2. FuzzStringType
  3. FuzzBool
  4. FuzzInt
  5. FuzzLong
  6. FuzzSize
  7. FuzzUChar
  8. FuzzUInt16
  9. FuzzUInt32
  10. FuzzInt64
  11. FuzzUInt64
  12. FuzzFloat
  13. FuzzDouble
  14. FuzzString
  15. FuzzString16
  16. FuzzData
  17. FuzzBytes
  18. FuzzBool
  19. FuzzInt
  20. FuzzLong
  21. FuzzSize
  22. FuzzUChar
  23. FuzzUInt16
  24. FuzzUInt32
  25. FuzzInt64
  26. FuzzUInt64
  27. FuzzFloat
  28. FuzzDouble
  29. FuzzString
  30. FuzzString16
  31. FuzzData
  32. FuzzBytes
  33. Create
  34. FuzzParam
  35. PopulateFuzzFunctionMap
  36. RewriteMessage
  37. usage
  38. MutateMain
  39. main

// Copyright 2013 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 <stdlib.h>

#include <algorithm>
#include <iostream>
#include <ostream>
#include <set>
#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/pickle.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.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"
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "tools/ipc_fuzzer/message_lib/message_cracker.h"
#include "tools/ipc_fuzzer/message_lib/message_file.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"

#if defined(OS_POSIX)
#include <unistd.h>
#endif

namespace IPC {
class Message;
}  // namespace IPC

namespace ipc_fuzzer {

// 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:
  // 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 FuzzString16(base::string16* value) = 0;
  virtual void FuzzData(char* data, int length) = 0;
  virtual void FuzzBytes(void* data, int data_len) = 0;
};

template <typename T>
void FuzzIntegralType(T* value, unsigned int frequency) {
  if (RandEvent(frequency)) {
    switch (RandInRange(4)) {
      case 0: (*value) = 0; break;
      case 1: (*value)--; break;
      case 2: (*value)++; break;
      case 3: (*value) = RandU64(); break;
    }
  }
}

template <typename T>
void FuzzStringType(T* value, unsigned int frequency,
                    const T& literal1, const T& literal2) {
  if (RandEvent(frequency)) {
    switch (RandInRange(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;
    }
  }
}

// One such fuzzer implementation.
class DefaultFuzzer : public Fuzzer {
 public:
  DefaultFuzzer(int frequency) : frequency_(frequency) {
  }

  virtual ~DefaultFuzzer() {}

  virtual void FuzzBool(bool* value) OVERRIDE {
    if (RandEvent(frequency_))
      (*value) = !(*value);
  }

  virtual void FuzzInt(int* value) OVERRIDE {
    FuzzIntegralType<int>(value, frequency_);
  }

  virtual void FuzzLong(long* value) OVERRIDE {
    FuzzIntegralType<long>(value, frequency_);
  }

  virtual void FuzzSize(size_t* value) OVERRIDE {
    FuzzIntegralType<size_t>(value, frequency_);
  }

  virtual void FuzzUChar(unsigned char* value) OVERRIDE {
    FuzzIntegralType<unsigned char>(value, frequency_);
  }

  virtual void FuzzUInt16(uint16* value) OVERRIDE {
    FuzzIntegralType<uint16>(value, frequency_);
  }

  virtual void FuzzUInt32(uint32* value) OVERRIDE {
    FuzzIntegralType<uint32>(value, frequency_);
  }

  virtual void FuzzInt64(int64* value) OVERRIDE {
    FuzzIntegralType<int64>(value, frequency_);
  }

  virtual void FuzzUInt64(uint64* value) OVERRIDE {
    FuzzIntegralType<uint64>(value, frequency_);
  }

  virtual void FuzzFloat(float* value) OVERRIDE {
    if (RandEvent(frequency_))
      *value = RandDouble();
  }

  virtual void FuzzDouble(double* value) OVERRIDE {
    if (RandEvent(frequency_))
      *value = RandDouble();
  }

  virtual void FuzzString(std::string* value) OVERRIDE {
    FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
  }

  virtual void FuzzString16(base::string16* value) OVERRIDE {
    FuzzStringType<base::string16>(value, frequency_,
                                   base::WideToUTF16(L"BORKED"),
                                   base::WideToUTF16(L""));
  }

  virtual void FuzzData(char* data, int length) OVERRIDE {
    if (RandEvent(frequency_)) {
      for (int i = 0; i < length; ++i) {
        FuzzIntegralType<char>(&data[i], frequency_);
      }
    }
  }

  virtual void FuzzBytes(void* data, int data_len) OVERRIDE {
    FuzzData(static_cast<char*>(data), data_len);
  }

 private:
  unsigned int frequency_;
};


// No-op fuzzer.  Rewrites each message unchanged to check if the message
// re-assembly is legit.
class NoOpFuzzer : public Fuzzer {
 public:
  NoOpFuzzer() {}
  virtual ~NoOpFuzzer() {}

  virtual void FuzzBool(bool* value) OVERRIDE {}
  virtual void FuzzInt(int* value) OVERRIDE {}
  virtual void FuzzLong(long* value) OVERRIDE {}
  virtual void FuzzSize(size_t* value) OVERRIDE {}
  virtual void FuzzUChar(unsigned char* value) OVERRIDE {}
  virtual void FuzzUInt16(uint16* value) OVERRIDE {}
  virtual void FuzzUInt32(uint32* value) OVERRIDE {}
  virtual void FuzzInt64(int64* value) OVERRIDE {}
  virtual void FuzzUInt64(uint64* value) OVERRIDE {}
  virtual void FuzzFloat(float* value) OVERRIDE {}
  virtual void FuzzDouble(double* value) OVERRIDE {}
  virtual void FuzzString(std::string* value) OVERRIDE {}
  virtual void FuzzString16(base::string16* value) OVERRIDE {}
  virtual void FuzzData(char* data, int length) OVERRIDE {}
  virtual void FuzzBytes(void* data, int data_len) OVERRIDE {}
};

class FuzzerFactory {
 public:
  static Fuzzer *Create(const std::string& name, int frequency) {
    if (name == "no-op")
      return new NoOpFuzzer();

    if (name == "default")
      return new DefaultFuzzer(frequency);

    std::cerr << "No such fuzzer: " << name << "\n";
    return 0;
  }
};

// Partially-specialized class that knows how to fuzz a given type.
template <class P>
struct FuzzTraits {
  static void Fuzz(P* p, Fuzzer *fuzzer) {
    // This is the catch-all for types we don't have enough information
    // to fuzz. It simply does nothing to the type. We might want to
    // change it to randomly flip a bit in the range (p, p+sizeof(P)).
  }
};

// Template function to invoke partially-specialized class method.
template <class P>
static void FuzzParam(P* p, Fuzzer* fuzzer) {
  FuzzTraits<P>::Fuzz(p, fuzzer);
}

// Specializations to fuzz primitive types.
template <>
struct FuzzTraits<bool> {
  static void Fuzz(bool* p, Fuzzer* fuzzer) {
    fuzzer->FuzzBool(p);
  }
};

template <>
struct FuzzTraits<int> {
  static void Fuzz(int* p, Fuzzer* fuzzer) {
    fuzzer->FuzzInt(p);
  }
};

template <>
struct FuzzTraits<unsigned int> {
  static void Fuzz(unsigned int* p, Fuzzer* fuzzer) {
    fuzzer->FuzzInt(reinterpret_cast<int*>(p));
  }
};

template <>
struct FuzzTraits<long> {
  static void Fuzz(long* p, Fuzzer* fuzzer) {
    fuzzer->FuzzLong(p);
  }
};

template <>
struct FuzzTraits<unsigned long> {
  static void Fuzz(unsigned long* p, Fuzzer* fuzzer) {
    fuzzer->FuzzLong(reinterpret_cast<long*>(p));
  }
};

template <>
struct FuzzTraits<long long> {
  static void Fuzz(long long* p, Fuzzer* fuzzer) {
    fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
  }
};

template <>
struct FuzzTraits<unsigned long long> {
  static void Fuzz(unsigned long long* p, Fuzzer* fuzzer) {
    fuzzer->FuzzInt64(reinterpret_cast<int64*>(p));
  }
};

template <>
struct FuzzTraits<short> {
  static void Fuzz(short* p, Fuzzer* fuzzer) {
    fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
  }
};

template <>
struct FuzzTraits<unsigned short> {
  static void Fuzz(unsigned short* p, Fuzzer* fuzzer) {
    fuzzer->FuzzUInt16(reinterpret_cast<uint16*>(p));
  }
};

template <>
struct FuzzTraits<char> {
  static void Fuzz(char* p, Fuzzer* fuzzer) {
    fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
  }
};

template <>
struct FuzzTraits<unsigned char> {
  static void Fuzz(unsigned char* p, Fuzzer* fuzzer) {
    fuzzer->FuzzUChar(p);
  }
};

template <>
struct FuzzTraits<float> {
  static void Fuzz(float* p, Fuzzer* fuzzer) {
    fuzzer->FuzzFloat(p);
  }
};

template <>
struct FuzzTraits<double> {
  static void Fuzz(double* p, Fuzzer* fuzzer) {
    fuzzer->FuzzDouble(p);
  }
};

template <>
struct FuzzTraits<std::string> {
  static void Fuzz(std::string* p, Fuzzer* fuzzer) {
    fuzzer->FuzzString(p);
  }
};

template <>
struct FuzzTraits<base::string16> {
  static void Fuzz(base::string16* p, Fuzzer* fuzzer) {
    fuzzer->FuzzString16(p);
  }
};

// Specializations to fuzz tuples.
template <class A>
struct FuzzTraits<Tuple1<A> > {
  static void Fuzz(Tuple1<A>* p, Fuzzer* fuzzer) {
    FuzzParam(&p->a, fuzzer);
  }
};

template <class A, class B>
struct FuzzTraits<Tuple2<A, B> > {
  static void Fuzz(Tuple2<A, B>* p, 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, 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, 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, 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, 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, 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, Fuzzer* fuzzer) {
    FuzzParam(&p->second, fuzzer);
  }
};

// Specializations to fuzz hand-coded tyoes
template <>
struct FuzzTraits<base::FileDescriptor> {
  static void Fuzz(base::FileDescriptor* p, Fuzzer* fuzzer) {
    FuzzParam(&p->fd, fuzzer);
  }
};

template <>
struct FuzzTraits<GURL> {
  static void Fuzz(GURL *p, Fuzzer* fuzzer) {
    FuzzParam(&p->possibly_invalid_spec(), fuzzer);
  }
};

template <>
struct FuzzTraits<gfx::Point> {
  static void Fuzz(gfx::Point *p, 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, 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, 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);
  }
};

// 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_BEGIN_WITH_PARENT
#undef IPC_STRUCT_MEMBER
#undef IPC_STRUCT_END
#define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
  IPC_STRUCT_BEGIN(struct_name)
#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, 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() \
    } \
  };

// TODO(tsepez): Make sure to end up with an enum that meets |condition|.
#undef IPC_ENUM_TRAITS_VALIDATE
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, conditon) \
  template <> \
  struct FuzzTraits<enum_name> { \
    static void Fuzz(enum_name* p, Fuzzer* fuzzer) { \
      FuzzParam(reinterpret_cast<int*>(p), fuzzer); \
    } \
  };

// Bring them into existence.
#include "tools/ipc_fuzzer/message_lib/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, Fuzzer* fuzzer) {      \
    return NULL;                                                            \
  }

#define IPC_EMPTY_ROUTED_FUZZ(name, in, out, ilist, olist)                  \
  IPC::Message* fuzzer_for_##name(IPC::Message *msg, Fuzzer* fuzzer) {      \
    return NULL;                                                            \
  }

#define IPC_ASYNC_CONTROL_FUZZ(name, in, out, ilist, olist)                 \
  IPC::Message* fuzzer_for_##name(IPC::Message *msg, 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, 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, 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());                      \
    MessageCracker::CopyMessageID(new_msg, real_msg);                       \
    return new_msg;                                                         \
  }


#define IPC_SYNC_ROUTED_FUZZ(name, in, out, ilist, olist)                   \
  IPC::Message* fuzzer_for_##name(IPC::Message *msg, 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());                      \
    MessageCracker::CopyMessageID(new_msg, 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 "tools/ipc_fuzzer/message_lib/all_messages.h"

typedef IPC::Message* (*FuzzFunction)(IPC::Message*, 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 "tools/ipc_fuzzer/message_lib/all_messages.h"
}

static IPC::Message* RewriteMessage(
    IPC::Message* message,
    Fuzzer* fuzzer,
    FuzzFunctionMap* map) {
  FuzzFunctionMap::iterator it = map->find(message->type());
  if (it == map->end()) {
    // This usually indicates a missing message file in all_messages.h, or
    // that the message dump file is taken from a different revision of
    // chromium from this executable.
    std::cerr << "Unknown message type: ["
              << IPC_MESSAGE_ID_CLASS(message->type()) << ", "
              << IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
    return 0;
  }

  return (*it->second)(message, fuzzer);
}

namespace {

const char kHelpSwitch[] = "help";
const char kHelpSwitchHelp[] =
    "show this message";

const char kFrequencySwitch[] = "frequency";
const char kFrequencySwitchHelp[] =
    "probability of mutation; tweak every 1/|q| times.";

const char kFuzzerNameSwitch[] = "fuzzer-name";
const char kFuzzerNameSwitchHelp[] =
    "select default or no-op fuzzer.";

const char kPermuteSwitch[] = "permute";
const char kPermuteSwitchHelp[] =
    "Randomly shuffle the order of all messages.";

const char kTypeListSwitch[] = "type-list";
const char kTypeListSwitchHelp[] =
    "explicit list of the only message-ids to mutate.";

void usage() {
  std::cerr << "Mutate messages from an exiting message file.\n";

  std::cerr << "Usage:\n"
            << "  ipc_fuzzer_mutate"
            << " [--" << kHelpSwitch << "]"
            << " [--" << kFuzzerNameSwitch << "=f]"
            << " [--" << kFrequencySwitch << "=q]"
            << " [--" << kTypeListSwitch << "=x,y,z...]"
            << " [--" << kPermuteSwitch << "]"
            << " infile outfile\n";

  std::cerr
      << " --" << kHelpSwitch << "         - " << kHelpSwitchHelp << "\n"
      << " --" << kFuzzerNameSwitch <<  "  - " << kFuzzerNameSwitchHelp << "\n"
      << " --" << kFrequencySwitch << "    - " << kFrequencySwitchHelp << "\n"
      << " --" << kTypeListSwitch <<  "    - " << kTypeListSwitchHelp << "\n"
      << " --" << kPermuteSwitch << "      - " << kPermuteSwitchHelp << "\n";
}

}  // namespace

int MutateMain(int argc, char** argv) {
  CommandLine::Init(argc, argv);
  CommandLine* cmd = CommandLine::ForCurrentProcess();
  CommandLine::StringVector args = cmd->GetArgs();

  if (args.size() != 2 || cmd->HasSwitch(kHelpSwitch)) {
    usage();
    return EXIT_FAILURE;
  }

  std::string input_file_name = args[0];
  std::string output_file_name = args[1];

  bool permute = cmd->HasSwitch(kPermuteSwitch);

  std::string fuzzer_name = "default";
  if (cmd->HasSwitch(kFuzzerNameSwitch))
    fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);

  int frequency = 23;
  if (cmd->HasSwitch(kFrequencySwitch))
    frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());

  std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
  std::vector<std::string> type_string_vector;
  base::SplitString(type_string_list, ',', &type_string_vector);
  std::set<int> type_set;
  for (size_t i = 0; i < type_string_vector.size(); ++i) {
    type_set.insert(atoi(type_string_vector[i].c_str()));
  }

  InitRand();

  Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
  if (!fuzzer)
    return EXIT_FAILURE;

  FuzzFunctionMap fuzz_function_map;
  PopulateFuzzFunctionMap(&fuzz_function_map);

  MessageVector message_vector;
  if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
    return EXIT_FAILURE;

  for (size_t i = 0; i < message_vector.size(); ++i) {
    IPC::Message* msg = message_vector[i];
    if (!type_set.empty() && type_set.end() == std::find(
            type_set.begin(), type_set.end(), msg->type())) {
      continue;
    }
    IPC::Message* new_message = RewriteMessage(msg, fuzzer, &fuzz_function_map);
    if (new_message) {
      delete message_vector[i];
      message_vector[i] = new_message;
    }
  }

  if (permute) {
    std::random_shuffle(message_vector.begin(), message_vector.end(),
                        RandInRange);
  }

  if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
    return EXIT_FAILURE;

  return EXIT_SUCCESS;
}

}  // namespace ipc_fuzzer

int main(int argc, char** argv) {
  return ipc_fuzzer::MutateMain(argc, argv);
}

/* [<][>][^][v][top][bottom][index][help] */