普通文本  |  1345行  |  38.99 KB

// 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 <vector>

#include "base/command_line.h"
#include "base/pickle.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/message_file.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"

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

// First include of message files to provide basic type.
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "ipc/ipc_message_null_macros.h"

namespace IPC {
class Message;
}  // namespace IPC

namespace {
// For breaking deep recursion.
int g_depth = 0;
}  // namespace

namespace ipc_fuzzer {

// Interface implemented by those who generate basic types.  The types all
// correspond to the types which a pickle from base/pickle.h can pickle,
// plus the floating point types.
class Generator {
 public:
  virtual void GenerateBool(bool* value) = 0;
  virtual void GenerateInt(int* value) = 0;
  virtual void GenerateLong(long* value) = 0;
  virtual void GenerateSize(size_t* value) = 0;
  virtual void GenerateUChar(unsigned char *value) = 0;
  virtual void GenerateUInt16(uint16* value) = 0;
  virtual void GenerateUInt32(uint32* value) = 0;
  virtual void GenerateInt64(int64* value) = 0;
  virtual void GenerateUInt64(uint64* value) = 0;
  virtual void GenerateFloat(float *value) = 0;
  virtual void GenerateDouble(double *value) = 0;
  virtual void GenerateString(std::string* value) = 0;
  virtual void GenerateString16(base::string16* value) = 0;
  virtual void GenerateData(char* data, int length) = 0;
  virtual void GenerateBytes(void* data, int data_len) = 0;
};

template <typename T>
void GenerateIntegralType(T* value) {
  switch (RandInRange(16)) {
    case 0:
      *value = 0;
      break;
    case 1:
      *value = 1;
      break;
    case 2:
      *value = -1;
      break;
    case 3:
      *value = 2;
      break;
    default:
      *value = static_cast<T>(RandU64());
      break;
  }
}

template <typename T>
void GenerateFloatingType(T* value) {
  *value = RandDouble();
}

template <typename T>
void GenerateStringType(T* value) {
  T temp_string;
  size_t length = RandInRange(300);
  for (size_t i = 0; i < length; ++i)
    temp_string += RandInRange(256);
  *value = temp_string;
}

class GeneratorImpl : public Generator {
 public:
  GeneratorImpl() {}
  virtual ~GeneratorImpl() {}

  virtual void GenerateBool(bool* value) OVERRIDE {
    *value = RandInRange(2);
  }

  virtual void GenerateInt(int* value) OVERRIDE {
    GenerateIntegralType<int>(value);
  }

  virtual void GenerateLong(long* value) OVERRIDE {
    GenerateIntegralType<long>(value);
  }

  virtual void GenerateSize(size_t* value) OVERRIDE {
    GenerateIntegralType<size_t>(value);
  }

  virtual void GenerateUChar(unsigned char* value) OVERRIDE {
    GenerateIntegralType<unsigned char>(value);
  }

  virtual void GenerateUInt16(uint16* value) OVERRIDE {
    GenerateIntegralType<uint16>(value);
  }

  virtual void GenerateUInt32(uint32* value) OVERRIDE {
    GenerateIntegralType<uint32>(value);
  }

  virtual void GenerateInt64(int64* value) OVERRIDE {
    GenerateIntegralType<int64>(value);
  }

  virtual void GenerateUInt64(uint64* value) OVERRIDE {
    GenerateIntegralType<uint64>(value);
  }

  virtual void GenerateFloat(float* value) OVERRIDE {
    GenerateFloatingType<float>(value);
  }

  virtual void GenerateDouble(double* value) OVERRIDE {
    GenerateFloatingType<double>(value);
  }

  virtual void GenerateString(std::string* value) OVERRIDE {
    GenerateStringType<std::string>(value);
  }

  virtual void GenerateString16(base::string16* value) OVERRIDE {
    GenerateStringType<base::string16>(value);
  }

  virtual void GenerateData(char* data, int length) OVERRIDE {
    for (int i = 0; i < length; ++i) {
      GenerateIntegralType<char>(&data[i]);
    }
  }

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

// Partially-specialized class that knows how to generate a given type.
template <class P>
struct GenerateTraits {
  static bool Generate(P* p, Generator *generator) {
    // This is the catch-all for types we don't have enough information
    // to generate.
    std::cerr << "Can't handle " << __PRETTY_FUNCTION__ << "\n";
    return false;
  }
};

// Template function to invoke partially-specialized class method.
template <class P>
static bool GenerateParam(P* p, Generator* generator) {
  return GenerateTraits<P>::Generate(p, generator);
}

// Specializations to generate primitive types.
template <>
struct GenerateTraits<bool> {
  static bool Generate(bool* p, Generator* generator) {
    generator->GenerateBool(p);
    return true;
  }
};

template <>
struct GenerateTraits<int> {
  static bool Generate(int* p, Generator* generator) {
    generator->GenerateInt(p);
    return true;
  }
};

template <>
struct GenerateTraits<unsigned int> {
  static bool Generate(unsigned int* p, Generator* generator) {
    generator->GenerateInt(reinterpret_cast<int*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<long> {
  static bool Generate(long* p, Generator* generator) {
    generator->GenerateLong(p);
    return true;
  }
};

template <>
struct GenerateTraits<unsigned long> {
  static bool Generate(unsigned long* p, Generator* generator) {
    generator->GenerateLong(reinterpret_cast<long*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<long long> {
  static bool Generate(long long* p, Generator* generator) {
    generator->GenerateInt64(reinterpret_cast<int64*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned long long> {
  static bool Generate(unsigned long long* p, Generator* generator) {
    generator->GenerateInt64(reinterpret_cast<int64*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<short> {
  static bool Generate(short* p, Generator* generator) {
    generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned short> {
  static bool Generate(unsigned short* p, Generator* generator) {
    generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<char> {
  static bool Generate(char* p, Generator* generator) {
    generator->GenerateUChar(reinterpret_cast<unsigned char*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned char> {
  static bool Generate(unsigned char* p, Generator* generator) {
    generator->GenerateUChar(p);
    return true;
  }
};

template <>
struct GenerateTraits<float> {
  static bool Generate(float* p, Generator* generator) {
    generator->GenerateFloat(p);
    return true;
  }
};

template <>
struct GenerateTraits<double> {
  static bool Generate(double* p, Generator* generator) {
    generator->GenerateDouble(p);
    return true;
  }
};

template <>
struct GenerateTraits<std::string> {
  static bool Generate(std::string* p, Generator* generator) {
    generator->GenerateString(p);
    return true;
  }
};

template <>
struct GenerateTraits<base::string16> {
  static bool Generate(base::string16* p, Generator* generator) {
    generator->GenerateString16(p);
    return true;
  }
};

// Specializations to generate tuples.
template <>
struct GenerateTraits<Tuple0> {
  static bool Generate(Tuple0* p, Generator* generator) {
    return true;
  }
};

template <class A>
struct GenerateTraits<Tuple1<A> > {
  static bool Generate(Tuple1<A>* p, Generator* generator) {
    return GenerateParam(&p->a, generator);
  }
};

template <class A, class B>
struct GenerateTraits<Tuple2<A, B> > {
  static bool Generate(Tuple2<A, B>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator);
  }
};

template <class A, class B, class C>
struct GenerateTraits<Tuple3<A, B, C> > {
  static bool Generate(Tuple3<A, B, C>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator);
  }
};

template <class A, class B, class C, class D>
struct GenerateTraits<Tuple4<A, B, C, D> > {
  static bool Generate(Tuple4<A, B, C, D>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator) &&
        GenerateParam(&p->d, generator);
  }
};

template <class A, class B, class C, class D, class E>
struct GenerateTraits<Tuple5<A, B, C, D, E> > {
  static bool Generate(Tuple5<A, B, C, D, E>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator) &&
        GenerateParam(&p->d, generator) &&
        GenerateParam(&p->e, generator);
  }
};

// Specializations to generate containers.
template <class A>
struct GenerateTraits<std::vector<A> > {
  static bool Generate(std::vector<A>* p, Generator* generator) {
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    p->resize(count);
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&p->at(i), generator)) {
        --g_depth;
        return false;
      }
    }
    --g_depth;
    return true;
  }
};

template <class A>
struct GenerateTraits<std::set<A> > {
  static bool Generate(std::set<A>* p, Generator* generator) {
    static int g_depth = 0;
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    A a;
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&a, generator)) {
        --g_depth;
        return false;
      }
      p->insert(a);
    }
    --g_depth;
    return true;
  }
};


template <class A, class B>
struct GenerateTraits<std::map<A, B> > {
  static bool Generate(std::map<A, B>* p, Generator* generator) {
    static int g_depth = 0;
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    std::pair<A, B> place_holder;
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&place_holder, generator)) {
        --g_depth;
        return false;
      }
      p->insert(place_holder);
    }
    --g_depth;
    return true;
  }
};

template <class A, class B>
struct GenerateTraits<std::pair<A, B> > {
  static bool Generate(std::pair<A, B>* p, Generator* generator) {
    return
        GenerateParam(&p->first, generator) &&
        GenerateParam(&p->second, generator);
  }
};

// Specializations to generate hand-coded tyoes
template <>
struct GenerateTraits<base::NullableString16> {
  static bool Generate(base::NullableString16* p, Generator* generator) {
    *p = base::NullableString16();
    return true;
  }
};

template <>
struct GenerateTraits<base::FileDescriptor> {
  static bool Generate(base::FileDescriptor* p, Generator* generator) {
    // I don't think we can generate real ones due to check on construct.
    p->fd = -1;
    return true;
  }
};

template <>
struct GenerateTraits<base::FilePath> {
  static bool Generate(base::FilePath* p, Generator* generator) {
    const char path_chars[] = "ACz0/.~:";
    size_t count = RandInRange(60);
    std::string random_path;
    for (size_t i = 0; i < count; ++i)
      random_path += path_chars[RandInRange(sizeof(path_chars) - 1)];
    *p = base::FilePath(random_path);
    return true;
  }
};

template <>
struct GenerateTraits<base::File::Error> {
  static bool Generate(base::File::Error* p, Generator* generator) {
    int temporary;
    if (!GenerateParam(&temporary, generator))
      return false;
    *p = static_cast<base::File::Error>(temporary);
    return true;
  }
};

template <>
struct GenerateTraits<base::File::Info> {
  static bool Generate(base::File::Info* p, Generator* generator) {
    double last_modified;
    double last_accessed;
    double creation_time;
    if (!GenerateParam(&p->size, generator))
      return false;
    if (!GenerateParam(&p->is_directory, generator))
      return false;
    if (!GenerateParam(&last_modified, generator))
      return false;
    if (GenerateParam(&last_accessed, generator))
      return false;
    if (GenerateParam(&creation_time, generator))
      return false;
    p->last_modified = base::Time::FromDoubleT(last_modified);
    p->last_accessed = base::Time::FromDoubleT(last_accessed);
    p->creation_time = base::Time::FromDoubleT(creation_time);
    return true;
  }
};

template <>
struct GenerateTraits<base::Time> {
  static bool Generate(base::Time* p, Generator* generator) {
    *p = base::Time::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::TimeDelta> {
  static bool Generate(base::TimeDelta* p, Generator* generator) {
    *p = base::TimeDelta::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::TimeTicks> {
  static bool Generate(base::TimeTicks* p, Generator* generator) {
    *p = base::TimeTicks::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::ListValue> {
  static bool Generate(base::ListValue* p, Generator* generator) {
    ++g_depth;
    size_t list_length = g_depth > 3 ? 0 : RandInRange(8);
    for (size_t index = 0; index < list_length; ++index) {
      switch (RandInRange(8))
      {
        case base::Value::TYPE_BOOLEAN: {
          bool tmp;
          generator->GenerateBool(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_INTEGER: {
          int tmp;
          generator->GenerateInt(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_DOUBLE: {
          double tmp;
          generator->GenerateDouble(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_STRING: {
          std::string tmp;
          generator->GenerateString(&tmp);
          p->Set(index, new base::StringValue(tmp));
          break;
        }
        case base::Value::TYPE_BINARY: {
          char tmp[200];
          size_t bin_length = RandInRange(sizeof(tmp));
          generator->GenerateData(tmp, bin_length);
          p->Set(index,
                 base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
          break;
        }
        case base::Value::TYPE_DICTIONARY: {
          base::DictionaryValue* tmp = new base::DictionaryValue();
          GenerateParam(tmp, generator);
          p->Set(index, tmp);
          break;
        }
        case base::Value::TYPE_LIST: {
          base::ListValue* tmp = new base::ListValue();
          GenerateParam(tmp, generator);
          p->Set(index, tmp);
          break;
        }
        case base::Value::TYPE_NULL:
        default:
          break;
      }
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<base::DictionaryValue> {
  static bool Generate(base::DictionaryValue* p, Generator* generator) {
    ++g_depth;
    size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
    for (size_t index = 0; index < dict_length; ++index) {
      std::string property;
      generator->GenerateString(&property);
      switch (RandInRange(8))
      {
        case base::Value::TYPE_BOOLEAN: {
          bool tmp;
          generator->GenerateBool(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_INTEGER: {
          int tmp;
          generator->GenerateInt(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_DOUBLE: {
          double tmp;
          generator->GenerateDouble(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_STRING: {
          std::string tmp;
          generator->GenerateString(&tmp);
          p->SetWithoutPathExpansion(property, new base::StringValue(tmp));
          break;
        }
        case base::Value::TYPE_BINARY: {
          char tmp[200];
          size_t bin_length = RandInRange(sizeof(tmp));
          generator->GenerateData(tmp, bin_length);
          p->SetWithoutPathExpansion(
              property,
              base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
          break;
        }
        case base::Value::TYPE_DICTIONARY: {
          base::DictionaryValue* tmp = new base::DictionaryValue();
          GenerateParam(tmp, generator);
          p->SetWithoutPathExpansion(property, tmp);
          break;
        }
        case base::Value::TYPE_LIST: {
          base::ListValue* tmp = new base::ListValue();
          GenerateParam(tmp, generator);
          p->SetWithoutPathExpansion(property, tmp);
          break;
        }
        case base::Value::TYPE_NULL:
        default:
          break;
      }
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<GURL> {
  static bool Generate(GURL *p, Generator* generator) {
    const char url_chars[] = "Ahtp0:/.?+\%&#";
    size_t count = RandInRange(100);
    std::string random_url;
    for (size_t i = 0; i < count; ++i)
      random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
    int selector = RandInRange(10);
    if (selector == 0)
      random_url = std::string("http://") + random_url;
    else if (selector == 1)
      random_url = std::string("file://") + random_url;
    else if (selector == 2)
      random_url = std::string("javascript:") + random_url;
    else if (selector == 2)
      random_url = std::string("data:") + random_url;
    *p = GURL(random_url);
    return true;
  }
};

// FIXME: Actually generate something.
template <>
struct GenerateTraits<SkBitmap> {
  static bool Generate(SkBitmap* p, Generator* generator) {
    *p = SkBitmap();
    return true;
  }
};

template <>
struct GenerateTraits<IPC::ChannelHandle> {
  static bool Generate(IPC::ChannelHandle* p, Generator* generator) {
    return
        GenerateParam(&p->name, generator) &&
        GenerateParam(&p->socket, generator);
  }
};

template <>
struct GenerateTraits<cc::CompositorFrame> {
  // FIXME: this should actually generate something
  static bool Generate(cc::CompositorFrame* p, Generator* generator) {
    return true;
  }
};

template <>
struct GenerateTraits<cc::CompositorFrameAck> {
  // FIXME: this should actually generate something
  static bool Generate(cc::CompositorFrameAck* p, Generator* generator) {
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKey> {
  static bool Generate(content::IndexedDBKey* p, Generator* generator) {
    ++g_depth;
    blink::WebIDBKeyType web_type =
        static_cast<blink::WebIDBKeyType>(RandInRange(7));
    switch (web_type)
    {
      case blink::WebIDBKeyTypeArray: {
        size_t length = g_depth > 3 ? 0 : RandInRange(4);
        std::vector<content::IndexedDBKey> array;
        array.resize(length);
        for (size_t i = 0; i < length; ++i) {
          if (!GenerateParam(&array[i], generator))
            return false;
        }
        *p = content::IndexedDBKey(array);
        return true;
      }
      case blink::WebIDBKeyTypeBinary: {
        std::string binary;
        if (!GenerateParam(&binary, generator))
          return false;
        *p = content::IndexedDBKey(binary);
        return true;
      }
      case blink::WebIDBKeyTypeString: {
        base::string16 string;
        if (!GenerateParam(&string, generator))
          return false;
        *p = content::IndexedDBKey(string);
        return true;
      }
      case blink::WebIDBKeyTypeDate:
      case blink::WebIDBKeyTypeNumber: {
        double number;
        if (!GenerateParam(&number, generator))
          return false;
        *p = content::IndexedDBKey(number, web_type);
        return true;
      }
      case blink::WebIDBKeyTypeInvalid:
      case blink::WebIDBKeyTypeNull: {
        *p = content::IndexedDBKey(web_type);
        return true;
      }
      default:
        NOTREACHED();
        return false;
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKeyRange> {
  static bool Generate(content::IndexedDBKeyRange *p, Generator* generator) {
    content::IndexedDBKey lower;
    content::IndexedDBKey upper;
    bool lower_open;
    bool upper_open;
    if (!GenerateParam(&lower, generator))
      return false;
    if (!GenerateParam(&upper, generator))
      return false;
    if (!GenerateParam(&lower_open, generator))
      return false;
    if (!GenerateParam(&upper_open, generator))
      return false;
    *p = content::IndexedDBKeyRange(lower, upper, lower_open, upper_open);
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKeyPath> {
  static bool Generate(content::IndexedDBKeyPath *p, Generator* generator) {
    switch (RandInRange(3)) {
      case 0: {
        std::vector<base::string16> array;
        if (!GenerateParam(&array, generator))
          return false;
        *p = content::IndexedDBKeyPath(array);
        break;
      }
      case 1: {
        base::string16 string;
        if (!GenerateParam(&string, generator))
          return false;
        *p = content::IndexedDBKeyPath(string);
        break;
      }
      case 2: {
        *p = content::IndexedDBKeyPath();
        break;
      }
    }
    return true;
  }
};

template <>
struct GenerateTraits<content::PageState> {
  static bool Generate(content::PageState *p, Generator* generator) {
    std::string junk;
    if (!GenerateParam(&junk, generator))
      return false;
    *p = content::PageState::CreateFromEncodedData(junk);
    return true;
  }
};

template <>
struct GenerateTraits<gpu::Mailbox> {
  static bool Generate(gpu::Mailbox *p, Generator* generator) {
    generator->GenerateBytes(p->name, sizeof(p->name));
    return true;
  }
};

template <>
struct GenerateTraits<media::AudioParameters> {
  static bool Generate(media::AudioParameters *p, Generator* generator) {
    int format;
    int channel_layout;
    int channels;
    int input_channels;
    int sample_rate;
    int bits_per_sample;
    int frames_per_buffer;
    int effects;
    if (!GenerateParam(&format, generator))
      return false;
    if (!GenerateParam(&channel_layout, generator))
      return false;
    if (!GenerateParam(&channels, generator))
      return false;
    if (!GenerateParam(&input_channels, generator))
      return false;
    if (!GenerateParam(&sample_rate, generator))
      return false;
    if (!GenerateParam(&bits_per_sample, generator))
      return false;
    if (!GenerateParam(&frames_per_buffer, generator))
      return false;
    if (!GenerateParam(&effects, generator))
      return false;
    media::AudioParameters params(
        static_cast<media::AudioParameters::Format>(format),
        static_cast<media::ChannelLayout>(channel_layout),
        channels, input_channels, sample_rate,
        bits_per_sample, frames_per_buffer, effects);
    *p = params;
    return true;
  }
};

template <>
struct GenerateTraits<media::VideoCaptureFormat> {
  static bool Generate(media::VideoCaptureFormat *p, Generator* generator) {
    int frame_size_width;
    int frame_size_height;
    int pixel_format;
    if (!GenerateParam(&frame_size_height, generator))
      return false;
    if (!GenerateParam(&frame_size_width, generator))
      return false;
    if (!GenerateParam(&pixel_format, generator))
      return false;
    if (!GenerateParam(&p->frame_rate, generator))
      return false;
    p->frame_size.SetSize(frame_size_width, frame_size_height);
    p->pixel_format = static_cast<media::VideoPixelFormat>(pixel_format);
    return true;
  }
};


template <>
struct GenerateTraits<net::LoadTimingInfo> {
  static bool Generate(net::LoadTimingInfo *p, Generator* generator) {
    return
        GenerateParam(&p->socket_log_id, generator) &&
        GenerateParam(&p->socket_reused, generator) &&
        GenerateParam(&p->request_start_time, generator) &&
        GenerateParam(&p->request_start, generator) &&
        GenerateParam(&p->proxy_resolve_start, generator) &&
        GenerateParam(&p->proxy_resolve_end, generator) &&
        GenerateParam(&p->connect_timing.dns_start, generator) &&
        GenerateParam(&p->connect_timing.dns_end, generator) &&
        GenerateParam(&p->connect_timing.connect_start, generator) &&
        GenerateParam(&p->connect_timing.connect_end, generator) &&
        GenerateParam(&p->connect_timing.ssl_start, generator) &&
        GenerateParam(&p->connect_timing.ssl_end, generator) &&
        GenerateParam(&p->send_start, generator) &&
        GenerateParam(&p->send_end, generator) &&
        GenerateParam(&p->receive_headers_end, generator);
  }
};

template <>
struct GenerateTraits<net::HostPortPair> {
  static bool Generate(net::HostPortPair *p, Generator* generator) {
    std::string host;
    uint16 port;
    if (!GenerateParam(&host, generator))
      return false;
    if (!GenerateParam(&port, generator))
      return false;
    p->set_host(host);
    p->set_port(port);
    return true;
  }
};

template <>
struct GenerateTraits<net::IPEndPoint> {
  static bool Generate(net::IPEndPoint *p, Generator* generator) {
    net::IPAddressNumber address;
    int port;
    if (!GenerateParam(&address, generator))
      return false;
    if (!GenerateParam(&port, generator))
      return false;
    net::IPEndPoint ip_endpoint(address, port);
    *p = ip_endpoint;
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Point> {
  static bool Generate(gfx::Point *p, Generator* generator) {
    int x;
    int y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    p->SetPoint(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::PointF> {
  static bool Generate(gfx::PointF *p, Generator* generator) {
    float x;
    float y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    p->SetPoint(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Size> {
  static bool Generate(gfx::Size *p, Generator* generator) {
    int w;
    int h;
    if (!GenerateParam(&w, generator))
      return false;
    if (!GenerateParam(&h, generator))
      return false;
    p->SetSize(w, h);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::SizeF> {
  static bool Generate(gfx::SizeF *p, Generator* generator) {
    float w;
    float h;
    if (!GenerateParam(&w, generator))
      return false;
    if (!GenerateParam(&h, generator))
      return false;
    p->SetSize(w, h);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Rect> {
  static bool Generate(gfx::Rect *p, Generator* generator) {
    gfx::Point origin;
    gfx::Size  size;
    if (!GenerateParam(&origin, generator))
      return false;
    if (!GenerateParam(&size, generator))
      return false;
    p->set_origin(origin);
    p->set_size(size);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::RectF> {
  static bool Generate(gfx::RectF *p, Generator* generator) {
    gfx::PointF origin;
    gfx::SizeF  size;
    if (!GenerateParam(&origin, generator))
      return false;
    if (!GenerateParam(&size, generator))
      return false;
    p->set_origin(origin);
    p->set_size(size);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Range> {
  static bool Generate(gfx::Range *p, Generator* generator) {
    size_t start;
    size_t end;
    if (!GenerateParam(&start, generator))
      return false;
    if (!GenerateParam(&end, generator))
      return false;
    *p = gfx::Range(start, end);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Vector2d> {
  static bool Generate(gfx::Vector2d *p, Generator* generator) {
    int x;
    int y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    *p = gfx::Vector2d(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Vector2dF> {
  static bool Generate(gfx::Vector2dF *p, Generator* generator) {
    float x;
    float y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    *p = gfx::Vector2dF(x, y);
    return true;
  }
};

// PP_ traits.
template <>
struct GenerateTraits<PP_Bool> {
  static bool Generate(PP_Bool *p, Generator* generator) {
    bool tmp;
    if (!GenerateParam(&tmp, generator))
      return false;
    *p = PP_FromBool(tmp);
    return true;
  }
};

template <>
struct GenerateTraits<PP_NetAddress_Private> {
  static bool Generate(PP_NetAddress_Private *p, Generator* generator) {
    p->size = RandInRange(sizeof(p->data) + 1);
    generator->GenerateBytes(&p->data, p->size);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::HostResource> {
  static bool Generate(ppapi::HostResource *p, Generator* generator) {
    PP_Instance instance;
    PP_Resource resource;
    if (!GenerateParam(&instance, generator))
      return false;
    if (!GenerateParam(&resource, generator))
      return false;
    p->SetHostResource(instance, resource);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::PepperFilePath> {
  static bool Generate(ppapi::PepperFilePath *p, Generator* generator) {
    unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
    base::FilePath path;
    if (!GenerateParam(&path, generator))
      return false;
    *p = ppapi::PepperFilePath(
        static_cast<ppapi::PepperFilePath::Domain>(domain), path);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::PpapiPermissions> {
  static bool Generate(ppapi::PpapiPermissions *p, Generator* generator) {
    uint32_t bits;
    if (!GenerateParam(&bits, generator))
      return false;
    *p = ppapi::PpapiPermissions(bits);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::SocketOptionData> {
  static bool Generate(ppapi::SocketOptionData *p, Generator* generator) {
    // FIXME: we can do better here.
    int32 temp;
    if (!GenerateParam(&temp, generator))
      return false;
    p->SetInt32(temp);
    return true;
  }
};

// Redefine macros to generate generating from traits declarations.
// 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 generate 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 GenerateTraits<struct_name> { \
    static bool Generate(struct_name *p, Generator* generator) {

#define IPC_STRUCT_TRAITS_MEMBER(name) \
      if (!GenerateParam(&p->name, generator)) \
        return false;

#define IPC_STRUCT_TRAITS_PARENT(type) \
      if (!GenerateParam(static_cast<type*>(p), generator)) \
        return false;

#define IPC_STRUCT_TRAITS_END() \
      return true; \
    } \
  };

// If |condition| isn't met, the messsge will fail to serialize. Try
// increasingly smaller ranges until we find one that happens to meet
// the condition, or fail trying.
#undef IPC_ENUM_TRAITS_VALIDATE
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition)             \
  template <>                                                      \
  struct GenerateTraits<enum_name> {                               \
    static bool Generate(enum_name* p, Generator* generator) {     \
      for (int shift = 30; shift; --shift) {                       \
        for (int tries = 0; tries < 2; ++tries) {                  \
          int value = RandInRange(1 << shift);                     \
          if (condition) {                                         \
            *reinterpret_cast<int*>(p) = value;                    \
            return true;                                           \
          }                                                        \
        }                                                          \
      }                                                            \
      std::cerr << "failed to satisfy " << #condition << "\n";     \
      return false;                                                \
    }                                                              \
  };

// Bring them into existence.
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "ipc/ipc_message_null_macros.h"

// Redefine macros to generate generating funtions
#undef IPC_MESSAGE_DECL
#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist)       \
  IPC_##kind##_##type##_GENERATE(name, in, out, ilist, olist)

#define IPC_EMPTY_CONTROL_GENERATE(name, in, out, ilist, olist)         \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    return new name();                                                  \
  }

#define IPC_EMPTY_ROUTED_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    return new name(RandInRange(MAX_FAKE_ROUTING_ID));                  \
  }

#define IPC_ASYNC_CONTROL_GENERATE(name, in, out, ilist, olist)         \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(IPC_MEMBERS_IN_##in(p));                          \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_ASYNC_ROUTED_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
                      IPC_COMMA_##in                                    \
                      IPC_MEMBERS_IN_##in(p));                          \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_SYNC_CONTROL_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(IPC_MEMBERS_IN_##in(p)                            \
                      IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
                      IPC_MEMBERS_OUT_##out());                         \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_SYNC_ROUTED_GENERATE(name, in, out, ilist, olist)           \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(RandInRange(MAX_FAKE_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());                         \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define MAX_FAKE_ROUTING_ID 15

#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"
#include "ipc/ipc_message_null_macros.h"

typedef IPC::Message* (*GeneratorFunction)(Generator*);
typedef std::vector<GeneratorFunction> GeneratorFunctionVector;

void PopulateGeneratorFunctionVector(
    GeneratorFunctionVector *function_vector) {
#undef IPC_MESSAGE_DECL
#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
  function_vector->push_back(generator_for_##name);
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
}

static const char kCountSwitch[] = "count";
static const char kHelpSwitch[] = "help";

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

  if (args.size() != 1 || cmd->HasSwitch(kHelpSwitch)) {
    std::cerr << "Usage: ipc_fuzzer_generate [--help] [--count=n] outfile\n";
    return EXIT_FAILURE;
  }
  std::string output_file_name = args[0];

  int message_count = 1000;
  if (cmd->HasSwitch(kCountSwitch))
    message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());

  InitRand();

  GeneratorFunctionVector function_vector;
  PopulateGeneratorFunctionVector(&function_vector);
  std::cerr << "Counted " << function_vector.size()
            << " distinct messages present in chrome.\n";

  Generator* generator = new GeneratorImpl();
  MessageVector message_vector;

  int bad_count = 0;
  if (message_count < 0) {
    // Enumerate them all.
    for (size_t i = 0; i < function_vector.size(); ++i) {
      if (IPC::Message* new_message = (*function_vector[i])(generator))
        message_vector.push_back(new_message);
      else
        bad_count += 1;
    }
  } else {
    // Generate a random batch.
    for (int i = 0; i < message_count; ++i) {
      size_t index = RandInRange(function_vector.size());
      if (IPC::Message* new_message = (*function_vector[index])(generator))
        message_vector.push_back(new_message);
      else
        bad_count += 1;
    }
  }

  std::cerr << "Failed to generate " << bad_count << " messages.\n";

  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::GenerateMain(argc, argv);
}