| Index: tools/ipc_fuzzer/message_lib/message_file_writer.cc
|
| diff --git a/tools/ipc_fuzzer/message_lib/message_file_writer.cc b/tools/ipc_fuzzer/message_lib/message_file_writer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..46953d8f5004513c47f56bdb3f44482da820d077
|
| --- /dev/null
|
| +++ b/tools/ipc_fuzzer/message_lib/message_file_writer.cc
|
| @@ -0,0 +1,176 @@
|
| +// 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 <limits.h>
|
| +#include <set>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/platform_file.h"
|
| +#include "tools/ipc_fuzzer/message_lib/message_file.h"
|
| +#include "tools/ipc_fuzzer/message_lib/message_file_format.h"
|
| +#include "tools/ipc_fuzzer/message_lib/message_names.h"
|
| +
|
| +namespace ipc_fuzzer {
|
| +
|
| +namespace {
|
| +
|
| +// Helper class to write a MessageVector + message names to a file.
|
| +class Writer {
|
| + public:
|
| + Writer(const base::FilePath& path);
|
| + ~Writer();
|
| + bool Write(const MessageVector& messages);
|
| +
|
| + private:
|
| + bool OpenFile();
|
| +
|
| + // Helper to append data to file_.
|
| + bool WriteBlob(const void *buffer, size_t size);
|
| +
|
| + // Collects a set of MessageVector message types. Corresponding message
|
| + // names need to be included in the file.
|
| + bool CollectMessageTypes();
|
| +
|
| + bool WriteHeader();
|
| + bool WriteMessages();
|
| +
|
| + // Each name table entry is a message type + string table offset.
|
| + bool WriteNameTable();
|
| +
|
| + // String table contains the actual message names.
|
| + bool WriteStringTable();
|
| +
|
| + typedef std::set<uint32> TypesSet;
|
| + base::FilePath path_;
|
| + base::PlatformFile file_;
|
| + const MessageVector* messages_;
|
| + TypesSet types_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Writer);
|
| +};
|
| +
|
| +Writer::Writer(const base::FilePath& path)
|
| + : path_(path),
|
| + file_(base::kInvalidPlatformFileValue),
|
| + messages_(NULL) {
|
| +}
|
| +
|
| +Writer::~Writer() {
|
| + if (file_ != base::kInvalidPlatformFileValue)
|
| + base::ClosePlatformFile(file_);
|
| +}
|
| +
|
| +bool Writer::OpenFile() {
|
| + file_ = base::CreatePlatformFile(
|
| + path_,
|
| + base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
|
| + NULL,
|
| + NULL);
|
| + if (file_ == base::kInvalidPlatformFileValue) {
|
| + LOG(ERROR) << "Failed to create IPC message file: " << path_.value();
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::WriteBlob(const void *buffer, size_t size) {
|
| + if (size > INT_MAX)
|
| + return false;
|
| + const char* char_buffer = static_cast<const char*>(buffer);
|
| + int ret = base::WritePlatformFileAtCurrentPos(file_, char_buffer, size);
|
| + if (ret != size) {
|
| + LOG(ERROR) << "Failed to write " << size << " bytes.";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::CollectMessageTypes() {
|
| + for (size_t i = 0; i < messages_->size(); ++i) {
|
| + uint32_t type = (*messages_)[i]->type();
|
| + if (!MessageNames::GetInstance()->TypeExists(type)) {
|
| + LOG(ERROR) << "Unknown message type: " << type;
|
| + return false;
|
| + }
|
| + types_.insert(type);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::WriteHeader() {
|
| + FileHeader header;
|
| + if (messages_->size() > UINT_MAX)
|
| + return false;
|
| + header.magic = FileHeader::kMagicValue;
|
| + header.version = FileHeader::kCurrentVersion;
|
| + header.message_count = messages_->size();
|
| + header.name_count = types_.size();
|
| + if (!WriteBlob(&header, sizeof(FileHeader)))
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::WriteMessages() {
|
| + for (size_t i = 0; i < messages_->size(); ++i) {
|
| + IPC::Message* message = (*messages_)[i];
|
| + if (!WriteBlob(message->data(), message->size()))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::WriteNameTable() {
|
| + size_t string_table_offset = 0;
|
| + NameTableEntry entry;
|
| +
|
| + for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) {
|
| + if (string_table_offset > UINT_MAX)
|
| + return false;
|
| + entry.type = *it;
|
| + entry.string_table_offset = string_table_offset;
|
| + if (!WriteBlob(&entry, sizeof(NameTableEntry)))
|
| + return false;
|
| + const std::string& name = MessageNames::GetInstance()->TypeToName(*it);
|
| + string_table_offset += name.length() + 1;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::WriteStringTable() {
|
| + for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) {
|
| + const std::string& name = MessageNames::GetInstance()->TypeToName(*it);
|
| + if (!WriteBlob(name.c_str(), name.length() + 1))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Writer::Write(const MessageVector& messages) {
|
| + messages_ = &messages;
|
| +
|
| + if (!OpenFile())
|
| + return false;
|
| + if (!CollectMessageTypes())
|
| + return false;
|
| + if (!WriteHeader())
|
| + return false;
|
| + if (!WriteMessages())
|
| + return false;
|
| + if (!WriteNameTable())
|
| + return false;
|
| + if (!WriteStringTable())
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +bool MessageFile::Write(const base::FilePath& path,
|
| + const MessageVector& messages) {
|
| + Writer writer(path);
|
| + return writer.Write(messages);
|
| +}
|
| +
|
| +} // namespace ipc_fuzzer
|
|
|