[go: nahoru, domu]

blob: cbd2bd35ba85615a41e4ecab682f8db1dd0ab9d1 [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>
6#include <iostream>
7#include <string>
8#include <sstream>
9
jeremy@chromium.org514411fc2008-12-10 22:28:1110#include "base/message_loop.h"
nsylvain@chromium.orgd4651ff2008-12-02 16:51:5811#include "base/platform_thread.h"
12#include "base/process_util.h"
initial.commit09911bf2008-07-26 23:55:2913#include "chrome/common/ipc_channel.h"
14#include "chrome/common/ipc_channel_proxy.h"
15#include "chrome/common/ipc_message_utils.h"
jeremy@chromium.org514411fc2008-12-10 22:28:1116#include "chrome/common/ipc_tests.h"
initial.commit09911bf2008-07-26 23:55:2917#include "testing/gtest/include/gtest/gtest.h"
jeremy@chromium.org95cb7fb92008-12-09 22:00:4718#include "testing/multiprocess_func_list.h"
initial.commit09911bf2008-07-26 23:55:2919
20TEST(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
33TEST(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
46TEST(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
57TEST(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
72TEST(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
85TEST(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// Typically the ipc_message_macros files is included twice but here we only
100// include it once in 'enum mode' because we want more control of the class
101// definitions.
102#define IPC_MESSAGE_MACROS_ENUMS
103#include "chrome/common/ipc_message_macros.h"
104
105enum IPCMessageIds {
106 UNUSED_IPC_TYPE,
107 SERVER_FIRST_IPC_TYPE, // 1st Test message tag.
108 SERVER_SECOND_IPC_TYPE, // 2nd Test message tag.
109 SERVER_THIRD_IPC_TYPE, // 3rd Test message tag.
110 CLIENT_MALFORMED_IPC, // Sent to client if server detects bad message.
111 CLIENT_UNHANDLED_IPC // Sent to client if server detects unhanded IPC.
112};
113
114// Generic message class that is an int followed by a wstring.
115class MsgClassIS : public IPC::MessageWithTuple< Tuple2<int, std::wstring> > {
116 public:
117 enum { ID = SERVER_FIRST_IPC_TYPE };
118 MsgClassIS(const int& arg1, const std::wstring& arg2)
119 : IPC::MessageWithTuple< Tuple2<int, std::wstring> >(
120 MSG_ROUTING_CONTROL, ID, MakeTuple(arg1, arg2)) {}
121};
122
123// Generic message class that is a wstring followed by an int.
124class MsgClassSI : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
125 public:
126 enum { ID = SERVER_SECOND_IPC_TYPE };
127 MsgClassSI(const std::wstring& arg1, const int& arg2)
128 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
129 MSG_ROUTING_CONTROL, ID, MakeTuple(arg1, arg2)) {}
130};
131
132// Message to create a mutex in the IPC server, using the received name.
133class MsgDoMutex : public IPC::MessageWithTuple< Tuple2<std::wstring, int> > {
134 public:
135 enum { ID = SERVER_THIRD_IPC_TYPE };
136 MsgDoMutex(const std::wstring& mutex_name, const int& unused)
137 : IPC::MessageWithTuple< Tuple2<std::wstring, int> >(
138 MSG_ROUTING_CONTROL, ID, MakeTuple(mutex_name, unused)) {}
139};
140
141class SimpleListener : public IPC::Channel::Listener {
142 public:
143 SimpleListener() : other_(NULL) {
144 }
145 void Init(IPC::Message::Sender* s) {
146 other_ = s;
147 }
148 protected:
149 IPC::Message::Sender* other_;
150};
151
152enum {
153 FUZZER_ROUTING_ID = 5
154};
155
156// The fuzzer server class. It runs in a child process and expects
157// only two IPC calls; after that it exits the message loop which
158// terminates the child process.
159class FuzzerServerListener : public SimpleListener {
160 public:
161 FuzzerServerListener() : message_count_(2), pending_messages_(0) {
162 }
163 virtual void OnMessageReceived(const IPC::Message& msg) {
164 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
165 ++pending_messages_;
166 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg)
167 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
168 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
169 IPC_END_MESSAGE_MAP()
170 if (pending_messages_) {
171 // Probably a problem de-serializing the message.
172 ReplyMsgNotHandled(msg.type());
173 }
174 }
175 }
176
177 private:
178 void OnMsgClassISMessage(int value, const std::wstring& text) {
179 UseData(MsgClassIS::ID, value, text);
180 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value);
181 Cleanup();
182 }
183
184 void OnMsgClassSIMessage(const std::wstring& text, int value) {
185 UseData(MsgClassSI::ID, value, text);
186 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value);
187 Cleanup();
188 }
189
190 bool RoundtripAckReply(int routing, int type_id, int reply) {
191 IPC::Message* message = new IPC::Message(routing, type_id,
192 IPC::Message::PRIORITY_NORMAL);
193 message->WriteInt(reply + 1);
194 message->WriteInt(reply);
195 return other_->Send(message);
196 }
197
198 void Cleanup() {
199 --message_count_;
200 --pending_messages_;
201 if (0 == message_count_)
202 MessageLoop::current()->Quit();
203 }
204
205 void ReplyMsgNotHandled(int type_id) {
206 RoundtripAckReply(FUZZER_ROUTING_ID, CLIENT_UNHANDLED_IPC, type_id);
207 Cleanup();
208 }
209
210 void UseData(int caller, int value, const std::wstring& text) {
211 std::wostringstream wos;
212 wos << L"IPC fuzzer:" << caller << " [" << value << L" " << text << L"]\n";
213 std::wstring output = wos.str();
nsylvain@chromium.orgd4651ff2008-12-02 16:51:58214 LOG(WARNING) << output.c_str();
initial.commit09911bf2008-07-26 23:55:29215 };
216
217 int message_count_;
218 int pending_messages_;
219};
220
221class FuzzerClientListener : public SimpleListener {
222 public:
223 FuzzerClientListener() : last_msg_(NULL) {
224 }
225
226 virtual void OnMessageReceived(const IPC::Message& msg) {
227 last_msg_ = new IPC::Message(msg);
228 MessageLoop::current()->Quit();
229 }
230
231 bool ExpectMessage(int value, int type_id) {
232 if (!MsgHandlerInternal(type_id))
233 return false;
234 int msg_value1 = 0;
235 int msg_value2 = 0;
236 void* iter = NULL;
237 if (!last_msg_->ReadInt(&iter, &msg_value1))
238 return false;
239 if (!last_msg_->ReadInt(&iter, &msg_value2))
240 return false;
241 if ((msg_value2 + 1) != msg_value1)
242 return false;
243 if (msg_value2 != value)
244 return false;
245
246 delete last_msg_;
247 last_msg_ = NULL;
248 return true;
249 }
250
251 bool ExpectMsgNotHandled(int type_id) {
252 return ExpectMessage(type_id, CLIENT_UNHANDLED_IPC);
253 }
254
255 private:
256 bool MsgHandlerInternal(int type_id) {
257 MessageLoop::current()->Run();
258 if (NULL == last_msg_)
259 return false;
260 if (FUZZER_ROUTING_ID != last_msg_->routing_id())
261 return false;
262 return (type_id == last_msg_->type());
263 };
264
265 IPC::Message* last_msg_;
266};
267
jeremy@chromium.org95cb7fb92008-12-09 22:00:47268// Runs the fuzzing server child mode. Returns when the preset number
269// of messages have been received.
270MULTIPROCESS_TEST_MAIN(RunFuzzServer) {
271 MessageLoopForIO main_message_loop;
initial.commit09911bf2008-07-26 23:55:29272 FuzzerServerListener listener;
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01273 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &listener);
initial.commit09911bf2008-07-26 23:55:29274 chan.Connect();
275 listener.Init(&chan);
276 MessageLoop::current()->Run();
jeremy@chromium.org95cb7fb92008-12-09 22:00:47277 return 0;
initial.commit09911bf2008-07-26 23:55:29278}
jeremy@chromium.org95cb7fb92008-12-09 22:00:47279
280class IPCFuzzingTest : public IPCChannelTest {
281};
initial.commit09911bf2008-07-26 23:55:29282
283// This test makes sure that the FuzzerClientListener and FuzzerServerListener
284// are working properly by generating two well formed IPC calls.
jeremy@chromium.org95cb7fb92008-12-09 22:00:47285TEST_F(IPCFuzzingTest, SanityTest) {
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01286 FuzzerClientListener listener;
287 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
288 &listener);
289 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
initial.commit09911bf2008-07-26 23:55:29290 ASSERT_TRUE(server_process);
nsylvain@chromium.orgd4651ff2008-12-02 16:51:58291 PlatformThread::Sleep(1000);
initial.commit09911bf2008-07-26 23:55:29292 ASSERT_TRUE(chan.Connect());
293 listener.Init(&chan);
294
295 IPC::Message* msg = NULL;
296 int value = 43;
297 msg = new MsgClassIS(value, L"expect 43");
298 chan.Send(msg);
299 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
300
301 msg = new MsgClassSI(L"expect 44", ++value);
302 chan.Send(msg);
303 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
304
nsylvain@chromium.orgd4651ff2008-12-02 16:51:58305 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
initial.commit09911bf2008-07-26 23:55:29306}
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
jeremy@chromium.org95cb7fb92008-12-09 22:00:47314TEST_F(IPCFuzzingTest, MsgBadPayloadShort) {
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01315 FuzzerClientListener listener;
316 IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
317 &listener);
318 base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
initial.commit09911bf2008-07-26 23:55:29319 ASSERT_TRUE(server_process);
pinkerton@google.coma1b399f2008-12-10 17:16:22320 PlatformThread::Sleep(1000);
initial.commit09911bf2008-07-26 23:55:29321 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
pinkerton@google.coma1b399f2008-12-10 17:16:22334 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
initial.commit09911bf2008-07-26 23:55:29335}
336#endif // NDEBUG
337
jeremy@chromium.org95cb7fb92008-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.
jeremy@chromium.org95cb7fb92008-12-09 22:00:47343TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
jeremy@chromium.orgdf3c1ca12008-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);
nsylvain@chromium.orgd4651ff2008-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);
jeremy@chromium.org95cb7fb92008-12-09 22:00:47355 msg->WriteWString(L"d");
initial.commit09911bf2008-07-26 23:55:29356 msg->WriteInt(0);
jeremy@chromium.org95cb7fb92008-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
jeremy@chromium.org95cb7fb92008-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
nsylvain@chromium.orgd4651ff2008-12-02 16:51:58368 EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
initial.commit09911bf2008-07-26 23:55:29369}
370
371// This class is for testing the IPC_BEGIN_MESSAGE_MAP_EX macros.
372class ServerMacroExTest {
373 public:
374 ServerMacroExTest() : unhandled_msgs_(0) {
375 }
376 virtual bool OnMessageReceived(const IPC::Message& msg) {
377 bool msg_is_ok = false;
378 IPC_BEGIN_MESSAGE_MAP_EX(ServerMacroExTest, msg, msg_is_ok)
379 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
380 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
381 IPC_MESSAGE_UNHANDLED(++unhandled_msgs_)
382 IPC_END_MESSAGE_MAP_EX()
383 return msg_is_ok;
384 }
385
386 int unhandled_msgs() const {
387 return unhandled_msgs_;
388 }
389
390 private:
391 void OnMsgClassISMessage(int value, const std::wstring& text) {
392 }
393 void OnMsgClassSIMessage(const std::wstring& text, int value) {
394 }
395
396 int unhandled_msgs_;
397};
398
jeremy@chromium.org95cb7fb92008-12-09 22:00:47399TEST_F(IPCFuzzingTest, MsgMapExMacro) {
initial.commit09911bf2008-07-26 23:55:29400 IPC::Message* msg = NULL;
401 ServerMacroExTest server;
402
403 // Test the regular messages.
404 msg = new MsgClassIS(3, L"text3");
405 EXPECT_TRUE(server.OnMessageReceived(*msg));
406 delete msg;
407 msg = new MsgClassSI(L"text2", 2);
408 EXPECT_TRUE(server.OnMessageReceived(*msg));
409 delete msg;
410
411#ifdef NDEBUG
412 // Test a bad message.
413 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
414 IPC::Message::PRIORITY_NORMAL);
415 msg->WriteInt(2);
416 EXPECT_FALSE(server.OnMessageReceived(*msg));
417 delete msg;
418
419 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
420 IPC::Message::PRIORITY_NORMAL);
421 msg->WriteInt(0x64);
422 msg->WriteInt(0x32);
423 EXPECT_FALSE(server.OnMessageReceived(*msg));
424 delete msg;
425
426 EXPECT_EQ(0, server.unhandled_msgs());
427#endif
428}
license.botbf09a502008-08-24 00:55:55429