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.
4
5 #include "ipc/ipc_message.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include <limits>
12 #include <memory>
13 #include <utility>
14
15 #include "base/memory/ptr_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "build/build_config.h"
19 #include "ipc/ipc_message_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 // IPC messages for testing ----------------------------------------------------
23
24 #define IPC_MESSAGE_IMPL
25 #include "ipc/ipc_message_macros.h"
26
27 #define IPC_MESSAGE_START TestMsgStart
28
29 IPC_MESSAGE_CONTROL0(TestMsgClassEmpty)
30
31 IPC_MESSAGE_CONTROL1(TestMsgClassI, int)
32
33 IPC_SYNC_MESSAGE_CONTROL1_1(TestMsgClassIS, int, std::string)
34
35 namespace IPC {
36
TEST(IPCMessageTest,BasicMessageTest)37 TEST(IPCMessageTest, BasicMessageTest) {
38 int v1 = 10;
39 std::string v2("foobar");
40 base::string16 v3(base::ASCIIToUTF16("hello world"));
41
42 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
43 m.WriteInt(v1);
44 m.WriteString(v2);
45 m.WriteString16(v3);
46
47 base::PickleIterator iter(m);
48
49 int vi;
50 std::string vs;
51 base::string16 vs16;
52
53 EXPECT_TRUE(iter.ReadInt(&vi));
54 EXPECT_EQ(v1, vi);
55
56 EXPECT_TRUE(iter.ReadString(&vs));
57 EXPECT_EQ(v2, vs);
58
59 EXPECT_TRUE(iter.ReadString16(&vs16));
60 EXPECT_EQ(v3, vs16);
61
62 // should fail
63 EXPECT_FALSE(iter.ReadInt(&vi));
64 EXPECT_FALSE(iter.ReadString(&vs));
65 EXPECT_FALSE(iter.ReadString16(&vs16));
66 }
67
TEST(IPCMessageTest,ListValue)68 TEST(IPCMessageTest, ListValue) {
69 base::ListValue input;
70 input.AppendDouble(42.42);
71 input.AppendString("forty");
72 input.Append(std::make_unique<base::Value>());
73
74 IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
75 IPC::WriteParam(&msg, input);
76
77 base::ListValue output;
78 base::PickleIterator iter(msg);
79 EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
80
81 EXPECT_TRUE(input.Equals(&output));
82
83 // Also test the corrupt case.
84 IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
85 bad_msg.WriteInt(99);
86 iter = base::PickleIterator(bad_msg);
87 EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
88 }
89
TEST(IPCMessageTest,DictionaryValue)90 TEST(IPCMessageTest, DictionaryValue) {
91 base::DictionaryValue input;
92 input.Set("null", std::make_unique<base::Value>());
93 input.SetBoolean("bool", true);
94 input.SetInteger("int", 42);
95 input.SetKey("int.with.dot", base::Value(43));
96
97 auto subdict = std::make_unique<base::DictionaryValue>();
98 subdict->SetString("str", "forty two");
99 subdict->SetBoolean("bool", false);
100
101 auto sublist = std::make_unique<base::ListValue>();
102 sublist->AppendDouble(42.42);
103 sublist->AppendString("forty");
104 sublist->AppendString("two");
105 subdict->Set("list", std::move(sublist));
106
107 input.Set("dict", std::move(subdict));
108
109 IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
110 IPC::WriteParam(&msg, input);
111
112 base::DictionaryValue output;
113 base::PickleIterator iter(msg);
114 EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
115
116 EXPECT_TRUE(input.Equals(&output));
117
118 // Also test the corrupt case.
119 IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
120 bad_msg.WriteInt(99);
121 iter = base::PickleIterator(bad_msg);
122 EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
123 }
124
TEST(IPCMessageTest,FindNext)125 TEST(IPCMessageTest, FindNext) {
126 IPC::Message message;
127 message.WriteString("Goooooooogle");
128 message.WriteInt(111);
129
130 std::vector<char> message_data(message.size() + 7);
131 memcpy(message_data.data(), message.data(), message.size());
132
133 const char* data_start = message_data.data();
134 const char* data_end = data_start + message.size();
135
136 IPC::Message::NextMessageInfo next;
137
138 // Data range contains the entire message plus some extra bytes
139 IPC::Message::FindNext(data_start, data_end + 1, &next);
140 EXPECT_TRUE(next.message_found);
141 EXPECT_EQ(next.message_size, message.size());
142 EXPECT_EQ(next.pickle_end, data_end);
143 EXPECT_EQ(next.message_end, data_end);
144
145 // Data range exactly contains the entire message
146 IPC::Message::FindNext(data_start, data_end, &next);
147 EXPECT_TRUE(next.message_found);
148 EXPECT_EQ(next.message_size, message.size());
149 EXPECT_EQ(next.pickle_end, data_end);
150 EXPECT_EQ(next.message_end, data_end);
151
152 // Data range doesn't contain the entire message
153 // (but contains the message header)
154 IPC::Message::FindNext(data_start, data_end - 1, &next);
155 EXPECT_FALSE(next.message_found);
156 EXPECT_EQ(next.message_size, message.size());
157
158 // Data range doesn't contain the message header
159 // (but contains the pickle header)
160 IPC::Message::FindNext(data_start,
161 data_start + sizeof(IPC::Message::Header) - 1,
162 &next);
163 EXPECT_FALSE(next.message_found);
164 EXPECT_EQ(next.message_size, 0u);
165
166 // Data range doesn't contain the pickle header
167 IPC::Message::FindNext(data_start,
168 data_start + sizeof(base::Pickle::Header) - 1,
169 &next);
170 EXPECT_FALSE(next.message_found);
171 EXPECT_EQ(next.message_size, 0u);
172 }
173
TEST(IPCMessageTest,FindNextOverflow)174 TEST(IPCMessageTest, FindNextOverflow) {
175 IPC::Message message;
176 message.WriteString("Data");
177 message.WriteInt(777);
178
179 const char* data_start = reinterpret_cast<const char*>(message.data());
180 const char* data_end = data_start + message.size();
181
182 IPC::Message::NextMessageInfo next;
183
184 // Payload size is negative (defeats 'start + size > end' check)
185 message.header()->payload_size = static_cast<uint32_t>(-1);
186 IPC::Message::FindNext(data_start, data_end, &next);
187 EXPECT_FALSE(next.message_found);
188 if (sizeof(size_t) > sizeof(uint32_t)) {
189 // No overflow, just insane message size
190 EXPECT_EQ(next.message_size,
191 message.header()->payload_size + sizeof(IPC::Message::Header));
192 } else {
193 // Actual overflow, reported as max size_t
194 EXPECT_EQ(next.message_size, std::numeric_limits<size_t>::max());
195 }
196
197 // Payload size is max positive integer (defeats size < 0 check, while
198 // still potentially causing overflow down the road).
199 message.header()->payload_size = std::numeric_limits<int32_t>::max();
200 IPC::Message::FindNext(data_start, data_end, &next);
201 EXPECT_FALSE(next.message_found);
202 EXPECT_EQ(next.message_size,
203 message.header()->payload_size + sizeof(IPC::Message::Header));
204 }
205
206 namespace {
207
208 class IPCMessageParameterTest : public testing::Test {
209 public:
IPCMessageParameterTest()210 IPCMessageParameterTest() : extra_param_("extra_param"), called_(false) {}
211
OnMessageReceived(const IPC::Message & message)212 bool OnMessageReceived(const IPC::Message& message) {
213 bool handled = true;
214 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(IPCMessageParameterTest, message,
215 &extra_param_)
216 IPC_MESSAGE_HANDLER(TestMsgClassEmpty, OnEmpty)
217 IPC_MESSAGE_HANDLER(TestMsgClassI, OnInt)
218 //IPC_MESSAGE_HANDLER(TestMsgClassIS, OnSync)
219 IPC_MESSAGE_UNHANDLED(handled = false)
220 IPC_END_MESSAGE_MAP()
221
222 return handled;
223 }
224
OnEmpty(std::string * extra_param)225 void OnEmpty(std::string* extra_param) {
226 EXPECT_EQ(extra_param, &extra_param_);
227 called_ = true;
228 }
229
OnInt(std::string * extra_param,int foo)230 void OnInt(std::string* extra_param, int foo) {
231 EXPECT_EQ(extra_param, &extra_param_);
232 EXPECT_EQ(foo, 42);
233 called_ = true;
234 }
235
236 /* TODO: handle sync IPCs
237 void OnSync(std::string* extra_param, int foo, std::string* out) {
238 EXPECT_EQ(extra_param, &extra_param_);
239 EXPECT_EQ(foo, 42);
240 called_ = true;
241 *out = std::string("out");
242 }
243
244 bool Send(IPC::Message* reply) {
245 delete reply;
246 return true;
247 }*/
248
249 std::string extra_param_;
250 bool called_;
251 };
252
253 } // namespace
254
TEST_F(IPCMessageParameterTest,EmptyDispatcherWithParam)255 TEST_F(IPCMessageParameterTest, EmptyDispatcherWithParam) {
256 TestMsgClassEmpty message;
257 EXPECT_TRUE(OnMessageReceived(message));
258 EXPECT_TRUE(called_);
259 }
260
261 #if defined(OS_ANDROID)
262 #define MAYBE_OneIntegerWithParam DISABLED_OneIntegerWithParam
263 #else
264 #define MAYBE_OneIntegerWithParam OneIntegerWithParam
265 #endif
TEST_F(IPCMessageParameterTest,MAYBE_OneIntegerWithParam)266 TEST_F(IPCMessageParameterTest, MAYBE_OneIntegerWithParam) {
267 TestMsgClassI message(42);
268 EXPECT_TRUE(OnMessageReceived(message));
269 EXPECT_TRUE(called_);
270 }
271
272 /* TODO: handle sync IPCs
273 TEST_F(IPCMessageParameterTest, Sync) {
274 std::string output;
275 TestMsgClassIS message(42, &output);
276 EXPECT_TRUE(OnMessageReceived(message));
277 EXPECT_TRUE(called_);
278 EXPECT_EQ(output, std::string("out"));
279 }*/
280
281 } // namespace IPC
282