• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <binder/IPCThreadState.h>
18 #include <binder/Parcel.h>
19 #include <binder/Status.h>
20 #include <cutils/ashmem.h>
21 #include <gtest/gtest.h>
22 
23 using android::BBinder;
24 using android::IBinder;
25 using android::IPCThreadState;
26 using android::NO_ERROR;
27 using android::OK;
28 using android::Parcel;
29 using android::sp;
30 using android::status_t;
31 using android::String16;
32 using android::String8;
33 using android::binder::Status;
34 using android::binder::unique_fd;
35 
checkCString(const char * str)36 static void checkCString(const char* str) {
37     for (size_t i = 0; i < 3; i++) {
38         Parcel p;
39 
40         for (size_t j = 0; j < i; j++) p.writeInt32(3);
41 
42         p.writeCString(str);
43         int32_t pos = p.dataPosition();
44 
45         p.setDataPosition(0);
46 
47         for (size_t j = 0; j < i; j++) p.readInt32();
48         const char* str2 = p.readCString();
49 
50         ASSERT_EQ(std::string(str), str2);
51         ASSERT_EQ(pos, p.dataPosition());
52     }
53 }
54 
TEST(Parcel,TestReadCString)55 TEST(Parcel, TestReadCString) {
56     // we should remove the *CString APIs, but testing them until
57     // they are deleted.
58     checkCString("");
59     checkCString("a");
60     checkCString("\n");
61     checkCString("32");
62     checkCString("321");
63     checkCString("3210");
64     checkCString("3210b");
65     checkCString("123434");
66 }
67 
TEST(Parcel,NonNullTerminatedString8)68 TEST(Parcel, NonNullTerminatedString8) {
69     String8 kTestString = String8("test-is-good");
70 
71     // write non-null terminated string
72     Parcel p;
73     p.writeString8(kTestString);
74     p.setDataPosition(0);
75     // BAD! assumption of wire format for test
76     // write over length of string
77     p.writeInt32(kTestString.size() - 2);
78 
79     p.setDataPosition(0);
80     String8 output;
81     EXPECT_NE(OK, p.readString8(&output));
82     EXPECT_EQ(output.size(), 0);
83 }
84 
TEST(Parcel,NonNullTerminatedString16)85 TEST(Parcel, NonNullTerminatedString16) {
86     String16 kTestString = String16("test-is-good");
87 
88     // write non-null terminated string
89     Parcel p;
90     p.writeString16(kTestString);
91     p.setDataPosition(0);
92     // BAD! assumption of wire format for test
93     // write over length of string
94     p.writeInt32(kTestString.size() - 2);
95 
96     p.setDataPosition(0);
97     String16 output;
98     EXPECT_NE(OK, p.readString16(&output));
99     EXPECT_EQ(output.size(), 0);
100 }
101 
TEST(Parcel,EnforceNoDataAvail)102 TEST(Parcel, EnforceNoDataAvail) {
103     const int32_t kTestInt = 42;
104     const String8 kTestString = String8("test-is-good");
105     Parcel p;
106     p.writeInt32(kTestInt);
107     p.writeString8(kTestString);
108     p.setDataPosition(0);
109     EXPECT_EQ(kTestInt, p.readInt32());
110     EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_BAD_PARCELABLE);
111     EXPECT_EQ(kTestString, p.readString8());
112     EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE);
113 }
114 
TEST(Parcel,DebugReadAllBinders)115 TEST(Parcel, DebugReadAllBinders) {
116     sp<IBinder> binder1 = sp<BBinder>::make();
117     sp<IBinder> binder2 = sp<BBinder>::make();
118 
119     Parcel p;
120     p.writeInt32(4);
121     p.writeStrongBinder(binder1);
122     p.writeStrongBinder(nullptr);
123     p.writeInt32(4);
124     p.writeStrongBinder(binder2);
125     p.writeInt32(4);
126 
127     auto ret = p.debugReadAllStrongBinders();
128 
129     ASSERT_EQ(ret.size(), 2);
130     EXPECT_EQ(ret[0], binder1);
131     EXPECT_EQ(ret[1], binder2);
132 }
133 
TEST(Parcel,DebugReadAllFds)134 TEST(Parcel, DebugReadAllFds) {
135     Parcel p;
136     p.writeInt32(4);
137     p.writeFileDescriptor(STDOUT_FILENO, false /*takeOwnership*/);
138     p.writeInt32(4);
139     p.writeFileDescriptor(STDIN_FILENO, false /*takeOwnership*/);
140     p.writeInt32(4);
141 
142     auto ret = p.debugReadAllFileDescriptors();
143 
144     ASSERT_EQ(ret.size(), 2);
145     EXPECT_EQ(ret[0], STDOUT_FILENO);
146     EXPECT_EQ(ret[1], STDIN_FILENO);
147 }
148 
TEST(Parcel,AppendFromEmpty)149 TEST(Parcel, AppendFromEmpty) {
150     Parcel p1;
151     Parcel p2;
152     p2.writeInt32(2);
153 
154     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
155 
156     p1.setDataPosition(0);
157     ASSERT_EQ(2, p1.readInt32());
158 
159     p2.setDataPosition(0);
160     ASSERT_EQ(2, p2.readInt32());
161 }
162 
TEST(Parcel,AppendPlainData)163 TEST(Parcel, AppendPlainData) {
164     Parcel p1;
165     p1.writeInt32(1);
166     Parcel p2;
167     p2.writeInt32(2);
168 
169     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
170 
171     p1.setDataPosition(0);
172     ASSERT_EQ(1, p1.readInt32());
173     ASSERT_EQ(2, p1.readInt32());
174 
175     p2.setDataPosition(0);
176     ASSERT_EQ(2, p2.readInt32());
177 }
178 
TEST(Parcel,AppendPlainDataPartial)179 TEST(Parcel, AppendPlainDataPartial) {
180     Parcel p1;
181     p1.writeInt32(1);
182     Parcel p2;
183     p2.writeInt32(2);
184     p2.writeInt32(3);
185     p2.writeInt32(4);
186 
187     // only copy 8 bytes (two int32's worth)
188     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8));
189 
190     p1.setDataPosition(0);
191     ASSERT_EQ(1, p1.readInt32());
192     ASSERT_EQ(2, p1.readInt32());
193     ASSERT_EQ(3, p1.readInt32());
194     ASSERT_EQ(0, p1.readInt32()); // not 4, end of Parcel
195 
196     p2.setDataPosition(0);
197     ASSERT_EQ(2, p2.readInt32());
198 }
199 
TEST(Parcel,AppendWithBadDataPos)200 TEST(Parcel, AppendWithBadDataPos) {
201     Parcel p1;
202     p1.writeInt32(1);
203     p1.writeInt32(1);
204     Parcel p2;
205     p2.setDataCapacity(8);
206     p2.setDataPosition(10000);
207 
208     EXPECT_EQ(android::BAD_VALUE, p2.appendFrom(&p1, 0, 8));
209 }
210 
TEST(Parcel,HasBinders)211 TEST(Parcel, HasBinders) {
212     sp<IBinder> b1 = sp<BBinder>::make();
213 
214     Parcel p1;
215     p1.writeInt32(1);
216     p1.writeStrongBinder(b1);
217 
218     bool result = false;
219     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
220     ASSERT_EQ(true, result);
221 
222     p1.setDataSize(0); // clear data
223     result = false;
224     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
225     ASSERT_EQ(false, result);
226     p1.writeStrongBinder(b1); // reset with binder data
227     result = false;
228     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
229     ASSERT_EQ(true, result);
230 
231     Parcel p3;
232     p3.appendFrom(&p1, 0, p1.dataSize());
233     result = false;
234     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
235     ASSERT_EQ(true, result);
236 }
237 
TEST(Parcel,HasBindersInRange)238 TEST(Parcel, HasBindersInRange) {
239     sp<IBinder> b1 = sp<BBinder>::make();
240     Parcel p1;
241     p1.writeStrongBinder(b1);
242     bool result = false;
243     ASSERT_EQ(NO_ERROR, p1.hasBindersInRange(0, p1.dataSize(), &result));
244     ASSERT_EQ(true, result);
245     result = false;
246     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
247     ASSERT_EQ(true, result);
248 }
249 
TEST(Parcel,AppendWithBinder)250 TEST(Parcel, AppendWithBinder) {
251     sp<IBinder> b1 = sp<BBinder>::make();
252     sp<IBinder> b2 = sp<BBinder>::make();
253 
254     Parcel p1;
255     p1.writeInt32(1);
256     p1.writeStrongBinder(b1);
257     Parcel p2;
258     p2.writeInt32(2);
259     p2.writeStrongBinder(b2);
260 
261     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
262 
263     p1.setDataPosition(0);
264     ASSERT_EQ(1, p1.readInt32());
265     ASSERT_EQ(b1, p1.readStrongBinder());
266     ASSERT_EQ(2, p1.readInt32());
267     ASSERT_EQ(b2, p1.readStrongBinder());
268     ASSERT_EQ(2, p1.objectsCount());
269 
270     p2.setDataPosition(0);
271     ASSERT_EQ(2, p2.readInt32());
272     ASSERT_EQ(b2, p2.readStrongBinder());
273 }
274 
TEST(Parcel,AppendWithBinderPartial)275 TEST(Parcel, AppendWithBinderPartial) {
276     sp<IBinder> b1 = sp<BBinder>::make();
277     sp<IBinder> b2 = sp<BBinder>::make();
278 
279     Parcel p1;
280     p1.writeInt32(1);
281     p1.writeStrongBinder(b1);
282     Parcel p2;
283     p2.writeInt32(2);
284     p2.writeStrongBinder(b2);
285 
286     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into strong binder
287 
288     p1.setDataPosition(0);
289     ASSERT_EQ(1, p1.readInt32());
290     ASSERT_EQ(b1, p1.readStrongBinder());
291     ASSERT_EQ(2, p1.readInt32());
292     ASSERT_EQ(1935813253, p1.readInt32()); // whatever garbage that is there (ABI)
293     ASSERT_EQ(1, p1.objectsCount());
294 
295     p2.setDataPosition(0);
296     ASSERT_EQ(2, p2.readInt32());
297     ASSERT_EQ(b2, p2.readStrongBinder());
298 }
299 
TEST(Parcel,AppendWithFd)300 TEST(Parcel, AppendWithFd) {
301     unique_fd fd1 = unique_fd(dup(0));
302     unique_fd fd2 = unique_fd(dup(0));
303 
304     Parcel p1;
305     p1.writeInt32(1);
306     p1.writeDupFileDescriptor(0);      // with ownership
307     p1.writeFileDescriptor(fd1.get()); // without ownership
308     Parcel p2;
309     p2.writeInt32(2);
310     p2.writeDupFileDescriptor(0);      // with ownership
311     p2.writeFileDescriptor(fd2.get()); // without ownership
312 
313     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
314 
315     p1.setDataPosition(0);
316     ASSERT_EQ(1, p1.readInt32());
317     ASSERT_NE(-1, p1.readFileDescriptor());
318     ASSERT_NE(-1, p1.readFileDescriptor());
319     ASSERT_EQ(2, p1.readInt32());
320     ASSERT_NE(-1, p1.readFileDescriptor());
321     ASSERT_NE(-1, p1.readFileDescriptor());
322     ASSERT_EQ(4, p1.objectsCount());
323 
324     p2.setDataPosition(0);
325     ASSERT_EQ(2, p2.readInt32());
326     ASSERT_NE(-1, p1.readFileDescriptor());
327     ASSERT_NE(-1, p1.readFileDescriptor());
328 }
329 
TEST(Parcel,AppendWithFdPartial)330 TEST(Parcel, AppendWithFdPartial) {
331     unique_fd fd1 = unique_fd(dup(0));
332     unique_fd fd2 = unique_fd(dup(0));
333 
334     Parcel p1;
335     p1.writeInt32(1);
336     p1.writeDupFileDescriptor(0);      // with ownership
337     p1.writeFileDescriptor(fd1.get()); // without ownership
338     Parcel p2;
339     p2.writeInt32(2);
340     p2.writeDupFileDescriptor(0);      // with ownership
341     p2.writeFileDescriptor(fd2.get()); // without ownership
342 
343     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into binder
344 
345     p1.setDataPosition(0);
346     ASSERT_EQ(1, p1.readInt32());
347     ASSERT_NE(-1, p1.readFileDescriptor());
348     ASSERT_NE(-1, p1.readFileDescriptor());
349     ASSERT_EQ(2, p1.readInt32());
350     ASSERT_EQ(1717840517, p1.readInt32()); // whatever garbage that is there (ABI)
351     ASSERT_EQ(2, p1.objectsCount());
352 
353     p2.setDataPosition(0);
354     ASSERT_EQ(2, p2.readInt32());
355     ASSERT_NE(-1, p1.readFileDescriptor());
356     ASSERT_NE(-1, p1.readFileDescriptor());
357 }
358 
359 // Tests a second operation results in a parcel at the same location as it
360 // started.
parcelOpSameLength(const std::function<void (Parcel *)> & a,const std::function<void (Parcel *)> & b)361 void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
362     Parcel p;
363     a(&p);
364     size_t end = p.dataPosition();
365     p.setDataPosition(0);
366     b(&p);
367     EXPECT_EQ(end, p.dataPosition());
368 }
369 
TEST(Parcel,InverseInterfaceToken)370 TEST(Parcel, InverseInterfaceToken) {
371     const String16 token = String16("asdf");
372     parcelOpSameLength([&] (Parcel* p) {
373         p->writeInterfaceToken(token);
374     }, [&] (Parcel* p) {
375         EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
376     });
377 }
378 
TEST(Parcel,Utf8FromUtf16Read)379 TEST(Parcel, Utf8FromUtf16Read) {
380     const char* token = "asdf";
381     parcelOpSameLength([&] (Parcel* p) {
382         p->writeString16(String16(token));
383     }, [&] (Parcel* p) {
384         std::string s;
385         EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
386         EXPECT_EQ(token, s);
387     });
388 }
389 
TEST(Parcel,Utf8AsUtf16Write)390 TEST(Parcel, Utf8AsUtf16Write) {
391     std::string token = "asdf";
392     parcelOpSameLength([&] (Parcel* p) {
393         p->writeUtf8AsUtf16(token);
394     }, [&] (Parcel* p) {
395         String16 s;
396         EXPECT_EQ(OK, p->readString16(&s));
397         EXPECT_EQ(s, String16(token.c_str()));
398     });
399 }
400 
401 template <typename T>
402 using readFunc = status_t (Parcel::*)(T* out) const;
403 template <typename T>
404 using writeFunc = status_t (Parcel::*)(const T& in);
405 template <typename T>
406 using copyWriteFunc = status_t (Parcel::*)(T in);
407 
408 template <typename T, typename WRITE_FUNC>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,WRITE_FUNC w)409 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, WRITE_FUNC w) {
410     for (const T& value : ts) {
411         parcelOpSameLength([&] (Parcel* p) {
412             (*p.*w)(value);
413         }, [&] (Parcel* p) {
414             T outValue;
415             EXPECT_EQ(OK, (*p.*r)(&outValue));
416             EXPECT_EQ(value, outValue);
417         });
418     }
419 }
420 
421 template <typename T>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,writeFunc<T> w)422 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, writeFunc<T> w) {
423     readWriteInverse<T, writeFunc<T>>(std::move(ts), r, w);
424 }
425 template <typename T>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,copyWriteFunc<T> w)426 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, copyWriteFunc<T> w) {
427     readWriteInverse<T, copyWriteFunc<T>>(std::move(ts), r, w);
428 }
429 
430 #define TEST_READ_WRITE_INVERSE(type, name, ...) \
431     TEST(Parcel, Inverse##name) { \
432         readWriteInverse<type>(__VA_ARGS__, &Parcel::read##name, &Parcel::write##name); \
433     }
434 
435 TEST_READ_WRITE_INVERSE(int32_t, Int32, {-2, -1, 0, 1, 2});
436 TEST_READ_WRITE_INVERSE(uint32_t, Uint32, {0, 1, 2});
437 TEST_READ_WRITE_INVERSE(int64_t, Int64, {-2, -1, 0, 1, 2});
438 TEST_READ_WRITE_INVERSE(uint64_t, Uint64, {0, 1, 2});
439 TEST_READ_WRITE_INVERSE(float, Float, {-1.0f, 0.0f, 3.14f});
440 TEST_READ_WRITE_INVERSE(double, Double, {-1.0, 0.0, 3.14});
441 TEST_READ_WRITE_INVERSE(bool, Bool, {true, false});
442 TEST_READ_WRITE_INVERSE(char16_t, Char, {u'a', u'\0'});
443 TEST_READ_WRITE_INVERSE(int8_t, Byte, {-1, 0, 1});
444 TEST_READ_WRITE_INVERSE(String8, String8, {String8(), String8("a"), String8("asdf")});
445 TEST_READ_WRITE_INVERSE(String16, String16, {String16(), String16("a"), String16("asdf")});
446 
TEST(Parcel,GetOpenAshmemSize)447 TEST(Parcel, GetOpenAshmemSize) {
448     constexpr size_t kSize = 1024;
449     constexpr size_t kCount = 3;
450 
451     Parcel p;
452 
453     for (size_t i = 0; i < kCount; i++) {
454         int fd = ashmem_create_region("test-getOpenAshmemSize", kSize);
455         ASSERT_GE(fd, 0);
456         ASSERT_EQ(OK, p.writeFileDescriptor(fd, true /* take ownership */));
457 
458         ASSERT_EQ((kSize * (i + 1)), p.getOpenAshmemSize());
459     }
460 }
461