• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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