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

Side by Side 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: Rename map_ to mapped_file_. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <limits.h>
6
7 #include "base/files/file_path.h"
8 #include "base/files/memory_mapped_file.h"
9 #include "base/logging.h"
10 #include "base/strings/string_piece.h"
11 #include "ipc/ipc_message.h"
12 #include "tools/ipc_fuzzer/message_lib/message_cracker.h"
13 #include "tools/ipc_fuzzer/message_lib/message_file.h"
14 #include "tools/ipc_fuzzer/message_lib/message_file_format.h"
15 #include "tools/ipc_fuzzer/message_lib/message_names.h"
16
17 namespace ipc_fuzzer {
18
19 namespace {
20
21 // Helper class to read IPC message file into a MessageVector and
22 // fix message types.
23 class Reader {
24 public:
25 Reader(const base::FilePath& path);
26 bool Read(MessageVector* messages);
27
28 private:
29 template <typename T>
30 bool CutObject(const T** object);
31
32 bool MapFile();
33 bool ReadMessages();
34
35 // Last part of the file is a string table for message names.
36 bool ReadStringTable();
37
38 // Reads type <-> name mapping into name_map_. References string table.
39 bool ReadNameTable();
40
41 // Does type -> name -> correct_type fixup.
42 bool FixMessageTypes();
43
44 // Raw data.
45 base::FilePath path_;
46 base::MemoryMappedFile mapped_file_;
47 base::StringPiece file_data_;
48 base::StringPiece string_table_;
49
50 // Parsed data.
51 const FileHeader* header_;
52 MessageVector* messages_;
53 MessageNames name_map_;
54
55 DISALLOW_COPY_AND_ASSIGN(Reader);
56 };
57
58 Reader::Reader(const base::FilePath& path)
59 : path_(path),
60 header_(NULL),
61 messages_(NULL) {
62 }
63
64 template <typename T>
65 bool Reader::CutObject(const T** object) {
66 if (file_data_.size() < sizeof(T)) {
67 LOG(ERROR) << "Unexpected EOF.";
68 return false;
69 }
70 *object = reinterpret_cast<const T*>(file_data_.data());
71 file_data_.remove_prefix(sizeof(T));
72 return true;
73 }
74
75 bool Reader::MapFile() {
76 if (!mapped_file_.Initialize(path_)) {
77 LOG(ERROR) << "Failed to map testcase: " << path_.value();
78 return false;
79 }
80 const char* data = reinterpret_cast<const char*>(mapped_file_.data());
81 file_data_.set(data, mapped_file_.length());
82 return true;
83 }
84
85 bool Reader::ReadMessages() {
86 for (size_t i = 0; i < header_->message_count; ++i) {
87 const char* begin = file_data_.begin();
88 const char* end = file_data_.end();
89 const char* message_tail = IPC::Message::FindNext(begin, end);
90 if (!message_tail) {
91 LOG(ERROR) << "Failed to parse message.";
92 return false;
93 }
94
95 size_t msglen = message_tail - begin;
96 if (msglen > INT_MAX) {
97 LOG(ERROR) << "Message too large.";
98 return false;
99 }
100
101 // Copy is necessary to fix message type later.
102 IPC::Message const_message(begin, msglen);
103 IPC::Message* message = new IPC::Message(const_message);
104 messages_->push_back(message);
105
Tom Sepez 2013/12/06 18:57:16 nit: (micro-nit, actually) no blank line here.
aedla 2013/12/09 18:08:32 Done.
106 file_data_.remove_prefix(msglen);
107 }
108 return true;
109 }
110
111 bool Reader::ReadStringTable() {
112 size_t name_count = header_->name_count;
113 if (!name_count)
Tom Sepez 2013/12/06 18:57:16 I'd consider this an error, since all the fixups b
aedla 2013/12/09 18:08:32 I'd like to support empty testcases, which have me
114 return true;
115 if (name_count > file_data_.size() / sizeof(NameTableEntry)) {
116 LOG(ERROR) << "Invalid name table size: " << name_count;
117 return false;
118 }
119
120 size_t string_table_offset = name_count * sizeof(NameTableEntry);
121 string_table_ = file_data_.substr(string_table_offset);
122 if (string_table_.empty()) {
123 LOG(ERROR) << "Missing string table.";
124 return false;
125 }
126 if (string_table_.end()[-1] != '\0') {
127 LOG(ERROR) << "String table doesn't end with NUL.";
128 return false;
129 }
130 return true;
131 }
132
133 bool Reader::ReadNameTable() {
134 for (size_t i = 0; i < header_->name_count; ++i) {
135 const NameTableEntry* entry;
136 if (!CutObject<NameTableEntry>(&entry))
137 return false;
138 size_t offset = entry->string_table_offset;
139 if (offset >= string_table_.size()) {
140 LOG(ERROR) << "Invalid string table offset: " << offset;
141 return false;
142 }
143 name_map_.Add(entry->type, std::string(string_table_.data() + offset));
144 }
145 return true;
146 }
147
148 bool Reader::FixMessageTypes() {
149 for (size_t i = 0; i < messages_->size(); ++i) {
Tom Sepez 2013/12/06 18:57:16 Probably a comment about why this is necessary, an
aedla 2013/12/09 18:08:32 Done.
150 IPC::Message* message = (*messages_)[i];
151 uint32 type = message->type();
152 if (!name_map_.TypeExists(type)) {
153 LOG(ERROR) << "Missing name table entry for type " << type;
154 return false;
Tom Sepez 2013/12/06 18:57:16 You can't bail here. Someone might have removed t
aedla 2013/12/09 18:08:32 Ah, this particular case happens when the file doe
155 }
156 const std::string& name = name_map_.TypeToName(type);
157 uint32 correct_type = MessageNames::Get().NameToType(name);
158 if (type != correct_type)
159 MessageCracker::SetMessageType(message, correct_type);
160 }
161 return true;
162 }
163
164 bool Reader::Read(MessageVector* messages) {
165 messages_ = messages;
166
167 if (!MapFile())
168 return false;
169 if (!CutObject<FileHeader>(&header_))
170 return false;
171 if (!ReadMessages())
172 return false;
173 if (!ReadStringTable())
174 return false;
175 if (!ReadNameTable())
176 return false;
177 if (!FixMessageTypes())
178 return false;
179
180 return true;
181 }
182
183 } // namespace
184
185 bool MessageFile::Read(const base::FilePath& path, MessageVector* messages) {
186 Reader reader(path);
187 return reader.Read(messages);
188 }
189
190 } // namespace ipc_fuzzer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698