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