1 // Copyright 2017 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 "build/build_config.h"
6 
7 #if defined(OS_NACL_NONSFI)
8 static_assert(false,
9               "ipc_message_protobuf_utils is not able to work with nacl_nonsfi "
10               "configuration.");
11 #endif
12 
13 #include "ipc/ipc_message_protobuf_utils.h"
14 
15 #include <initializer_list>
16 
17 #include "ipc/test_proto.pb.h"
18 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_message_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace IPC {
23 
24 template <>
25 struct ParamTraits<ipc_message_utils_test::TestMessage1> {
26   typedef ipc_message_utils_test::TestMessage1 param_type;
WriteIPC::ParamTraits27   static void Write(base::Pickle* m, const param_type& p) {
28     WriteParam(m, p.number());
29   }
ReadIPC::ParamTraits30   static bool Read(const base::Pickle* m,
31                    base::PickleIterator* iter,
32                    param_type* r) {
33     int number;
34     if (!iter->ReadInt(&number))
35       return false;
36     r->set_number(number);
37     return true;
38   }
39 };
40 
41 template <>
42 struct ParamTraits<ipc_message_utils_test::TestMessage2> {
43   typedef ipc_message_utils_test::TestMessage2 param_type;
WriteIPC::ParamTraits44   static void Write(base::Pickle* m, const param_type& p) {
45     WriteParam(m, p.numbers());
46     WriteParam(m, p.strings());
47     WriteParam(m, p.messages());
48   }
ReadIPC::ParamTraits49   static bool Read(const base::Pickle* m,
50                    base::PickleIterator* iter,
51                    param_type* r) {
52     return ReadParam(m, iter, r->mutable_numbers()) &&
53            ReadParam(m, iter, r->mutable_strings()) &&
54            ReadParam(m, iter, r->mutable_messages());
55   }
56 };
57 
58 namespace {
59 
60 template <class P1, class P2>
AssertEqual(const P1 & left,const P2 & right)61 void AssertEqual(const P1& left, const P2& right) {
62   ASSERT_EQ(left, right);
63 }
64 
65 template<>
AssertEqual(const int & left,const ipc_message_utils_test::TestMessage1 & right)66 void AssertEqual(const int& left,
67                  const ipc_message_utils_test::TestMessage1& right) {
68   ASSERT_EQ(left, right.number());
69 }
70 
71 template <template<class> class RepeatedFieldLike, class P1, class P2>
AssertRepeatedFieldEquals(std::initializer_list<P1> expected,const RepeatedFieldLike<P2> & fields)72 void AssertRepeatedFieldEquals(std::initializer_list<P1> expected,
73                                const RepeatedFieldLike<P2>& fields) {
74   ASSERT_EQ(static_cast<int>(expected.size()), fields.size());
75   auto it = expected.begin();
76   int i = 0;
77   for (; it != expected.end(); it++, i++) {
78     AssertEqual(*it, fields.Get(i));
79   }
80 }
81 
TEST(IPCMessageRepeatedFieldUtilsTest,RepeatedFieldShouldBeSerialized)82 TEST(IPCMessageRepeatedFieldUtilsTest, RepeatedFieldShouldBeSerialized) {
83   ipc_message_utils_test::TestMessage2 message;
84   message.add_numbers(1);
85   message.add_numbers(100);
86   message.add_strings("abc");
87   message.add_strings("def");
88   message.add_messages()->set_number(1000);
89   message.add_messages()->set_number(10000);
90 
91   base::Pickle pickle;
92   IPC::WriteParam(&pickle, message);
93 
94   base::PickleIterator iter(pickle);
95   ipc_message_utils_test::TestMessage2 output;
96   ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
97 
98   AssertRepeatedFieldEquals({1, 100}, output.numbers());
99   AssertRepeatedFieldEquals({"abc", "def"}, output.strings());
100   AssertRepeatedFieldEquals({1000, 10000}, output.messages());
101 }
102 
TEST(IPCMessageRepeatedFieldUtilsTest,PartialEmptyRepeatedFieldShouldBeSerialized)103 TEST(IPCMessageRepeatedFieldUtilsTest,
104      PartialEmptyRepeatedFieldShouldBeSerialized) {
105   ipc_message_utils_test::TestMessage2 message;
106   message.add_numbers(1);
107   message.add_numbers(100);
108   message.add_messages()->set_number(1000);
109   message.add_messages()->set_number(10000);
110 
111   base::Pickle pickle;
112   IPC::WriteParam(&pickle, message);
113 
114   base::PickleIterator iter(pickle);
115   ipc_message_utils_test::TestMessage2 output;
116   ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
117 
118   AssertRepeatedFieldEquals({1, 100}, output.numbers());
119   ASSERT_EQ(0, output.strings_size());
120   AssertRepeatedFieldEquals({1000, 10000}, output.messages());
121 }
122 
TEST(IPCMessageRepeatedFieldUtilsTest,EmptyRepeatedFieldShouldBeSerialized)123 TEST(IPCMessageRepeatedFieldUtilsTest, EmptyRepeatedFieldShouldBeSerialized) {
124   ipc_message_utils_test::TestMessage2 message;
125 
126   base::Pickle pickle;
127   IPC::WriteParam(&pickle, message);
128 
129   base::PickleIterator iter(pickle);
130   ipc_message_utils_test::TestMessage2 output;
131   ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
132 
133   ASSERT_EQ(0, output.numbers_size());
134   ASSERT_EQ(0, output.strings_size());
135   ASSERT_EQ(0, output.messages_size());
136 }
137 
TEST(IPCMessageRepeatedFieldUtilsTest,InvalidPickleShouldNotCrashRepeatedFieldDeserialization)138 TEST(IPCMessageRepeatedFieldUtilsTest,
139      InvalidPickleShouldNotCrashRepeatedFieldDeserialization) {
140   base::Pickle pickle;
141   IPC::WriteParam(&pickle, INT_MAX);
142   IPC::WriteParam(&pickle, 0);
143   IPC::WriteParam(&pickle, INT_MAX);
144   IPC::WriteParam(&pickle, std::string());
145   IPC::WriteParam(&pickle, 0);
146 
147   base::PickleIterator iter(pickle);
148   ipc_message_utils_test::TestMessage2 output;
149   ASSERT_FALSE(IPC::ReadParam(&pickle, &iter, &output));
150 }
151 
152 // This test needs ~20 seconds in Debug mode, or ~4 seconds in Release mode.
153 // See http://crbug.com/741866 for details.
TEST(IPCMessageRepeatedFieldUtilsTest,DISABLED_InvalidPickleShouldNotCrashRepeatedFieldDeserialization2)154 TEST(IPCMessageRepeatedFieldUtilsTest,
155      DISABLED_InvalidPickleShouldNotCrashRepeatedFieldDeserialization2) {
156   base::Pickle pickle;
157   IPC::WriteParam(&pickle, 256 * 1024 * 1024);
158   IPC::WriteParam(&pickle, 0);
159   IPC::WriteParam(&pickle, INT_MAX);
160   IPC::WriteParam(&pickle, std::string());
161   IPC::WriteParam(&pickle, 0);
162 
163   base::PickleIterator iter(pickle);
164   ipc_message_utils_test::TestMessage2 output;
165   ASSERT_FALSE(IPC::ReadParam(&pickle, &iter, &output));
166 }
167 
168 }  // namespace
169 
170 }  // namespace IPC
171