* Changing crash report limitation logic to have more control over extreme cases.
[chromium-blink-merge.git] / ipc / ipc_fuzzing_tests.cc
blobefaed2cdeeaf7aff9a592945a13e81046e1c9d25
1 // Copyright (c) 2012 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.
5 #include <stdint.h>
6 #include <stdio.h>
8 #include <sstream>
9 #include <string>
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/threading/platform_thread.h"
15 #include "ipc/ipc_test_base.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 // IPC messages for testing ----------------------------------------------------
20 #define IPC_MESSAGE_IMPL
21 #include "ipc/ipc_message_macros.h"
23 #define IPC_MESSAGE_START TestMsgStart
25 // Generic message class that is an int followed by a string16.
26 IPC_MESSAGE_CONTROL2(MsgClassIS, int, base::string16)
28 // Generic message class that is a string16 followed by an int.
29 IPC_MESSAGE_CONTROL2(MsgClassSI, base::string16, int)
31 // Message to create a mutex in the IPC server, using the received name.
32 IPC_MESSAGE_CONTROL2(MsgDoMutex, base::string16, int)
34 // Used to generate an ID for a message that should not exist.
35 IPC_MESSAGE_CONTROL0(MsgUnhandled)
37 // -----------------------------------------------------------------------------
39 namespace {
41 TEST(IPCMessageIntegrity, ReadBeyondBufferStr) {
42 // This was BUG 984408.
43 uint32_t v1 = kuint32max - 1;
44 int v2 = 666;
45 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
46 EXPECT_TRUE(m.WriteInt(v1));
47 EXPECT_TRUE(m.WriteInt(v2));
49 base::PickleIterator iter(m);
50 std::string vs;
51 EXPECT_FALSE(iter.ReadString(&vs));
54 TEST(IPCMessageIntegrity, ReadBeyondBufferStr16) {
55 // This was BUG 984408.
56 uint32_t v1 = kuint32max - 1;
57 int v2 = 777;
58 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
59 EXPECT_TRUE(m.WriteInt(v1));
60 EXPECT_TRUE(m.WriteInt(v2));
62 base::PickleIterator iter(m);
63 base::string16 vs;
64 EXPECT_FALSE(iter.ReadString16(&vs));
67 TEST(IPCMessageIntegrity, ReadBytesBadIterator) {
68 // This was BUG 1035467.
69 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
70 EXPECT_TRUE(m.WriteInt(1));
71 EXPECT_TRUE(m.WriteInt(2));
73 base::PickleIterator iter(m);
74 const char* data = NULL;
75 EXPECT_TRUE(iter.ReadBytes(&data, sizeof(int)));
78 TEST(IPCMessageIntegrity, ReadVectorNegativeSize) {
79 // A slight variation of BUG 984408. Note that the pickling of vector<char>
80 // has a specialized template which is not vulnerable to this bug. So here
81 // try to hit the non-specialized case vector<P>.
82 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
83 EXPECT_TRUE(m.WriteInt(-1)); // This is the count of elements.
84 EXPECT_TRUE(m.WriteInt(1));
85 EXPECT_TRUE(m.WriteInt(2));
86 EXPECT_TRUE(m.WriteInt(3));
88 std::vector<double> vec;
89 base::PickleIterator iter(m);
90 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
93 #if defined(OS_ANDROID)
94 #define MAYBE_ReadVectorTooLarge1 DISABLED_ReadVectorTooLarge1
95 #else
96 #define MAYBE_ReadVectorTooLarge1 ReadVectorTooLarge1
97 #endif
98 TEST(IPCMessageIntegrity, MAYBE_ReadVectorTooLarge1) {
99 // This was BUG 1006367. This is the large but positive length case. Again
100 // we try to hit the non-specialized case vector<P>.
101 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
102 EXPECT_TRUE(m.WriteInt(0x21000003)); // This is the count of elements.
103 EXPECT_TRUE(m.WriteInt64(1));
104 EXPECT_TRUE(m.WriteInt64(2));
106 std::vector<int64_t> vec;
107 base::PickleIterator iter(m);
108 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
111 TEST(IPCMessageIntegrity, ReadVectorTooLarge2) {
112 // This was BUG 1006367. This is the large but positive with an additional
113 // integer overflow when computing the actual byte size. Again we try to hit
114 // the non-specialized case vector<P>.
115 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
116 EXPECT_TRUE(m.WriteInt(0x71000000)); // This is the count of elements.
117 EXPECT_TRUE(m.WriteInt64(1));
118 EXPECT_TRUE(m.WriteInt64(2));
120 std::vector<int64_t> vec;
121 base::PickleIterator iter(m);
122 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
125 class SimpleListener : public IPC::Listener {
126 public:
127 SimpleListener() : other_(NULL) {
129 void Init(IPC::Sender* s) {
130 other_ = s;
132 protected:
133 IPC::Sender* other_;
136 enum {
137 FUZZER_ROUTING_ID = 5
140 // The fuzzer server class. It runs in a child process and expects
141 // only two IPC calls; after that it exits the message loop which
142 // terminates the child process.
143 class FuzzerServerListener : public SimpleListener {
144 public:
145 FuzzerServerListener() : message_count_(2), pending_messages_(0) {
147 bool OnMessageReceived(const IPC::Message& msg) override {
148 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
149 ++pending_messages_;
150 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg)
151 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
152 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
153 IPC_END_MESSAGE_MAP()
154 if (pending_messages_) {
155 // Probably a problem de-serializing the message.
156 ReplyMsgNotHandled(msg.type());
159 return true;
162 private:
163 void OnMsgClassISMessage(int value, const base::string16& text) {
164 UseData(MsgClassIS::ID, value, text);
165 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value);
166 Cleanup();
169 void OnMsgClassSIMessage(const base::string16& text, int value) {
170 UseData(MsgClassSI::ID, value, text);
171 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value);
172 Cleanup();
175 bool RoundtripAckReply(int routing, uint32_t type_id, int reply) {
176 IPC::Message* message = new IPC::Message(routing, type_id,
177 IPC::Message::PRIORITY_NORMAL);
178 message->WriteInt(reply + 1);
179 message->WriteInt(reply);
180 return other_->Send(message);
183 void Cleanup() {
184 --message_count_;
185 --pending_messages_;
186 if (0 == message_count_)
187 base::MessageLoop::current()->Quit();
190 void ReplyMsgNotHandled(uint32_t type_id) {
191 RoundtripAckReply(FUZZER_ROUTING_ID, MsgUnhandled::ID, type_id);
192 Cleanup();
195 void UseData(int caller, int value, const base::string16& text) {
196 std::ostringstream os;
197 os << "IPC fuzzer:" << caller << " [" << value << " "
198 << base::UTF16ToUTF8(text) << "]\n";
199 std::string output = os.str();
200 LOG(WARNING) << output;
203 int message_count_;
204 int pending_messages_;
207 class FuzzerClientListener : public SimpleListener {
208 public:
209 FuzzerClientListener() : last_msg_(NULL) {
212 bool OnMessageReceived(const IPC::Message& msg) override {
213 last_msg_ = new IPC::Message(msg);
214 base::MessageLoop::current()->Quit();
215 return true;
218 bool ExpectMessage(int value, uint32_t type_id) {
219 if (!MsgHandlerInternal(type_id))
220 return false;
221 int msg_value1 = 0;
222 int msg_value2 = 0;
223 base::PickleIterator iter(*last_msg_);
224 if (!iter.ReadInt(&msg_value1))
225 return false;
226 if (!iter.ReadInt(&msg_value2))
227 return false;
228 if ((msg_value2 + 1) != msg_value1)
229 return false;
230 if (msg_value2 != value)
231 return false;
233 delete last_msg_;
234 last_msg_ = NULL;
235 return true;
238 bool ExpectMsgNotHandled(uint32_t type_id) {
239 return ExpectMessage(type_id, MsgUnhandled::ID);
242 private:
243 bool MsgHandlerInternal(uint32_t type_id) {
244 base::MessageLoop::current()->Run();
245 if (NULL == last_msg_)
246 return false;
247 if (FUZZER_ROUTING_ID != last_msg_->routing_id())
248 return false;
249 return (type_id == last_msg_->type());
252 IPC::Message* last_msg_;
255 // Runs the fuzzing server child mode. Returns when the preset number of
256 // messages have been received.
257 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) {
258 base::MessageLoopForIO main_message_loop;
259 FuzzerServerListener listener;
260 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
261 IPCTestBase::GetChannelName("FuzzServerClient"), &listener, nullptr));
262 CHECK(channel->Connect());
263 listener.Init(channel.get());
264 base::MessageLoop::current()->Run();
265 return 0;
268 class IPCFuzzingTest : public IPCTestBase {
271 #if defined(OS_ANDROID)
272 #define MAYBE_SanityTest DISABLED_SanityTest
273 #else
274 #define MAYBE_SanityTest SanityTest
275 #endif
276 // This test makes sure that the FuzzerClientListener and FuzzerServerListener
277 // are working properly by generating two well formed IPC calls.
278 TEST_F(IPCFuzzingTest, MAYBE_SanityTest) {
279 Init("FuzzServerClient");
281 FuzzerClientListener listener;
282 CreateChannel(&listener);
283 listener.Init(channel());
284 ASSERT_TRUE(ConnectChannel());
285 ASSERT_TRUE(StartClient());
287 IPC::Message* msg = NULL;
288 int value = 43;
289 msg = new MsgClassIS(value, base::ASCIIToUTF16("expect 43"));
290 sender()->Send(msg);
291 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
293 msg = new MsgClassSI(base::ASCIIToUTF16("expect 44"), ++value);
294 sender()->Send(msg);
295 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
297 EXPECT_TRUE(WaitForClientShutdown());
298 DestroyChannel();
301 #if defined(OS_ANDROID)
302 #define MAYBE_MsgBadPayloadShort DISABLED_MsgBadPayloadShort
303 #else
304 #define MAYBE_MsgBadPayloadShort MsgBadPayloadShort
305 #endif
306 // This test uses a payload that is smaller than expected. This generates an
307 // error while unpacking the IPC buffer which in debug trigger an assertion and
308 // in release is ignored (!). Right after we generate another valid IPC to make
309 // sure framing is working properly.
310 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
311 TEST_F(IPCFuzzingTest, MAYBE_MsgBadPayloadShort) {
312 Init("FuzzServerClient");
314 FuzzerClientListener listener;
315 CreateChannel(&listener);
316 listener.Init(channel());
317 ASSERT_TRUE(ConnectChannel());
318 ASSERT_TRUE(StartClient());
320 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
321 IPC::Message::PRIORITY_NORMAL);
322 msg->WriteInt(666);
323 sender()->Send(msg);
324 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID));
326 msg = new MsgClassSI(base::ASCIIToUTF16("expect one"), 1);
327 sender()->Send(msg);
328 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID));
330 EXPECT_TRUE(WaitForClientShutdown());
331 DestroyChannel();
333 #endif
335 #if defined(OS_ANDROID)
336 #define MAYBE_MsgBadPayloadArgs DISABLED_MsgBadPayloadArgs
337 #else
338 #define MAYBE_MsgBadPayloadArgs MsgBadPayloadArgs
339 #endif
340 // This test uses a payload that has too many arguments, but so the payload size
341 // is big enough so the unpacking routine does not generate an error as in the
342 // case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se)
343 // as by design we don't carry type information on the IPC message.
344 TEST_F(IPCFuzzingTest, MAYBE_MsgBadPayloadArgs) {
345 Init("FuzzServerClient");
347 FuzzerClientListener listener;
348 CreateChannel(&listener);
349 listener.Init(channel());
350 ASSERT_TRUE(ConnectChannel());
351 ASSERT_TRUE(StartClient());
353 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
354 IPC::Message::PRIORITY_NORMAL);
355 msg->WriteString16(base::ASCIIToUTF16("d"));
356 msg->WriteInt(0);
357 msg->WriteInt(0x65); // Extra argument.
359 sender()->Send(msg);
360 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID));
362 // Now send a well formed message to make sure the receiver wasn't
363 // thrown out of sync by the extra argument.
364 msg = new MsgClassIS(3, base::ASCIIToUTF16("expect three"));
365 sender()->Send(msg);
366 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID));
368 EXPECT_TRUE(WaitForClientShutdown());
369 DestroyChannel();
372 } // namespace