1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <limits.h> 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <set> 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "tools/ipc_fuzzer/message_lib/message_file.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "tools/ipc_fuzzer/message_lib/message_file_format.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "tools/ipc_fuzzer/message_lib/message_names.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace ipc_fuzzer { 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Helper class to write a MessageVector + message names to a file. 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class Writer { 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Writer(const base::FilePath& path); 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ~Writer() {} 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool Write(const MessageVector& messages); 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool OpenFile(); 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Helper to append data to file_. 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool WriteBlob(const void *buffer, size_t size); 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Collects a set of MessageVector message types. Corresponding message 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // names need to be included in the file. 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool CollectMessageTypes(); 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool WriteHeader(); 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool WriteMessages(); 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Each name table entry is a message type + string table offset. 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool WriteNameTable(); 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // String table contains the actual message names. 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool WriteStringTable(); 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef std::set<uint32> TypesSet; 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath path_; 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file_; 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const MessageVector* messages_; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TypesSet types_; 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Writer); 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Writer::Writer(const base::FilePath& path) : path_(path), messages_(NULL) { 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::OpenFile() { 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) file_.Initialize(path_, 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!file_.IsValid()) { 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Failed to create IPC message file: " << path_.value(); 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::WriteBlob(const void *buffer, size_t size) { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (size > INT_MAX) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* char_buffer = static_cast<const char*>(buffer); 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int ret = file_.WriteAtCurrentPos(char_buffer, size); 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ret != static_cast<int>(size)) { 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Failed to write " << size << " bytes."; 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::CollectMessageTypes() { 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (size_t i = 0; i < messages_->size(); ++i) { 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32_t type = (*messages_)[i]->type(); 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!MessageNames::GetInstance()->TypeExists(type)) { 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Unknown message type: " << type; 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) types_.insert(type); 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::WriteHeader() { 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FileHeader header; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (messages_->size() > UINT_MAX) 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) header.magic = FileHeader::kMagicValue; 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) header.version = FileHeader::kCurrentVersion; 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) header.message_count = messages_->size(); 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) header.name_count = types_.size(); 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteBlob(&header, sizeof(FileHeader))) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::WriteMessages() { 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (size_t i = 0; i < messages_->size(); ++i) { 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) IPC::Message* message = (*messages_)[i]; 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteBlob(message->data(), message->size())) 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::WriteNameTable() { 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t string_table_offset = 0; 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NameTableEntry entry; 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) { 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (string_table_offset > UINT_MAX) 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.type = *it; 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.string_table_offset = string_table_offset; 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteBlob(&entry, sizeof(NameTableEntry))) 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& name = MessageNames::GetInstance()->TypeToName(*it); 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) string_table_offset += name.length() + 1; 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::WriteStringTable() { 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) { 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& name = MessageNames::GetInstance()->TypeToName(*it); 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteBlob(name.c_str(), name.length() + 1)) 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Writer::Write(const MessageVector& messages) { 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) messages_ = &messages; 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!OpenFile()) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!CollectMessageTypes()) 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteHeader()) 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteMessages()) 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteNameTable()) 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!WriteStringTable()) 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool MessageFile::Write(const base::FilePath& path, 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const MessageVector& messages) { 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Writer writer(path); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return writer.Write(messages); 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace ipc_fuzzer 166