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

Side by Side Diff: ipc/ipc_fuzzing_tests.cc

Issue 155905: Separates ipc code from common (http://crbug.com/16829) (Closed)
Patch Set: Fixes reference to 'common_message_traits' it's actually 'common_param_traits' Created 11 years, 5 months 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
« no previous file with comments | « ipc/ipc_descriptors.h ('k') | ipc/ipc_logging.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 <stdio.h>
6 #include <iostream>
7 #include <string>
8 #include <sstream>
9
10 #include "base/message_loop.h"
11 #include "base/platform_thread.h"
12 #include "base/process_util.h"
13 #include "ipc/ipc_channel.h"
14 #include "ipc/ipc_channel_proxy.h"
15 #include "ipc/ipc_message_utils.h"
16 #include "ipc/ipc_tests.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "testing/multiprocess_func_list.h"
19
20 TEST(IPCMessageIntegrity, ReadBeyondBufferStr) {
21 //This was BUG 984408.
22 uint32 v1 = kuint32max - 1;
23 int v2 = 666;
24 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
25 EXPECT_TRUE(m.WriteInt(v1));
26 EXPECT_TRUE(m.WriteInt(v2));
27
28 void* iter = NULL;
29 std::string vs;
30 EXPECT_FALSE(m.ReadString(&iter, &vs));
31 }
32
33 TEST(IPCMessageIntegrity, ReadBeyondBufferWStr) {
34 //This was BUG 984408.
35 uint32 v1 = kuint32max - 1;
36 int v2 = 777;
37 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
38 EXPECT_TRUE(m.WriteInt(v1));
39 EXPECT_TRUE(m.WriteInt(v2));
40
41 void* iter = NULL;
42 std::wstring vs;
43 EXPECT_FALSE(m.ReadWString(&iter, &vs));
44 }
45
46 TEST(IPCMessageIntegrity, ReadBytesBadIterator) {
47 // This was BUG 1035467.
48 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
49 EXPECT_TRUE(m.WriteInt(1));
50 EXPECT_TRUE(m.WriteInt(2));
51
52 void* iter = NULL;
53 const char* data = NULL;
54 EXPECT_FALSE(m.ReadBytes(&iter, &data, sizeof(int)));
55 }
56
57 TEST(IPCMessageIntegrity, ReadVectorNegativeSize) {
58 // A slight variation of BUG 984408. Note that the pickling of vector<char>
59 // has a specialized template which is not vulnerable to this bug. So here
60 // try to hit the non-specialized case vector<P>.
61 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
62 EXPECT_TRUE(m.WriteInt(-1)); // This is the count of elements.
63 EXPECT_TRUE(m.WriteInt(1));
64 EXPECT_TRUE(m.WriteInt(2));
65 EXPECT_TRUE(m.WriteInt(3));
66
67 std::vector<double> vec;
68 void* iter = 0;
69 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
70 }
71
72 TEST(IPCMessageIntegrity, ReadVectorTooLarge1) {
73 // This was BUG 1006367. This is the large but positive length case. Again
74 // we try to hit the non-specialized case vector<P>.
75 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
76 EXPECT_TRUE(m.WriteInt(0x21000003)); // This is the count of elements.
77 EXPECT_TRUE(m.WriteInt64(1));
78 EXPECT_TRUE(m.WriteInt64(2));
79
80 std::vector<int64> vec;
81 void* iter = 0;
82 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
83 }
84
85 TEST(IPCMessageIntegrity, ReadVectorTooLarge2) {
86 // This was BUG 1006367. This is the large but positive with an additional
87 // integer overflow when computing the actual byte size. Again we try to hit
88 // the non-specialized case vector<P>.
89 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
90 EXPECT_TRUE(m.WriteInt(0x71000000)); // This is the count of elements.
91 EXPECT_TRUE(m.WriteInt64(1));
92 EXPECT_TRUE(m.WriteInt64(2));
93
94 std::vector<int64> vec;
95 void* iter = 0;
96 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
97 }
98
99 // We don't actually use the messages defined in this file, but we do this
100 // to get to the IPC macros.
101 #define MESSAGES_INTERNAL_FILE "ipc/ipc_sync_message_unittest.h"
102 #include "ipc/ipc_message_macros.h"
103
104 enum IPCMessageIds {
105 UNUSED_IPC_TYPE,
106 SERVER_FIRST_IPC_TYPE, // 1st Test message tag.
107 SERVER_SECOND_IPC_TYPE, // 2nd Test message tag.
108 SERVER_THIRD_IPC_TYPE, // 3rd Test message tag.
109 CLIENT_MALFORMED_IPC, // Sent to client if server detects bad message.
110 CLIENT_UNHANDLED_IPC // Sent to client if server detects unhanded IPC.
111 };
112
113 // Generic message class that is an int followed by a wstring.
114 class MsgClassIS : public IPC::MessageWithTuple< Tuple2<int, std::wstring> > {
115 public:
116 enum { ID = SERVER_FIRST_IPC_TYPE };
117 MsgClassIS(const int& arg1, const std::wstring& arg2)
118 : IPC::MessageWithTuple< Tuple2<int, std::wstring> >(
119 MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1, arg2)) {}
120 };
121
122 // Generic message class that is a wstring followed by an int.
123 class MsgClassSI : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
124 public:
125 enum { ID = SERVER_SECOND_IPC_TYPE };
126 MsgClassSI(const std::wstring& arg1, const int& arg2)
127 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
128 MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1, arg2)) {}
129 };
130
131 // Message to create a mutex in the IPC server, using the received name.
132 class MsgDoMutex : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
133 public:
134 enum { ID = SERVER_THIRD_IPC_TYPE };
135 MsgDoMutex(const std::wstring& mutex_name, const int& unused)
136 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
137 MSG_ROUTING_CONTROL, ID, MakeRefTuple(mutex_name, unused)) {}
138 };
139
140 class SimpleListener : public IPC::Channel::Listener {
141 public:
142 SimpleListener() : other_(NULL) {
143 }
144 void Init(IPC::Message::Sender* s) {
145 other_ = s;
146 }
147 protected:
148 IPC::Message::Sender* other_;
149 };
150
151 enum {
152 FUZZER_ROUTING_ID = 5
153 };
154
155 // The fuzzer server class. It runs in a child process and expects
156 // only two IPC calls; after that it exits the message loop which
157 // terminates the child process.
158 class FuzzerServerListener : public SimpleListener {
159 public:
160 FuzzerServerListener() : message_count_(2), pending_messages_(0) {
161 }
162 virtual void OnMessageReceived(const IPC::Message& msg) {
163 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
164 ++pending_messages_;
165 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg)
166 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
167 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
168 IPC_END_MESSAGE_MAP()
169 if (pending_messages_) {
170 // Probably a problem de-serializing the message.
171 ReplyMsgNotHandled(msg.type());
172 }
173 }
174 }
175
176 private:
177 void OnMsgClassISMessage(int value, const std::wstring& text) {
178 UseData(MsgClassIS::ID, value, text);
179 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value);
180 Cleanup();
181 }
182
183 void OnMsgClassSIMessage(const std::wstring& text, int value) {
184 UseData(MsgClassSI::ID, value, text);
185 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value);
186 Cleanup();
187 }
188
189 bool RoundtripAckReply(int routing, int type_id, int reply) {
190 IPC::Message* message = new IPC::Message(routing, type_id,
191 IPC::Message::PRIORITY_NORMAL);
192 message->WriteInt(reply + 1);
193 message->WriteInt(reply);
194 return other_->Send(message);
195 }
196
197 void Cleanup() {
198 --message_count_;
199 --pending_messages_;
200 if (0 == message_count_)
201 MessageLoop::current()->Quit();
202 }
203
204 void ReplyMsgNotHandled(int type_id) {
205 RoundtripAckReply(FUZZER_ROUTING_ID, CLIENT_UNHANDLED_IPC, type_id);
206 Cleanup();
207 }
208
209 void UseData(int caller, int value, const std::wstring& text) {
210 std::wostringstream wos;
211 wos << L"IPC fuzzer:" << caller << " [" << value << L" " << text << L"]\n";
212 std::wstring output = wos.str();
213 LOG(WARNING) << output.c_str();
214 };
215
216 int message_count_;
217 int pending_messages_;
218 };
219
220 class FuzzerClientListener : public SimpleListener {
221 public:
222 FuzzerClientListener() : last_msg_(NULL) {
223 }
224
225 virtual void OnMessageReceived(const IPC::Message& msg) {
226 last_msg_ = new IPC::Message(msg);
227 MessageLoop::current()->Quit();
228 }
229
230 bool ExpectMessage(int value, int type_id) {
231 if (!MsgHandlerInternal(type_id))
232 return false;
233 int msg_value1 = 0;
234 int msg_value2 = 0;
235 void* iter = NULL;
236 if (!last_msg_->ReadInt(&iter, &msg_value1))
237 return false;
238 if (!last_msg_->ReadInt(&iter, &msg_value2))
239 return false;
240 if ((msg_value2 + 1) != msg_value1)
241 return false;
242 if (msg_value2 != value)
243 return false;
244
245 delete last_msg_;
246 last_msg_ = NULL;
247 return true;
248 }
249
250 bool ExpectMsgNotHandled(int type_id) {
251 return ExpectMessage(type_id, CLIENT_UNHANDLED_IPC);
252 }
253
254 private:
255 bool MsgHandlerInternal(int type_id) {
256 MessageLoop::current()->Run();
257 if (NULL == last_msg_)
258 return false;
259 if (FUZZER_ROUTING_ID != last_msg_->routing_id())
260 return false;
261 return (type_id == last_msg_->type());
262 };
263
264 IPC::Message* last_msg_;
265 };
266
267 // Runs the fuzzing server child mode. Returns when the preset number
268 // of messages have been received.
269 MULTIPROCESS_TEST_MAIN(RunFuzzServer) {
270 MessageLoopForIO main_message_loop;
271 FuzzerServerListener listener;
272 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &listener);
273 chan.Connect();
274 listener.Init(&chan);
275 MessageLoop::current()->Run();
276 return 0;
277 }
278
279 class IPCFuzzingTest : public IPCChannelTest {
280 };
281
282 // This test makes sure that the FuzzerClientListener and FuzzerServerListener
283 // are working properly by generating two well formed IPC calls.
284 TEST_F(IPCFuzzingTest, SanityTest) {
285 FuzzerClientListener listener;
286 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
287 &listener);
288 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
289 ASSERT_TRUE(server_process);
290 PlatformThread::Sleep(1000);
291 ASSERT_TRUE(chan.Connect());
292 listener.Init(&chan);
293
294 IPC::Message* msg = NULL;
295 int value = 43;
296 msg = new MsgClassIS(value, L"expect 43");
297 chan.Send(msg);
298 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
299
300 msg = new MsgClassSI(L"expect 44", ++value);
301 chan.Send(msg);
302 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
303
304 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
305 base::CloseProcessHandle(server_process);
306 }
307
308 // This test uses a payload that is smaller than expected.
309 // This generates an error while unpacking the IPC buffer which in
310 // In debug this triggers an assertion and in release it is ignored(!!). Right
311 // after we generate another valid IPC to make sure framing is working
312 // properly.
313 #ifdef NDEBUG
314 TEST_F(IPCFuzzingTest, MsgBadPayloadShort) {
315 FuzzerClientListener listener;
316 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
317 &listener);
318 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
319 ASSERT_TRUE(server_process);
320 PlatformThread::Sleep(1000);
321 ASSERT_TRUE(chan.Connect());
322 listener.Init(&chan);
323
324 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
325 IPC::Message::PRIORITY_NORMAL);
326 msg->WriteInt(666);
327 chan.Send(msg);
328 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID));
329
330 msg = new MsgClassSI(L"expect one", 1);
331 chan.Send(msg);
332 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID));
333
334 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
335 base::CloseProcessHandle(server_process);
336 }
337 #endif // NDEBUG
338
339 // This test uses a payload that has too many arguments, but so the payload
340 // size is big enough so the unpacking routine does not generate an error as
341 // in the case of MsgBadPayloadShort test.
342 // This test does not pinpoint a flaw (per se) as by design we don't carry
343 // type information on the IPC message.
344 TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
345 FuzzerClientListener listener;
346 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
347 &listener);
348 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
349 ASSERT_TRUE(server_process);
350 PlatformThread::Sleep(1000);
351 ASSERT_TRUE(chan.Connect());
352 listener.Init(&chan);
353
354 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
355 IPC::Message::PRIORITY_NORMAL);
356 msg->WriteWString(L"d");
357 msg->WriteInt(0);
358 msg->WriteInt(0x65); // Extra argument.
359
360 chan.Send(msg);
361 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID));
362
363 // Now send a well formed message to make sure the receiver wasn't
364 // thrown out of sync by the extra argument.
365 msg = new MsgClassIS(3, L"expect three");
366 chan.Send(msg);
367 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID));
368
369 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
370 base::CloseProcessHandle(server_process);
371 }
372
373 // This class is for testing the IPC_BEGIN_MESSAGE_MAP_EX macros.
374 class ServerMacroExTest {
375 public:
376 ServerMacroExTest() : unhandled_msgs_(0) {
377 }
378 virtual bool OnMessageReceived(const IPC::Message& msg) {
379 bool msg_is_ok = false;
380 IPC_BEGIN_MESSAGE_MAP_EX(ServerMacroExTest, msg, msg_is_ok)
381 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
382 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
383 IPC_MESSAGE_UNHANDLED(++unhandled_msgs_)
384 IPC_END_MESSAGE_MAP_EX()
385 return msg_is_ok;
386 }
387
388 int unhandled_msgs() const {
389 return unhandled_msgs_;
390 }
391
392 private:
393 void OnMsgClassISMessage(int value, const std::wstring& text) {
394 }
395 void OnMsgClassSIMessage(const std::wstring& text, int value) {
396 }
397
398 int unhandled_msgs_;
399 };
400
401 TEST_F(IPCFuzzingTest, MsgMapExMacro) {
402 IPC::Message* msg = NULL;
403 ServerMacroExTest server;
404
405 // Test the regular messages.
406 msg = new MsgClassIS(3, L"text3");
407 EXPECT_TRUE(server.OnMessageReceived(*msg));
408 delete msg;
409 msg = new MsgClassSI(L"text2", 2);
410 EXPECT_TRUE(server.OnMessageReceived(*msg));
411 delete msg;
412
413 #ifdef NDEBUG
414 // Test a bad message.
415 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
416 IPC::Message::PRIORITY_NORMAL);
417 msg->WriteInt(2);
418 EXPECT_FALSE(server.OnMessageReceived(*msg));
419 delete msg;
420
421 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
422 IPC::Message::PRIORITY_NORMAL);
423 msg->WriteInt(0x64);
424 msg->WriteInt(0x32);
425 EXPECT_FALSE(server.OnMessageReceived(*msg));
426 delete msg;
427
428 EXPECT_EQ(0, server.unhandled_msgs());
429 #endif
430 }
OLDNEW
« no previous file with comments | « ipc/ipc_descriptors.h ('k') | ipc/ipc_logging.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698