Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Unified Diff: tools/ipc_fuzzer/message_lib/message_file_reader.cc

Issue 105083002: IPC fuzzer: create message_lib library. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/ipc_fuzzer/message_lib/message_file_reader.cc
diff --git a/tools/ipc_fuzzer/message_lib/message_file_reader.cc b/tools/ipc_fuzzer/message_lib/message_file_reader.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e93c460b7e287dbfc3012b789db3b505f7b44f25
--- /dev/null
+++ b/tools/ipc_fuzzer/message_lib/message_file_reader.cc
@@ -0,0 +1,230 @@
+// 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 "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "ipc/ipc_message.h"
+#include "tools/ipc_fuzzer/message_lib/message_cracker.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 read IPC message file into a MessageVector and
+// fix message types.
+class Reader {
+ public:
+ Reader(const base::FilePath& path);
+ bool Read(MessageVector* messages);
+
+ private:
+ template <typename T>
+ bool CutObject(const T** object);
+
+ // Reads the header, checks magic and version.
+ bool ReadHeader();
+
+ bool MapFile();
+ bool ReadMessages();
+
+ // Last part of the file is a string table for message names.
+ bool ReadStringTable();
+
+ // Reads type <-> name mapping into name_map_. References string table.
+ bool ReadNameTable();
+
+ // Removes obsolete messages from the vector.
+ bool RemoveUnknownMessages();
+
+ // Does type -> name -> correct_type fixup.
+ void FixMessageTypes();
+
+ // Raw data.
+ base::FilePath path_;
+ base::MemoryMappedFile mapped_file_;
+ base::StringPiece file_data_;
+ base::StringPiece string_table_;
+
+ // Parsed data.
+ const FileHeader* header_;
+ MessageVector* messages_;
+ MessageNames name_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(Reader);
+};
+
+Reader::Reader(const base::FilePath& path)
+ : path_(path),
+ header_(NULL),
+ messages_(NULL) {
+}
+
+template <typename T>
+bool Reader::CutObject(const T** object) {
+ if (file_data_.size() < sizeof(T)) {
+ LOG(ERROR) << "Unexpected EOF.";
+ return false;
+ }
+ *object = reinterpret_cast<const T*>(file_data_.data());
+ file_data_.remove_prefix(sizeof(T));
+ return true;
+}
+
+bool Reader::ReadHeader() {
+ if (!CutObject<FileHeader>(&header_))
+ return false;
+ if (header_->magic != FileHeader::kMagicValue) {
+ LOG(ERROR) << path_.value() << " is not an IPC message file.";
+ return false;
+ }
+ if (header_->version != FileHeader::kCurrentVersion) {
+ LOG(ERROR) << "Wrong version for message file " << path_.value() << ". "
+ << "File version is " << header_->version << ", "
+ << "current version is " << FileHeader::kCurrentVersion << ".";
+ return false;
+ }
+ return true;
+}
+
+bool Reader::MapFile() {
+ if (!mapped_file_.Initialize(path_)) {
+ LOG(ERROR) << "Failed to map testcase: " << path_.value();
+ return false;
+ }
+ const char* data = reinterpret_cast<const char*>(mapped_file_.data());
+ file_data_.set(data, mapped_file_.length());
+ return true;
+}
+
+bool Reader::ReadMessages() {
+ for (size_t i = 0; i < header_->message_count; ++i) {
+ const char* begin = file_data_.begin();
+ const char* end = file_data_.end();
+ const char* message_tail = IPC::Message::FindNext(begin, end);
+ if (!message_tail) {
+ LOG(ERROR) << "Failed to parse message.";
+ return false;
+ }
+
+ size_t msglen = message_tail - begin;
+ if (msglen > INT_MAX) {
+ LOG(ERROR) << "Message too large.";
+ return false;
+ }
+
+ // Copy is necessary to fix message type later.
+ IPC::Message const_message(begin, msglen);
+ IPC::Message* message = new IPC::Message(const_message);
+ messages_->push_back(message);
+ file_data_.remove_prefix(msglen);
+ }
+ return true;
+}
+
+bool Reader::ReadStringTable() {
+ size_t name_count = header_->name_count;
+ if (!name_count)
+ return true;
+ if (name_count > file_data_.size() / sizeof(NameTableEntry)) {
+ LOG(ERROR) << "Invalid name table size: " << name_count;
+ return false;
+ }
+
+ size_t string_table_offset = name_count * sizeof(NameTableEntry);
+ string_table_ = file_data_.substr(string_table_offset);
+ if (string_table_.empty()) {
+ LOG(ERROR) << "Missing string table.";
+ return false;
+ }
+ if (string_table_.end()[-1] != '\0') {
+ LOG(ERROR) << "String table doesn't end with NUL.";
+ return false;
+ }
+ return true;
+}
+
+bool Reader::ReadNameTable() {
+ for (size_t i = 0; i < header_->name_count; ++i) {
+ const NameTableEntry* entry;
+ if (!CutObject<NameTableEntry>(&entry))
+ return false;
+ size_t offset = entry->string_table_offset;
+ if (offset >= string_table_.size()) {
+ LOG(ERROR) << "Invalid string table offset: " << offset;
+ return false;
+ }
+ name_map_.Add(entry->type, std::string(string_table_.data() + offset));
+ }
+ return true;
+}
+
+bool Reader::RemoveUnknownMessages() {
+ MessageVector::iterator it = messages_->begin();
+ while (it != messages_->end()) {
+ uint32 type = (*it)->type();
+ if (!name_map_.TypeExists(type)) {
+ LOG(ERROR) << "Missing name table entry for type " << type;
+ return false;
+ }
+ const std::string& name = name_map_.TypeToName(type);
+ if (!MessageNames::GetInstance()->NameExists(name)) {
+ LOG(WARNING) << "Unknown message " << name;
+ it = messages_->erase(it);
+ } else {
+ ++it;
+ }
+ }
+ return true;
+}
+
+// Message types are based on line numbers, so a minor edit of *_messages.h
+// changes the types of messages in that file. The types are fixed here to
+// increase the lifetime of message files. This is only a partial fix because
+// message arguments and structure layouts can change as well.
+void Reader::FixMessageTypes() {
+ for (MessageVector::iterator it = messages_->begin();
+ it != messages_->end(); ++it) {
+ uint32 type = (*it)->type();
+ const std::string& name = name_map_.TypeToName(type);
+ uint32 correct_type = MessageNames::GetInstance()->NameToType(name);
+ if (type != correct_type)
+ MessageCracker::SetMessageType(*it, correct_type);
+ }
+}
+
+bool Reader::Read(MessageVector* messages) {
+ messages_ = messages;
+
+ if (!MapFile())
+ return false;
+ if (!ReadHeader())
+ return false;
+ if (!ReadMessages())
+ return false;
+ if (!ReadStringTable())
+ return false;
+ if (!ReadNameTable())
+ return false;
+ if (!RemoveUnknownMessages())
+ return false;
+ FixMessageTypes();
+
+ return true;
+}
+
+} // namespace
+
+bool MessageFile::Read(const base::FilePath& path, MessageVector* messages) {
+ Reader reader(path);
+ return reader.Read(messages);
+}
+
+} // namespace ipc_fuzzer
« no previous file with comments | « tools/ipc_fuzzer/message_lib/message_file_format.h ('k') | tools/ipc_fuzzer/message_lib/message_file_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698