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

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

Issue 106163003: Refactor IPC fuzzer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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 <list>
7
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/posix/global_descriptors.h"
15 #include "base/stl_util.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 void SendNextMessage();
53
54 scoped_ptr<IPC::ChannelProxy> channel_;
55 base::MessageLoop main_loop_;
56 base::Thread io_thread_;
57 base::WaitableEvent shutdown_event_;
58 scoped_ptr<base::Timer> timer_;
59 scoped_ptr<base::MemoryMappedFile> testcase_map_;
60 std::list<IPC::Message*> messages_;
61
62 DISALLOW_COPY_AND_ASSIGN(IpcFuzzerProcess);
63 };
64
65 IpcFuzzerProcess::IpcFuzzerProcess()
66 : main_loop_(base::MessageLoop::TYPE_DEFAULT),
67 io_thread_("Chrome_ChildIOThread"),
68 shutdown_event_(true, false) {
69 }
70
71 IpcFuzzerProcess::~IpcFuzzerProcess() {
72 channel_.reset();
73 STLDeleteElements(&messages_);
74 }
75
76 void IpcFuzzerProcess::Initialize(int argc, const char **argv) {
77 CommandLine::Init(argc, argv);
78
79 // Log to default destination.
80 logging::SetMinLogLevel(logging::LOG_ERROR);
81 logging::InitLogging(logging::LoggingSettings());
82
83 io_thread_.StartWithOptions(
84 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
85
86 #if defined(OS_POSIX)
87 base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
88 g_fds->Set(kPrimaryIPCChannel,
89 kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
90 #endif
91 }
92
93 void IpcFuzzerProcess::OpenChannel() {
94 std::string channel_name =
95 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
96 switches::kProcessChannelID);
97
98 channel_.reset(
99 new IPC::ChannelProxy(channel_name,
100 IPC::Channel::MODE_CLIENT,
101 this,
102 io_thread_.message_loop_proxy()));
103 }
104
105 bool IpcFuzzerProcess::ExtractMessages(const char *data, size_t len) {
106 const char* end = data + len;
107
108 while (data < end) {
109 const char* message_tail = IPC::Message::FindNext(data, end);
110 if (!message_tail)
111 break;
112
113 size_t len = message_tail - data;
114 if (len > INT_MAX) {
115 LOG(ERROR) << "Message too large";
116 break;
117 }
118
119 IPC::Message* message = new IPC::Message(data, len);
120 messages_.push_back(message);
121 data = message_tail;
122 }
123
124 if (data < end) {
125 unsigned long left = end - data;
126 LOG(ERROR) << left << " bytes left while extracting messages";
127 return false;
128 }
129
130 return true;
131 }
132
133 bool IpcFuzzerProcess::OpenTestcase() {
134 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
135
136 if (!command_line.HasSwitch(switches::kIpcFuzzerTestcase)) {
137 LOG(ERROR) << "No IPC fuzzer testcase specified";
138 return false;
139 }
140
141 base::FilePath path =
142 command_line.GetSwitchValuePath(switches::kIpcFuzzerTestcase);
143 testcase_map_.reset(new base::MemoryMappedFile());
144 if (!testcase_map_->Initialize(path)) {
145 LOG(ERROR) << "Failed to map testcase: " << path.value();
146 return false;
147 }
148
149 const char* data = reinterpret_cast<const char *>(testcase_map_->data());
150 size_t len = testcase_map_->length();
151
152 return ExtractMessages(data, len);
153 }
154
155 void IpcFuzzerProcess::SendNextMessage() {
156 if (messages_.empty()) {
157 base::MessageLoop::current()->Quit();
158 return;
159 }
160
161 IPC::Message* message = messages_.front();
162 messages_.pop_front();
163
164 channel_->Send(message);
165 }
166
167 void IpcFuzzerProcess::StartSendingMessages() {
168 timer_.reset(new base::Timer(false, true));
169 timer_->Start(FROM_HERE,
170 base::TimeDelta::FromMilliseconds(1),
171 base::Bind(&IpcFuzzerProcess::SendNextMessage,
172 base::Unretained(this)));
173 }
174
175 bool IpcFuzzerProcess::OnMessageReceived(const IPC::Message& msg) {
176 return true;
177 }
178
179 void IpcFuzzerProcess::OnChannelError() {
180 LOG(ERROR) << "Channel error, quitting";
181 base::MessageLoop::current()->Quit();
182 }
183
184 } // namespace
185
186 int main(int argc, const char **argv) {
187 IpcFuzzerProcess fuzzer;
188 fuzzer.Initialize(argc, argv);
189 fuzzer.OpenChannel();
190
191 if (!fuzzer.OpenTestcase())
192 return 0;
193
194 fuzzer.StartSendingMessages();
195
196 base::MessageLoop::current()->Run();
197 return 0;
198 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698