xref: /aosp_15_r20/frameworks/native/libs/binder/tests/binderParcelUnitTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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,HasBinders)200 TEST(Parcel, HasBinders) {
201     sp<IBinder> b1 = sp<BBinder>::make();
202 
203     Parcel p1;
204     p1.writeInt32(1);
205     p1.writeStrongBinder(b1);
206 
207     bool result = false;
208     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
209     ASSERT_EQ(true, result);
210 
211     p1.setDataSize(0); // clear data
212     result = false;
213     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
214     ASSERT_EQ(false, result);
215     p1.writeStrongBinder(b1); // reset with binder data
216     result = false;
217     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
218     ASSERT_EQ(true, result);
219 
220     Parcel p3;
221     p3.appendFrom(&p1, 0, p1.dataSize());
222     result = false;
223     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
224     ASSERT_EQ(true, result);
225 }
226 
TEST(Parcel,HasBindersInRange)227 TEST(Parcel, HasBindersInRange) {
228     sp<IBinder> b1 = sp<BBinder>::make();
229     Parcel p1;
230     p1.writeStrongBinder(b1);
231     bool result = false;
232     ASSERT_EQ(NO_ERROR, p1.hasBindersInRange(0, p1.dataSize(), &result));
233     ASSERT_EQ(true, result);
234     result = false;
235     ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
236     ASSERT_EQ(true, result);
237 }
238 
TEST(Parcel,AppendWithBinder)239 TEST(Parcel, AppendWithBinder) {
240     sp<IBinder> b1 = sp<BBinder>::make();
241     sp<IBinder> b2 = sp<BBinder>::make();
242 
243     Parcel p1;
244     p1.writeInt32(1);
245     p1.writeStrongBinder(b1);
246     Parcel p2;
247     p2.writeInt32(2);
248     p2.writeStrongBinder(b2);
249 
250     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
251 
252     p1.setDataPosition(0);
253     ASSERT_EQ(1, p1.readInt32());
254     ASSERT_EQ(b1, p1.readStrongBinder());
255     ASSERT_EQ(2, p1.readInt32());
256     ASSERT_EQ(b2, p1.readStrongBinder());
257     ASSERT_EQ(2, p1.objectsCount());
258 
259     p2.setDataPosition(0);
260     ASSERT_EQ(2, p2.readInt32());
261     ASSERT_EQ(b2, p2.readStrongBinder());
262 }
263 
TEST(Parcel,AppendWithBinderPartial)264 TEST(Parcel, AppendWithBinderPartial) {
265     sp<IBinder> b1 = sp<BBinder>::make();
266     sp<IBinder> b2 = sp<BBinder>::make();
267 
268     Parcel p1;
269     p1.writeInt32(1);
270     p1.writeStrongBinder(b1);
271     Parcel p2;
272     p2.writeInt32(2);
273     p2.writeStrongBinder(b2);
274 
275     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into strong binder
276 
277     p1.setDataPosition(0);
278     ASSERT_EQ(1, p1.readInt32());
279     ASSERT_EQ(b1, p1.readStrongBinder());
280     ASSERT_EQ(2, p1.readInt32());
281     ASSERT_EQ(1935813253, p1.readInt32()); // whatever garbage that is there (ABI)
282     ASSERT_EQ(1, p1.objectsCount());
283 
284     p2.setDataPosition(0);
285     ASSERT_EQ(2, p2.readInt32());
286     ASSERT_EQ(b2, p2.readStrongBinder());
287 }
288 
TEST(Parcel,AppendWithFd)289 TEST(Parcel, AppendWithFd) {
290     unique_fd fd1 = unique_fd(dup(0));
291     unique_fd fd2 = unique_fd(dup(0));
292 
293     Parcel p1;
294     p1.writeInt32(1);
295     p1.writeDupFileDescriptor(0);      // with ownership
296     p1.writeFileDescriptor(fd1.get()); // without ownership
297     Parcel p2;
298     p2.writeInt32(2);
299     p2.writeDupFileDescriptor(0);      // with ownership
300     p2.writeFileDescriptor(fd2.get()); // without ownership
301 
302     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
303 
304     p1.setDataPosition(0);
305     ASSERT_EQ(1, p1.readInt32());
306     ASSERT_NE(-1, p1.readFileDescriptor());
307     ASSERT_NE(-1, p1.readFileDescriptor());
308     ASSERT_EQ(2, p1.readInt32());
309     ASSERT_NE(-1, p1.readFileDescriptor());
310     ASSERT_NE(-1, p1.readFileDescriptor());
311     ASSERT_EQ(4, p1.objectsCount());
312 
313     p2.setDataPosition(0);
314     ASSERT_EQ(2, p2.readInt32());
315     ASSERT_NE(-1, p1.readFileDescriptor());
316     ASSERT_NE(-1, p1.readFileDescriptor());
317 }
318 
TEST(Parcel,AppendWithFdPartial)319 TEST(Parcel, AppendWithFdPartial) {
320     unique_fd fd1 = unique_fd(dup(0));
321     unique_fd fd2 = unique_fd(dup(0));
322 
323     Parcel p1;
324     p1.writeInt32(1);
325     p1.writeDupFileDescriptor(0);      // with ownership
326     p1.writeFileDescriptor(fd1.get()); // without ownership
327     Parcel p2;
328     p2.writeInt32(2);
329     p2.writeDupFileDescriptor(0);      // with ownership
330     p2.writeFileDescriptor(fd2.get()); // without ownership
331 
332     ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into binder
333 
334     p1.setDataPosition(0);
335     ASSERT_EQ(1, p1.readInt32());
336     ASSERT_NE(-1, p1.readFileDescriptor());
337     ASSERT_NE(-1, p1.readFileDescriptor());
338     ASSERT_EQ(2, p1.readInt32());
339     ASSERT_EQ(1717840517, p1.readInt32()); // whatever garbage that is there (ABI)
340     ASSERT_EQ(2, p1.objectsCount());
341 
342     p2.setDataPosition(0);
343     ASSERT_EQ(2, p2.readInt32());
344     ASSERT_NE(-1, p1.readFileDescriptor());
345     ASSERT_NE(-1, p1.readFileDescriptor());
346 }
347 
348 // Tests a second operation results in a parcel at the same location as it
349 // started.
parcelOpSameLength(const std::function<void (Parcel *)> & a,const std::function<void (Parcel *)> & b)350 void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
351     Parcel p;
352     a(&p);
353     size_t end = p.dataPosition();
354     p.setDataPosition(0);
355     b(&p);
356     EXPECT_EQ(end, p.dataPosition());
357 }
358 
TEST(Parcel,InverseInterfaceToken)359 TEST(Parcel, InverseInterfaceToken) {
360     const String16 token = String16("asdf");
361     parcelOpSameLength([&] (Parcel* p) {
362         p->writeInterfaceToken(token);
363     }, [&] (Parcel* p) {
364         EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
365     });
366 }
367 
TEST(Parcel,Utf8FromUtf16Read)368 TEST(Parcel, Utf8FromUtf16Read) {
369     const char* token = "asdf";
370     parcelOpSameLength([&] (Parcel* p) {
371         p->writeString16(String16(token));
372     }, [&] (Parcel* p) {
373         std::string s;
374         EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
375         EXPECT_EQ(token, s);
376     });
377 }
378 
TEST(Parcel,Utf8AsUtf16Write)379 TEST(Parcel, Utf8AsUtf16Write) {
380     std::string token = "asdf";
381     parcelOpSameLength([&] (Parcel* p) {
382         p->writeUtf8AsUtf16(token);
383     }, [&] (Parcel* p) {
384         String16 s;
385         EXPECT_EQ(OK, p->readString16(&s));
386         EXPECT_EQ(s, String16(token.c_str()));
387     });
388 }
389 
390 template <typename T>
391 using readFunc = status_t (Parcel::*)(T* out) const;
392 template <typename T>
393 using writeFunc = status_t (Parcel::*)(const T& in);
394 template <typename T>
395 using copyWriteFunc = status_t (Parcel::*)(T in);
396 
397 template <typename T, typename WRITE_FUNC>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,WRITE_FUNC w)398 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, WRITE_FUNC w) {
399     for (const T& value : ts) {
400         parcelOpSameLength([&] (Parcel* p) {
401             (*p.*w)(value);
402         }, [&] (Parcel* p) {
403             T outValue;
404             EXPECT_EQ(OK, (*p.*r)(&outValue));
405             EXPECT_EQ(value, outValue);
406         });
407     }
408 }
409 
410 template <typename T>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,writeFunc<T> w)411 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, writeFunc<T> w) {
412     readWriteInverse<T, writeFunc<T>>(std::move(ts), r, w);
413 }
414 template <typename T>
readWriteInverse(std::vector<T> && ts,readFunc<T> r,copyWriteFunc<T> w)415 void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, copyWriteFunc<T> w) {
416     readWriteInverse<T, copyWriteFunc<T>>(std::move(ts), r, w);
417 }
418 
419 #define TEST_READ_WRITE_INVERSE(type, name, ...) \
420     TEST(Parcel, Inverse##name) { \
421         readWriteInverse<type>(__VA_ARGS__, &Parcel::read##name, &Parcel::write##name); \
422     }
423 
424 TEST_READ_WRITE_INVERSE(int32_t, Int32, {-2, -1, 0, 1, 2});
425 TEST_READ_WRITE_INVERSE(uint32_t, Uint32, {0, 1, 2});
426 TEST_READ_WRITE_INVERSE(int64_t, Int64, {-2, -1, 0, 1, 2});
427 TEST_READ_WRITE_INVERSE(uint64_t, Uint64, {0, 1, 2});
428 TEST_READ_WRITE_INVERSE(float, Float, {-1.0f, 0.0f, 3.14f});
429 TEST_READ_WRITE_INVERSE(double, Double, {-1.0, 0.0, 3.14});
430 TEST_READ_WRITE_INVERSE(bool, Bool, {true, false});
431 TEST_READ_WRITE_INVERSE(char16_t, Char, {u'a', u'\0'});
432 TEST_READ_WRITE_INVERSE(int8_t, Byte, {-1, 0, 1});
433 TEST_READ_WRITE_INVERSE(String8, String8, {String8(), String8("a"), String8("asdf")});
434 TEST_READ_WRITE_INVERSE(String16, String16, {String16(), String16("a"), String16("asdf")});
435 
TEST(Parcel,GetOpenAshmemSize)436 TEST(Parcel, GetOpenAshmemSize) {
437     constexpr size_t kSize = 1024;
438     constexpr size_t kCount = 3;
439 
440     Parcel p;
441 
442     for (size_t i = 0; i < kCount; i++) {
443         int fd = ashmem_create_region("test-getOpenAshmemSize", kSize);
444         ASSERT_GE(fd, 0);
445         ASSERT_EQ(OK, p.writeFileDescriptor(fd, true /* take ownership */));
446 
447         ASSERT_EQ((kSize * (i + 1)), p.getOpenAshmemSize());
448     }
449 }
450