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 base::FilePath::StringType output_file_name
;
114 if (args
.size() < 2) {
118 output_file_name
= args
[1];
121 ipc_fuzzer::MessageVector input_message_vector
;
122 for (const base::FilePath::StringType
& name
: base::SplitString(
123 args
[0], base::FilePath::StringType(1, ','),
124 base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
)) {
125 ipc_fuzzer::MessageVector message_vector
;
126 if (!ipc_fuzzer::MessageFile::Read(base::FilePath(name
), &message_vector
))
128 input_message_vector
.insert(input_message_vector
.end(),
129 message_vector
.begin(), message_vector
.end());
130 message_vector
.weak_clear();
133 bool has_indices
= cmd
->HasSwitch(kInSwitch
);
134 std::vector
<bool> indices
;
137 indices
.resize(input_message_vector
.size(), false);
138 for (const std::string
& cur
: base::SplitString(
139 cmd
->GetSwitchValueASCII(kInSwitch
), ",", base::TRIM_WHITESPACE
,
140 base::SPLIT_WANT_ALL
)) {
141 int index
= atoi(cur
.c_str());
142 if (index
>= 0 && static_cast<size_t>(index
) < indices
.size())
143 indices
[index
] = true;
147 ipc_fuzzer::MessageVector output_message_vector
;
148 std::vector
<size_t> remap_vector
;
150 for (size_t i
= 0; i
< input_message_vector
.size(); ++i
) {
151 bool valid
= (i
>= start_index
&& i
< end_index
);
152 if (valid
&& has_regexp
) {
153 valid
= MessageMatches(input_message_vector
[i
], filter_pattern
);
155 if (valid
&& has_indices
) {
158 if (valid
!= invert
) {
159 output_message_vector
.push_back(input_message_vector
[i
]);
160 remap_vector
.push_back(i
);
161 input_message_vector
[i
] = NULL
;
166 for (size_t i
= 0; i
< output_message_vector
.size(); ++i
) {
167 std::cout
<< remap_vector
[i
] << ". "
168 << MessageName(output_message_vector
[i
]) << "\n";
171 if (!ipc_fuzzer::MessageFile::Write(
172 base::FilePath(output_file_name
), output_message_vector
)) {