blob: f94e170dc56ee97367acaadff3c6bb9323dc725a [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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.
initial.commit09911bf2008-07-26 23:55:294
initial.commit09911bf2008-07-26 23:55:295#include <stdio.h>
initial.commit09911bf2008-07-26 23:55:296#include <string>
7#include <sstream>
8
[email protected]514411fc2008-12-10 22:28:119#include "base/message_loop.h"
[email protected]d4651ff2008-12-02 16:51:5810#include "base/platform_thread.h"
11#include "base/process_util.h"
[email protected]946d1b22009-07-22 23:57:2112#include "ipc/ipc_channel.h"
13#include "ipc/ipc_channel_proxy.h"
14#include "ipc/ipc_message_utils.h"
15#include "ipc/ipc_tests.h"
initial.commit09911bf2008-07-26 23:55:2916#include "testing/gtest/include/gtest/gtest.h"
[email protected]95cb7fb92008-12-09 22:00:4717#include "testing/multiprocess_func_list.h"
initial.commit09911bf2008-07-26 23:55:2918
19TEST(IPCMessageIntegrity, ReadBeyondBufferStr) {
20 //This was BUG 984408.
21 uint32 v1 = kuint32max - 1;
22 int v2 = 666;
23 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
24 EXPECT_TRUE(m.WriteInt(v1));
25 EXPECT_TRUE(m.WriteInt(v2));
26
27 void* iter = NULL;
28 std::string vs;
29 EXPECT_FALSE(m.ReadString(&iter, &vs));
30}
31
32TEST(IPCMessageIntegrity, ReadBeyondBufferWStr) {
33 //This was BUG 984408.
34 uint32 v1 = kuint32max - 1;
35 int v2 = 777;
36 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
37 EXPECT_TRUE(m.WriteInt(v1));
38 EXPECT_TRUE(m.WriteInt(v2));
39
40 void* iter = NULL;
41 std::wstring vs;
42 EXPECT_FALSE(m.ReadWString(&iter, &vs));
43}
44
45TEST(IPCMessageIntegrity, ReadBytesBadIterator) {
46 // This was BUG 1035467.
47 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
48 EXPECT_TRUE(m.WriteInt(1));
49 EXPECT_TRUE(m.WriteInt(2));
50
51 void* iter = NULL;
52 const char* data = NULL;
[email protected]26d2f472010-03-30 23:52:2453 EXPECT_TRUE(m.ReadBytes(&iter, &data, sizeof(int)));
initial.commit09911bf2008-07-26 23:55:2954}
55
56TEST(IPCMessageIntegrity, ReadVectorNegativeSize) {
57 // A slight variation of BUG 984408. Note that the pickling of vector<char>
58 // has a specialized template which is not vulnerable to this bug. So here
59 // try to hit the non-specialized case vector<P>.
60 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
61 EXPECT_TRUE(m.WriteInt(-1)); // This is the count of elements.
62 EXPECT_TRUE(m.WriteInt(1));
63 EXPECT_TRUE(m.WriteInt(2));
64 EXPECT_TRUE(m.WriteInt(3));
65
66 std::vector<double> vec;
67 void* iter = 0;
68 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
69}
70
71TEST(IPCMessageIntegrity, ReadVectorTooLarge1) {
72 // This was BUG 1006367. This is the large but positive length case. Again
73 // we try to hit the non-specialized case vector<P>.
74 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
75 EXPECT_TRUE(m.WriteInt(0x21000003)); // This is the count of elements.
76 EXPECT_TRUE(m.WriteInt64(1));
77 EXPECT_TRUE(m.WriteInt64(2));
78
79 std::vector<int64> vec;
80 void* iter = 0;
81 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
82}
83
84TEST(IPCMessageIntegrity, ReadVectorTooLarge2) {
85 // This was BUG 1006367. This is the large but positive with an additional
86 // integer overflow when computing the actual byte size. Again we try to hit
87 // the non-specialized case vector<P>.
88 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
89 EXPECT_TRUE(m.WriteInt(0x71000000)); // This is the count of elements.
90 EXPECT_TRUE(m.WriteInt64(1));
91 EXPECT_TRUE(m.WriteInt64(2));
92
93 std::vector<int64> vec;
94 void* iter = 0;
95 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
96}
97
[email protected]f91cb992009-02-04 20:10:1298// We don't actually use the messages defined in this file, but we do this
99// to get to the IPC macros.
[email protected]946d1b22009-07-22 23:57:21100#define MESSAGES_INTERNAL_FILE "ipc/ipc_sync_message_unittest.h"
101#include "ipc/ipc_message_macros.h"
initial.commit09911bf2008-07-26 23:55:29102
103enum IPCMessageIds {
104 UNUSED_IPC_TYPE,
105 SERVER_FIRST_IPC_TYPE, // 1st Test message tag.
106 SERVER_SECOND_IPC_TYPE, // 2nd Test message tag.
107 SERVER_THIRD_IPC_TYPE, // 3rd Test message tag.
108 CLIENT_MALFORMED_IPC, // Sent to client if server detects bad message.
109 CLIENT_UNHANDLED_IPC // Sent to client if server detects unhanded IPC.
110};
111
112// Generic message class that is an int followed by a wstring.
113class MsgClassIS : public IPC::MessageWithTuple< Tuple2<int, std::wstring> > {
114 public:
115 enum { ID = SERVER_FIRST_IPC_TYPE };
116 MsgClassIS(const int& arg1, const std::wstring& arg2)
117 : IPC::MessageWithTuple< Tuple2<int, std::wstring> >(
[email protected]c2fe31542009-05-20 18:24:14118 MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1, arg2)) {}
initial.commit09911bf2008-07-26 23:55:29119};
120
121// Generic message class that is a wstring followed by an int.
122class MsgClassSI : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
123 public:
124 enum { ID = SERVER_SECOND_IPC_TYPE };
125 MsgClassSI(const std::wstring& arg1, const int& arg2)
126 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
[email protected]c2fe31542009-05-20 18:24:14127 MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1, arg2)) {}
initial.commit09911bf2008-07-26 23:55:29128};
129
130// Message to create a mutex in the IPC server, using the received name.
131class MsgDoMutex : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
132 public:
133 enum { ID = SERVER_THIRD_IPC_TYPE };
134 MsgDoMutex(const std::wstring& mutex_name, const int& unused)
135 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
[email protected]c2fe31542009-05-20 18:24:14136 MSG_ROUTING_CONTROL, ID, MakeRefTuple(mutex_name, unused)) {}
initial.commit09911bf2008-07-26 23:55:29137};
138
139class SimpleListener : public IPC::Channel::Listener {
140 public:
141 SimpleListener() : other_(NULL) {
142 }
143 void Init(IPC::Message::Sender* s) {
144 other_ = s;
145 }
146 protected:
147 IPC::Message::Sender* other_;
148};
149
150enum {
151 FUZZER_ROUTING_ID = 5
152};
153
154// The fuzzer server class. It runs in a child process and expects
155// only two IPC calls; after that it exits the message loop which
156// terminates the child process.
157class FuzzerServerListener : public SimpleListener {
158 public:
159 FuzzerServerListener() : message_count_(2), pending_messages_(0) {
160 }
161 virtual void OnMessageReceived(const IPC::Message& msg) {
162 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
163 ++pending_messages_;
164 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg)
165 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
166 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
167 IPC_END_MESSAGE_MAP()
168 if (pending_messages_) {
169 // Probably a problem de-serializing the message.
170 ReplyMsgNotHandled(msg.type());
171 }
172 }
173 }
174
175 private:
176 void OnMsgClassISMessage(int value, const std::wstring& text) {
177 UseData(MsgClassIS::ID, value, text);
178 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value);
179 Cleanup();
180 }
181
182 void OnMsgClassSIMessage(const std::wstring& text, int value) {
183 UseData(MsgClassSI::ID, value, text);
184 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value);
185 Cleanup();
186 }
187
[email protected]7ee1a44c2010-07-23 14:18:59188 bool RoundtripAckReply(int routing, uint32 type_id, int reply) {
initial.commit09911bf2008-07-26 23:55:29189 IPC::Message* message = new IPC::Message(routing, type_id,
190 IPC::Message::PRIORITY_NORMAL);
191 message->WriteInt(reply + 1);
192 message->WriteInt(reply);
193 return other_->Send(message);
194 }
195
196 void Cleanup() {
197 --message_count_;
198 --pending_messages_;
199 if (0 == message_count_)
200 MessageLoop::current()->Quit();
201 }
202
[email protected]7ee1a44c2010-07-23 14:18:59203 void ReplyMsgNotHandled(uint32 type_id) {
initial.commit09911bf2008-07-26 23:55:29204 RoundtripAckReply(FUZZER_ROUTING_ID, CLIENT_UNHANDLED_IPC, type_id);
205 Cleanup();
206 }
207
208 void UseData(int caller, int value, const std::wstring& text) {
209 std::wostringstream wos;
210 wos << L"IPC fuzzer:" << caller << " [" << value << L" " << text << L"]\n";
211 std::wstring output = wos.str();
[email protected]d4651ff2008-12-02 16:51:58212 LOG(WARNING) << output.c_str();
initial.commit09911bf2008-07-26 23:55:29213 };
214
215 int message_count_;
216 int pending_messages_;
217};
218
219class FuzzerClientListener : public SimpleListener {
220 public:
221 FuzzerClientListener() : last_msg_(NULL) {
222 }
223
224 virtual void OnMessageReceived(const IPC::Message& msg) {
225 last_msg_ = new IPC::Message(msg);
226 MessageLoop::current()->Quit();
227 }
228
[email protected]7ee1a44c2010-07-23 14:18:59229 bool ExpectMessage(int value, uint32 type_id) {
initial.commit09911bf2008-07-26 23:55:29230 if (!MsgHandlerInternal(type_id))
231 return false;
232 int msg_value1 = 0;
233 int msg_value2 = 0;
234 void* iter = NULL;
235 if (!last_msg_->ReadInt(&iter, &msg_value1))
236 return false;
237 if (!last_msg_->ReadInt(&iter, &msg_value2))
238 return false;
239 if ((msg_value2 + 1) != msg_value1)
240 return false;
241 if (msg_value2 != value)
242 return false;
243
244 delete last_msg_;
245 last_msg_ = NULL;
246 return true;
247 }
248
[email protected]7ee1a44c2010-07-23 14:18:59249 bool ExpectMsgNotHandled(uint32 type_id) {
initial.commit09911bf2008-07-26 23:55:29250 return ExpectMessage(type_id, CLIENT_UNHANDLED_IPC);
251 }
252
253 private:
[email protected]7ee1a44c2010-07-23 14:18:59254 bool MsgHandlerInternal(uint32 type_id) {
initial.commit09911bf2008-07-26 23:55:29255 MessageLoop::current()->Run();
256 if (NULL == last_msg_)
257 return false;
258 if (FUZZER_ROUTING_ID != last_msg_->routing_id())
259 return false;
260 return (type_id == last_msg_->type());
261 };
262
263 IPC::Message* last_msg_;
264};
265
[email protected]95cb7fb92008-12-09 22:00:47266// Runs the fuzzing server child mode. Returns when the preset number
267// of messages have been received.
268MULTIPROCESS_TEST_MAIN(RunFuzzServer) {
269 MessageLoopForIO main_message_loop;
initial.commit09911bf2008-07-26 23:55:29270 FuzzerServerListener listener;
[email protected]df3c1ca12008-12-19 21:37:01271 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &listener);
initial.commit09911bf2008-07-26 23:55:29272 chan.Connect();
273 listener.Init(&chan);
274 MessageLoop::current()->Run();
[email protected]95cb7fb92008-12-09 22:00:47275 return 0;
initial.commit09911bf2008-07-26 23:55:29276}
277
[email protected]95cb7fb92008-12-09 22:00:47278class IPCFuzzingTest : public IPCChannelTest {
279};
280
initial.commit09911bf2008-07-26 23:55:29281// This test makes sure that the FuzzerClientListener and FuzzerServerListener
282// are working properly by generating two well formed IPC calls.
[email protected]95cb7fb92008-12-09 22:00:47283TEST_F(IPCFuzzingTest, SanityTest) {
[email protected]df3c1ca12008-12-19 21:37:01284 FuzzerClientListener listener;
285 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
286 &listener);
287 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
initial.commit09911bf2008-07-26 23:55:29288 ASSERT_TRUE(server_process);
[email protected]d4651ff2008-12-02 16:51:58289 PlatformThread::Sleep(1000);
initial.commit09911bf2008-07-26 23:55:29290 ASSERT_TRUE(chan.Connect());
291 listener.Init(&chan);
292
293 IPC::Message* msg = NULL;
294 int value = 43;
295 msg = new MsgClassIS(value, L"expect 43");
296 chan.Send(msg);
297 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
298
299 msg = new MsgClassSI(L"expect 44", ++value);
300 chan.Send(msg);
301 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
302
[email protected]d4651ff2008-12-02 16:51:58303 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
[email protected]cd4fd152009-02-09 19:28:41304 base::CloseProcessHandle(server_process);
initial.commit09911bf2008-07-26 23:55:29305}
306
307// This test uses a payload that is smaller than expected.
308// This generates an error while unpacking the IPC buffer which in
309// In debug this triggers an assertion and in release it is ignored(!!). Right
310// after we generate another valid IPC to make sure framing is working
311// properly.
312#ifdef NDEBUG
[email protected]95cb7fb92008-12-09 22:00:47313TEST_F(IPCFuzzingTest, MsgBadPayloadShort) {
[email protected]df3c1ca12008-12-19 21:37:01314 FuzzerClientListener listener;
315 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
316 &listener);
317 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
initial.commit09911bf2008-07-26 23:55:29318 ASSERT_TRUE(server_process);
[email protected]a1b399f2008-12-10 17:16:22319 PlatformThread::Sleep(1000);
initial.commit09911bf2008-07-26 23:55:29320 ASSERT_TRUE(chan.Connect());
321 listener.Init(&chan);
322
323 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
324 IPC::Message::PRIORITY_NORMAL);
325 msg->WriteInt(666);
326 chan.Send(msg);
327 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID));
328
329 msg = new MsgClassSI(L"expect one", 1);
330 chan.Send(msg);
331 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID));
332
[email protected]a1b399f2008-12-10 17:16:22333 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
[email protected]cd4fd152009-02-09 19:28:41334 base::CloseProcessHandle(server_process);
initial.commit09911bf2008-07-26 23:55:29335}
336#endif // NDEBUG
337
[email protected]95cb7fb92008-12-09 22:00:47338// This test uses a payload that has too many arguments, but so the payload
initial.commit09911bf2008-07-26 23:55:29339// size is big enough so the unpacking routine does not generate an error as
340// in the case of MsgBadPayloadShort test.
341// This test does not pinpoint a flaw (per se) as by design we don't carry
342// type information on the IPC message.
[email protected]95cb7fb92008-12-09 22:00:47343TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
[email protected]df3c1ca12008-12-19 21:37:01344 FuzzerClientListener listener;
345 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
346 &listener);
347 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
initial.commit09911bf2008-07-26 23:55:29348 ASSERT_TRUE(server_process);
[email protected]d4651ff2008-12-02 16:51:58349 PlatformThread::Sleep(1000);
initial.commit09911bf2008-07-26 23:55:29350 ASSERT_TRUE(chan.Connect());
351 listener.Init(&chan);
352
353 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
354 IPC::Message::PRIORITY_NORMAL);
[email protected]95cb7fb92008-12-09 22:00:47355 msg->WriteWString(L"d");
initial.commit09911bf2008-07-26 23:55:29356 msg->WriteInt(0);
[email protected]95cb7fb92008-12-09 22:00:47357 msg->WriteInt(0x65); // Extra argument.
358
initial.commit09911bf2008-07-26 23:55:29359 chan.Send(msg);
360 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID));
361
[email protected]95cb7fb92008-12-09 22:00:47362 // Now send a well formed message to make sure the receiver wasn't
363 // thrown out of sync by the extra argument.
initial.commit09911bf2008-07-26 23:55:29364 msg = new MsgClassIS(3, L"expect three");
365 chan.Send(msg);
366 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID));
367
[email protected]d4651ff2008-12-02 16:51:58368 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
[email protected]cd4fd152009-02-09 19:28:41369 base::CloseProcessHandle(server_process);
initial.commit09911bf2008-07-26 23:55:29370}
371
372// This class is for testing the IPC_BEGIN_MESSAGE_MAP_EX macros.
373class ServerMacroExTest {
374 public:
375 ServerMacroExTest() : unhandled_msgs_(0) {
376 }
377 virtual bool OnMessageReceived(const IPC::Message& msg) {
378 bool msg_is_ok = false;
379 IPC_BEGIN_MESSAGE_MAP_EX(ServerMacroExTest, msg, msg_is_ok)
380 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
381 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
382 IPC_MESSAGE_UNHANDLED(++unhandled_msgs_)
383 IPC_END_MESSAGE_MAP_EX()
384 return msg_is_ok;
385 }
386
387 int unhandled_msgs() const {
388 return unhandled_msgs_;
389 }
390
391 private:
392 void OnMsgClassISMessage(int value, const std::wstring& text) {
393 }
394 void OnMsgClassSIMessage(const std::wstring& text, int value) {
395 }
396
397 int unhandled_msgs_;
398};
399
[email protected]95cb7fb92008-12-09 22:00:47400TEST_F(IPCFuzzingTest, MsgMapExMacro) {
initial.commit09911bf2008-07-26 23:55:29401 IPC::Message* msg = NULL;
402 ServerMacroExTest server;
403
404 // Test the regular messages.
405 msg = new MsgClassIS(3, L"text3");
406 EXPECT_TRUE(server.OnMessageReceived(*msg));
407 delete msg;
408 msg = new MsgClassSI(L"text2", 2);
409 EXPECT_TRUE(server.OnMessageReceived(*msg));
410 delete msg;
411
412#ifdef NDEBUG
413 // Test a bad message.
414 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
415 IPC::Message::PRIORITY_NORMAL);
416 msg->WriteInt(2);
417 EXPECT_FALSE(server.OnMessageReceived(*msg));
418 delete msg;
419
420 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
421 IPC::Message::PRIORITY_NORMAL);
422 msg->WriteInt(0x64);
423 msg->WriteInt(0x32);
424 EXPECT_FALSE(server.OnMessageReceived(*msg));
425 delete msg;
426
427 EXPECT_EQ(0, server.unhandled_msgs());
428#endif
429}