1 // Copyright 2014 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.
11 #include "base/command_line.h"
12 #include "base/strings/string_split.h"
13 #include "third_party/re2/re2/re2.h"
14 #include "tools/ipc_fuzzer/message_lib/message_file.h"
15 #include "tools/ipc_fuzzer/message_lib/message_names.h"
19 const char kDumpSwitch
[] = "dump";
20 const char kDumpSwitchHelp
[] =
21 "dump human-readable form to stdout instead of copying.";
23 const char kEndSwitch
[] = "end";
24 const char kEndSwitchHelp
[] =
25 "output messages before |m|th message in file (exclusive).";
27 const char kHelpSwitch
[] = "help";
28 const char kHelpSwitchHelp
[] =
29 "display this message.";
31 const char kInSwitch
[] = "in";
32 const char kInSwitchHelp
[] =
33 "output only the messages at the specified positions in the file.";
35 const char kInvertSwitch
[] = "invert";
36 const char kInvertSwitchHelp
[] =
37 "output messages NOT meeting above criteria.";
39 const char kRegexpSwitch
[] = "regexp";
40 const char kRegexpSwitchHelp
[] =
41 "output messages matching regular expression |x|.";
43 const char kStartSwitch
[] = "start";
44 const char kStartSwitchHelp
[] =
45 "output messages after |n|th message in file (inclusive).";
48 std::cerr
<< "ipc_message_util: Concatenate all |infile| message files and "
49 << "copy a subset of the result to |outfile|.\n";
51 std::cerr
<< "Usage:\n"
52 << " ipc_message_util"
53 << " [--" << kStartSwitch
<< "=n]"
54 << " [--" << kEndSwitch
<< "=m]"
55 << " [--" << kInSwitch
<< "=i[,j,...]]"
56 << " [--" << kRegexpSwitch
<< "=x]"
57 << " [--" << kInvertSwitch
<< "]"
58 << " [--" << kDumpSwitch
<< "]"
59 << " [--" << kHelpSwitch
<< "]"
60 << " infile,infile,... [outfile]\n";
62 std::cerr
<< " --" << kStartSwitch
<< " - " << kStartSwitchHelp
<< "\n"
63 << " --" << kEndSwitch
<< " - " << kEndSwitchHelp
<< "\n"
64 << " --" << kInSwitch
<< " - " << kInSwitchHelp
<< "\n"
65 << " --" << kRegexpSwitch
<< " - " << kRegexpSwitchHelp
<< "\n"
66 << " --" << kInvertSwitch
<< " - " << kInvertSwitchHelp
<< "\n"
67 << " --" << kDumpSwitch
<< " - " << kDumpSwitchHelp
<< "\n"
68 << " --" << kHelpSwitch
<< " - " << kHelpSwitchHelp
<< "\n";
71 std::string
MessageName(const IPC::Message
* msg
) {
72 return ipc_fuzzer::MessageNames::GetInstance()->TypeToName(msg
->type());
75 bool MessageMatches(const IPC::Message
* msg
, const RE2
& pattern
) {
76 return RE2::FullMatch(MessageName(msg
), pattern
);
81 int main(int argc
, char** argv
) {
82 base::CommandLine::Init(argc
, argv
);
83 base::CommandLine
* cmd
= base::CommandLine::ForCurrentProcess();
84 base::CommandLine::StringVector args
= cmd
->GetArgs();
86 if (args
.size() < 1 || args
.size() > 2 || cmd
->HasSwitch(kHelpSwitch
)) {
91 size_t start_index
= 0;
92 if (cmd
->HasSwitch(kStartSwitch
)) {
93 int temp
= atoi(cmd
->GetSwitchValueASCII(kStartSwitch
).c_str());
95 start_index
= static_cast<size_t>(temp
);
98 size_t end_index
= INT_MAX
;
99 if (cmd
->HasSwitch(kEndSwitch
)) {
100 int temp
= atoi(cmd
->GetSwitchValueASCII(kEndSwitch
).c_str());
102 end_index
= static_cast<size_t>(temp
);
105 bool has_regexp
= cmd
->HasSwitch(kRegexpSwitch
);
106 RE2
filter_pattern(cmd
->GetSwitchValueASCII(kRegexpSwitch
));
108 bool invert
= cmd
->HasSwitch(kInvertSwitch
);
109 bool perform_dump
= cmd
->HasSwitch(kDumpSwitch
);
111 std::vector
<base::FilePath::StringType
> input_file_names
;
112 base::FilePath::StringType output_file_name
;
113 base::SplitString(args
[0], ',', &input_file_names
);
116 if (args
.size() < 2) {
120 output_file_name
= args
[1];
123 ipc_fuzzer::MessageVector input_message_vector
;
124 for (std::vector
<base::FilePath::StringType
>::iterator
125 it
= input_file_names
.begin(); it
!= input_file_names
.end(); ++it
) {
126 ipc_fuzzer::MessageVector message_vector
;
127 if (!ipc_fuzzer::MessageFile::Read(base::FilePath(*it
), &message_vector
))
129 input_message_vector
.insert(input_message_vector
.end(),
130 message_vector
.begin(), message_vector
.end());
131 message_vector
.weak_clear();
134 bool has_indices
= cmd
->HasSwitch(kInSwitch
);
135 std::vector
<bool> indices
;
138 indices
.resize(input_message_vector
.size(), false);
139 std::vector
<std::string
> index_strings
;
140 base::SplitString(cmd
->GetSwitchValueASCII(kInSwitch
), ',', &index_strings
);
141 for (std::vector
<std::string
>::iterator it
= index_strings
.begin();
142 it
!= index_strings
.end(); ++it
) {
143 int index
= atoi(it
->c_str());
144 if (index
>= 0 && static_cast<size_t>(index
) < indices
.size())
145 indices
[index
] = true;
149 ipc_fuzzer::MessageVector output_message_vector
;
150 std::vector
<size_t> remap_vector
;
152 for (size_t i
= 0; i
< input_message_vector
.size(); ++i
) {
153 bool valid
= (i
>= start_index
&& i
< end_index
);
154 if (valid
&& has_regexp
) {
155 valid
= MessageMatches(input_message_vector
[i
], filter_pattern
);
157 if (valid
&& has_indices
) {
160 if (valid
!= invert
) {
161 output_message_vector
.push_back(input_message_vector
[i
]);
162 remap_vector
.push_back(i
);
163 input_message_vector
[i
] = NULL
;
168 for (size_t i
= 0; i
< output_message_vector
.size(); ++i
) {
169 std::cout
<< remap_vector
[i
] << ". "
170 << MessageName(output_message_vector
[i
]) << "\n";
173 if (!ipc_fuzzer::MessageFile::Write(
174 base::FilePath(output_file_name
), output_message_vector
)) {