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