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

Side by Side Diff: tools/ipc_fuzzer/ipc_fuzzer_main.cc

Issue 18254010: IPC fuzzer child process component (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments from jochen 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 #include <stdio.h>
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/memory_mapped_file.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/posix/global_descriptors.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/threading/thread.h"
18 #include "base/timer/timer.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "ipc/ipc_channel_proxy.h"
21 #include "ipc/ipc_descriptors.h"
22 #include "ipc/ipc_listener.h"
23 #include "ipc/ipc_message.h"
24 #include "ipc/ipc_platform_file.h"
25 #include "ipc/ipc_switches.h"
26
27 namespace {
28
29 class IpcFuzzerProcess : public IPC::Listener {
30 public:
31 IpcFuzzerProcess();
32 virtual ~IpcFuzzerProcess();
33
34 // Set up command line, logging, IO thread.
35 void Initialize(int argc, const char **argv);
36
37 // Open a channel to the browser process. It will think we are a renderer.
38 void OpenChannel();
39
40 // Extract messages from a file specified by --ipc-fuzzer-testcase=.
41 bool OpenTestcase();
42
43 // Trigger the sending of messages to the browser.
44 void StartSendingMessages();
45
46 // IPC::Listener implementation.
47 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
48 virtual void OnChannelError() OVERRIDE;
49
50 private:
51 bool ExtractMessages(const char *data, size_t len);
52 IPC::Message* GetNextMessage();
53 void SendNextMessage();
54
55 scoped_ptr<IPC::ChannelProxy> channel_;
56 base::MessageLoop main_loop_;
57 base::Thread io_thread_;
58 base::WaitableEvent shutdown_event_;
59 scoped_ptr<base::Timer> timer_;
60 scoped_ptr<base::MemoryMappedFile> testcase_map_;
61 std::vector<scoped_ptr<IPC::Message>> messages_;
Tom Sepez 2013/11/26 21:30:44 nit: > >
aedla 2013/11/27 19:24:51 Moved to std::list<IPC::Message*>.
62 size_t current_message_;
63
64 DISALLOW_COPY_AND_ASSIGN(IpcFuzzerProcess);
65 };
66
67 IpcFuzzerProcess::IpcFuzzerProcess()
68 : main_loop_(base::MessageLoop::TYPE_DEFAULT),
69 io_thread_("Chrome_ChildIOThread"),
70 shutdown_event_(true, false),
71 current_message_(0) {
72 }
73
74 IpcFuzzerProcess::~IpcFuzzerProcess() {
75 channel_.reset();
76 }
77
78 void IpcFuzzerProcess::Initialize(int argc, const char **argv) {
79 CommandLine::Init(argc, argv);
80
81 // Log to default destination.
82 logging::SetMinLogLevel(logging::LOG_ERROR);
83 logging::InitLogging(logging::LoggingSettings());
84
85 io_thread_.StartWithOptions(
86 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
87
88 #if defined(OS_POSIX)
89 base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
90 g_fds->Set(kPrimaryIPCChannel,
91 kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
92 #endif
93 }
94
95 void IpcFuzzerProcess::OpenChannel() {
96 std::string channel_name =
97 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
98 switches::kProcessChannelID);
99
100 channel_.reset(
101 new IPC::ChannelProxy(channel_name,
102 IPC::Channel::MODE_CLIENT,
103 this,
104 io_thread_.message_loop_proxy()));
105 }
106
107 bool IpcFuzzerProcess::ExtractMessages(const char *data, size_t len) {
108 const char* end = data + len;
109
110 while (data < end) {
111 const char* message_tail = IPC::Message::FindNext(data, end);
112 if (!message_tail)
113 break;
114
115 size_t len = message_tail - data;
116 if (len > INT_MAX)
117 break;
Tom Sepez 2013/11/26 18:25:05 nit: do you want to do something more extreme then
aedla 2013/11/27 19:24:51 Yeah, added an error message here. It previously f
118
119 IPC::Message* message = new IPC::Message(data, len);
120 data = message_tail;
121
122 messages_.resize(messages_.size() + 1);
123 messages_.back().reset(message);
124 }
125
126 if (data < end) {
127 unsigned long left = end - data;
128 LOG(ERROR) << left << " bytes left while extracting messages";
129 return false;
130 }
131
132 return true;
133 }
134
135 bool IpcFuzzerProcess::OpenTestcase() {
136 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
137
138 if (!command_line.HasSwitch(switches::kIpcFuzzerTestcase)) {
139 LOG(ERROR) << "No IPC fuzzer testcase specified";
140 return false;
141 }
142
143 base::FilePath path =
144 command_line.GetSwitchValuePath(switches::kIpcFuzzerTestcase);
145 testcase_map_.reset(new base::MemoryMappedFile());
146 if (!testcase_map_->Initialize(path)) {
147 LOG(ERROR) << "Failed to map testcase: " << path.value();
148 return false;
149 }
150
151 const char* data = reinterpret_cast<const char *>(testcase_map_->data());
152 size_t len = testcase_map_->length();
153
154 return ExtractMessages(data, len);
155 }
156
157 IPC::Message* IpcFuzzerProcess::GetNextMessage() {
158 if (current_message_ == messages_.size())
159 return NULL;
160
161 IPC::Message* const_message = messages_[current_message_].get();
162 IPC::Message* message = new IPC::Message(*const_message);
Tom Sepez 2013/11/26 18:25:05 nit: might be nice if we didn't have to duplicate
aedla 2013/11/27 19:24:51 Done.
163 ++current_message_;
164
165 return message;
166 }
167
168 void IpcFuzzerProcess::SendNextMessage() {
169 IPC::Message* message = GetNextMessage();
170 if (!message) {
171 base::MessageLoop::current()->Quit();
172 return;
173 }
174
175 channel_->Send(message);
176 }
177
178 void IpcFuzzerProcess::StartSendingMessages() {
179 timer_.reset(new base::Timer(false, true));
180 timer_->Start(FROM_HERE,
181 base::TimeDelta::FromMilliseconds(1),
182 base::Bind(&IpcFuzzerProcess::SendNextMessage,
183 base::Unretained(this)));
184 }
185
186 bool IpcFuzzerProcess::OnMessageReceived(const IPC::Message& msg) {
187 return true;
188 }
189
190 void IpcFuzzerProcess::OnChannelError() {
191 LOG(ERROR) << "Channel error, quitting";
192 base::MessageLoop::current()->Quit();
193 }
194
195 } // namespace
196
197 int main(int argc, const char **argv) {
198 IpcFuzzerProcess fuzzer;
199 fuzzer.Initialize(argc, argv);
200 fuzzer.OpenChannel();
201
202 if (!fuzzer.OpenTestcase())
203 return 0;
204
205 fuzzer.StartSendingMessages();
206
207 base::MessageLoop::current()->Run();
208 return 0;
209 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698