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.
8 #include "base/files/file.h"
9 #include "base/logging.h"
10 #include "tools/ipc_fuzzer/message_lib/message_file.h"
11 #include "tools/ipc_fuzzer/message_lib/message_file_format.h"
12 #include "tools/ipc_fuzzer/message_lib/message_names.h"
14 namespace ipc_fuzzer
{
18 // Helper class to write a MessageVector + message names to a file.
21 Writer(const base::FilePath
& path
);
23 bool Write(const MessageVector
& messages
);
28 // Helper to append data to file_.
29 bool WriteBlob(const void *buffer
, size_t size
);
31 // Collects a set of MessageVector message types. Corresponding message
32 // names need to be included in the file.
33 bool CollectMessageTypes();
38 // Each name table entry is a message type + string table offset.
39 bool WriteNameTable();
41 // String table contains the actual message names.
42 bool WriteStringTable();
44 typedef std::set
<uint32
> TypesSet
;
47 const MessageVector
* messages_
;
50 DISALLOW_COPY_AND_ASSIGN(Writer
);
53 Writer::Writer(const base::FilePath
& path
) : path_(path
), messages_(NULL
) {
56 bool Writer::OpenFile() {
57 file_
.Initialize(path_
,
58 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
);
59 if (!file_
.IsValid()) {
60 LOG(ERROR
) << "Failed to create IPC message file: " << path_
.value();
66 bool Writer::WriteBlob(const void *buffer
, size_t size
) {
69 const char* char_buffer
= static_cast<const char*>(buffer
);
70 int ret
= file_
.WriteAtCurrentPos(char_buffer
, size
);
71 if (ret
!= static_cast<int>(size
)) {
72 LOG(ERROR
) << "Failed to write " << size
<< " bytes.";
78 bool Writer::CollectMessageTypes() {
79 for (size_t i
= 0; i
< messages_
->size(); ++i
) {
80 uint32_t type
= (*messages_
)[i
]->type();
81 if (!MessageNames::GetInstance()->TypeExists(type
)) {
82 LOG(ERROR
) << "Unknown message type: " << type
;
90 bool Writer::WriteHeader() {
92 if (messages_
->size() > UINT_MAX
)
94 header
.magic
= FileHeader::kMagicValue
;
95 header
.version
= FileHeader::kCurrentVersion
;
96 header
.message_count
= messages_
->size();
97 header
.name_count
= types_
.size();
98 if (!WriteBlob(&header
, sizeof(FileHeader
)))
103 bool Writer::WriteMessages() {
104 for (size_t i
= 0; i
< messages_
->size(); ++i
) {
105 IPC::Message
* message
= (*messages_
)[i
];
106 if (!WriteBlob(message
->data(), message
->size()))
112 bool Writer::WriteNameTable() {
113 size_t string_table_offset
= 0;
114 NameTableEntry entry
;
116 for (TypesSet::iterator it
= types_
.begin(); it
!= types_
.end(); ++it
) {
117 if (string_table_offset
> UINT_MAX
)
120 entry
.string_table_offset
= string_table_offset
;
121 if (!WriteBlob(&entry
, sizeof(NameTableEntry
)))
123 const std::string
& name
= MessageNames::GetInstance()->TypeToName(*it
);
124 string_table_offset
+= name
.length() + 1;
129 bool Writer::WriteStringTable() {
130 for (TypesSet::iterator it
= types_
.begin(); it
!= types_
.end(); ++it
) {
131 const std::string
& name
= MessageNames::GetInstance()->TypeToName(*it
);
132 if (!WriteBlob(name
.c_str(), name
.length() + 1))
138 bool Writer::Write(const MessageVector
& messages
) {
139 messages_
= &messages
;
143 if (!CollectMessageTypes())
147 if (!WriteMessages())
149 if (!WriteNameTable())
151 if (!WriteStringTable())
159 bool MessageFile::Write(const base::FilePath
& path
,
160 const MessageVector
& messages
) {
162 return writer
.Write(messages
);
165 } // namespace ipc_fuzzer