1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "parcel_fuzzer.h"
17 
18 #include "fuzz_log.h"
19 #include "fuzzer/FuzzedDataProvider.h"
20 #include "parcel.h"
21 #include "securec.h"
22 #include "string_ex.h"
23 
24 using namespace std;
25 
26 namespace OHOS {
27 const uint8_t MAX_BUFFER_SIZE = 255;
28 const uint8_t MAX_STRING_LENGTH = 255;
29 const uint8_t MAX_VECTOR_SIZE = 10;
30 const int MAX_OPERATIONS_GENERAL = 500;
31 const int MAX_OPERATIONS_UNALIGNED = 100;
32 const int MAX_OPERATIONS_OTHER = 15;
33 
34 enum Group {
35     GENERAL_GROUP = 0,
36     UNALIGNED_GROUP = 1,
37     OTHER_GROUP = 2,
38 };
39 
40 #define PARCEL_NO_INPUT_WITH_RETURN(T, FUN) \
41     [](FuzzedDataProvider*, Parcel& p) {    \
42         FUZZ_LOGI("%{public}s", #FUN);      \
43         T t = p.FUN();                      \
44         (void)t;                            \
45     }
46 
47 #define PARCEL_INT_INPUT_WITH_BOOL_RETURN(T, FUN) \
48     [](FuzzedDataProvider* d, Parcel& p) {        \
49         FUZZ_LOGI("%{public}s", #FUN);            \
50         T data = d->ConsumeIntegral<T>();         \
51         bool t = p.FUN(data);                     \
52         (void)t;                                  \
53     }
54 
55 #define PARCEL_REF_INPUT_WITH_BOOL_RETURN(T, FUN) \
56     [](FuzzedDataProvider*, Parcel& p) {          \
57         FUZZ_LOGI("%{public}s", #FUN);            \
58         T out {};                                 \
59         bool t = p.FUN(out);                      \
60         (void)t;                                  \
61     }
62 
63 #define PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(T, FUN)                      \
64     [](FuzzedDataProvider* d, Parcel& p) {                                \
65         FUZZ_LOGI("%{public}s", #FUN);                                    \
66         size_t n = d->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE); \
67         void* buf = malloc(n * sizeof(T));                                \
68         size_t wb = d->ConsumeData(buf, n * sizeof(T));                   \
69         auto* tmp = static_cast<const T*>(buf);                           \
70         std::vector<T> data(tmp, tmp + wb / sizeof(T));                   \
71         bool t = p.FUN(data);                                             \
72         (void)t;                                                          \
73         free(buf);                                                        \
74     }
75 
76 #define PARCEL_POINT_INPUT_WITH_BOOL_RETURN(T, FUN) \
77     [](FuzzedDataProvider*, Parcel& p) {            \
78         FUZZ_LOGI("%{public}s", #FUN);              \
79         vector<T> out;                              \
80         bool t = p.FUN(&out);                       \
81         (void)t;                                    \
82     }
83 
84 class TestParcelable : public virtual Parcelable {
85 public:
86     TestParcelable() = default;
TestParcelable(bool asRemote)87     explicit TestParcelable(bool asRemote)
88     {
89         asRemote_ = asRemote;
90     };
91     ~TestParcelable() = default;
92 
93     bool Marshalling(Parcel& parcel) const override;
94     static TestParcelable* Unmarshalling(Parcel& parcel);
95     static bool Marshalling(Parcel& parcel, const sptr<TestParcelable>& object);
96 
97 public:
98     int32_t int32Write_ = -0x12345678;
99     int32_t int32Read_;
100 };
101 
Marshalling(Parcel & parcel) const102 bool TestParcelable::Marshalling(Parcel& parcel) const
103 {
104     bool result = parcel.WriteInt32(this->int32Write_);
105     return result;
106 }
107 
Unmarshalling(Parcel & parcel)108 TestParcelable* TestParcelable::Unmarshalling(Parcel& parcel)
109 {
110     auto* read = new TestParcelable();
111     read->int32Read_ = parcel.ReadInt32();
112     return read;
113 }
114 
Marshalling(Parcel & parcel,const sptr<TestParcelable> & object)115 bool TestParcelable::Marshalling(Parcel& parcel, const sptr<TestParcelable>& object)
116 {
117     bool result = parcel.WriteInt32(object->int32Write_);
118     return result;
119 }
120 
121 class RemoteObject : public virtual Parcelable {
122 public:
RemoteObject()123     RemoteObject()
124     {
125         asRemote_ = true;
126     };
127     bool Marshalling(Parcel& parcel) const override;
128     static sptr<RemoteObject> Unmarshalling(Parcel& parcel);
129 };
130 
Marshalling(Parcel & parcel) const131 bool RemoteObject::Marshalling(Parcel& parcel) const
132 {
133     parcel_flat_binder_object flat;
134     flat.hdr.type = 0xff;
135     flat.flags = 0x7f;
136     flat.binder = 0;
137     flat.handle = (uint32_t)(-1);
138     flat.cookie = reinterpret_cast<uintptr_t>(this);
139     bool status = parcel.WriteBuffer(&flat, sizeof(parcel_flat_binder_object));
140     if (!status) {
141         return false;
142     }
143     return true;
144 }
145 
Unmarshalling(Parcel & parcel)146 sptr<RemoteObject> RemoteObject::Unmarshalling(Parcel& parcel)
147 {
148     const uint8_t* buffer = parcel.ReadBuffer(sizeof(parcel_flat_binder_object), false);
149     if (buffer == nullptr) {
150         return nullptr;
151     }
152     sptr<RemoteObject> obj = new RemoteObject();
153     return obj;
154 }
155 
156 const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> operations = {
157     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataSize),
158     PARCEL_NO_INPUT_WITH_RETURN(uintptr_t, GetData),
159     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetOffsetsSize),
160     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetWritableBytes),
161     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetReadableBytes),
162     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataCapacity),
163     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetMaxCapacity),
164 
__anon90ce765f0102() 165     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
166         FUZZ_LOGI("WriteBool");
167         bool booltest = dataProvider->ConsumeBool();
168         parcel.WriteBool(booltest);
169     },
170 
171     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int8_t, WriteInt8),
172     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int16_t, WriteInt16),
173     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int32_t, WriteInt32),
174     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int64_t, WriteInt64),
175     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint8_t, WriteUint8),
176     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint16_t, WriteUint16),
177     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint32_t, WriteUint32),
178     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint64_t, WriteUint64),
179     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uintptr_t, WritePointer),
180 
__anon90ce765f0202() 181     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
182         FUZZ_LOGI("WriteFloat");
183         float floattest = dataProvider->ConsumeFloatingPoint<float>();
184         parcel.WriteFloat(floattest);
185     },
186 
__anon90ce765f0302() 187     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
188         FUZZ_LOGI("WriteDouble");
189         double doubletest = dataProvider->ConsumeFloatingPoint<double>();
190         parcel.WriteDouble(doubletest);
191     },
192 
__anon90ce765f0402() 193     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
194         FUZZ_LOGI("WriteBuffer");
195         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
196         void* buffer = malloc(bufferSize);
197         size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize);
198         parcel.WriteBuffer(buffer, writtenBytes);
199         free(buffer);
200     },
201 
__anon90ce765f0502() 202     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
203         FUZZ_LOGI("WriteBufferAddTerminator");
204         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
205         void* buffer = malloc(bufferSize);
206         size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize);
207         const size_t maxTypeSize = 4; // max type size is 4 bytes.
208         if (writtenBytes == 0) {
209             free(buffer);
210             return;
211         }
212         size_t typeSize = dataProvider->ConsumeIntegralInRange<size_t>(0, maxTypeSize);
213         parcel.WriteBufferAddTerminator(buffer, writtenBytes, typeSize);
214         free(buffer);
215     },
216 
__anon90ce765f0602() 217     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
218         FUZZ_LOGI("WriteUnpadBuffer");
219         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
220         void* buffer = malloc(bufferSize);
221         size_t writtenBytes = dataProvider->ConsumeData(buffer, bufferSize);
222         parcel.WriteUnpadBuffer(buffer, writtenBytes);
223         free(buffer);
224     },
225 
__anon90ce765f0702() 226     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
227         FUZZ_LOGI("WriteCString");
228         string teststr = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
229         parcel.WriteCString(teststr.c_str());
230     },
231 
__anon90ce765f0802() 232     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
233         FUZZ_LOGI("WriteString");
234         string teststr = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
235         parcel.WriteString(teststr);
236     },
237 
__anon90ce765f0902() 238     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
239         FUZZ_LOGI("WriteString16");
240         string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
241         u16string utf16 = Str8ToStr16(utf8);
242         parcel.WriteString16(utf16);
243     },
244 
__anon90ce765f0a02() 245     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
246         FUZZ_LOGI("WriteString16WithLength");
247         string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
248         u16string utf16 = Str8ToStr16(utf8);
249         char16_t* value = utf16.data();
250         parcel.WriteString16WithLength(value, utf16.length());
251     },
252 
__anon90ce765f0b02() 253     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
254         FUZZ_LOGI("WriteString8WithLength");
255         string utf8 = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
256         char* value = utf8.data();
257         parcel.WriteString8WithLength(value, utf8.length());
258     },
259 
__anon90ce765f0c02() 260     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
261         FUZZ_LOGI("WriteParcelable");
262         bool remoteFlag = dataProvider->ConsumeBool();
263         TestParcelable parcelableWrite(remoteFlag);
264         parcel.WriteParcelable(&parcelableWrite);
265     },
266 
__anon90ce765f0d02() 267     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
268         FUZZ_LOGI("WriteStrongParcelable");
269         bool remoteFlag = dataProvider->ConsumeBool();
270         sptr<TestParcelable> parcelableWrite = new TestParcelable(remoteFlag);
271         parcel.WriteStrongParcelable(parcelableWrite);
272     },
273 
__anon90ce765f0e02() 274     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
275         FUZZ_LOGI("WriteRemoteObject");
276         RemoteObject obj;
277         parcel.WriteRemoteObject(&obj);
278     },
279 
__anon90ce765f0f02() 280     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
281         FUZZ_LOGI("WriteObject");
282         bool remoteFlag = dataProvider->ConsumeBool();
283         sptr<TestParcelable> parcelableWrite = new TestParcelable(remoteFlag);
284         parcel.WriteObject(parcelableWrite);
285     },
286 
__anon90ce765f1002() 287     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
288         FUZZ_LOGI("ParseFrom");
289         void* buffer = nullptr;
290         size_t testdataSize = parcel.GetDataSize();
291         if (testdataSize > 0) {
292             buffer = malloc(testdataSize);
293             memcpy_s(buffer, testdataSize, reinterpret_cast<const uint8_t*>(parcel.GetData()), testdataSize);
294         }
295         Parcel parcel2(nullptr);
296         parcel2.ParseFrom(reinterpret_cast<uintptr_t>(buffer), testdataSize);
297     },
298 
299     PARCEL_NO_INPUT_WITH_RETURN(bool, ReadBool),
300     PARCEL_NO_INPUT_WITH_RETURN(int8_t, ReadInt8),
301     PARCEL_NO_INPUT_WITH_RETURN(int16_t, ReadInt16),
302     PARCEL_NO_INPUT_WITH_RETURN(int32_t, ReadInt32),
303     PARCEL_NO_INPUT_WITH_RETURN(int64_t, ReadInt64),
304     PARCEL_NO_INPUT_WITH_RETURN(uint8_t, ReadUint8),
305     PARCEL_NO_INPUT_WITH_RETURN(uint16_t, ReadUint16),
306     PARCEL_NO_INPUT_WITH_RETURN(uint32_t, ReadUint32),
307     PARCEL_NO_INPUT_WITH_RETURN(uint64_t, ReadUint64),
308     PARCEL_NO_INPUT_WITH_RETURN(float, ReadFloat),
309     PARCEL_NO_INPUT_WITH_RETURN(double, ReadDouble),
310     PARCEL_NO_INPUT_WITH_RETURN(uintptr_t, ReadPointer),
311 
312     PARCEL_REF_INPUT_WITH_BOOL_RETURN(bool, ReadBool),
313     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8),
314     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16),
315     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int32_t, ReadInt32),
316     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int64_t, ReadInt64),
317     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUint8),
318     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUint16),
319     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint32_t, ReadUint32),
320     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint64_t, ReadUint64),
321     PARCEL_REF_INPUT_WITH_BOOL_RETURN(float, ReadFloat),
322     PARCEL_REF_INPUT_WITH_BOOL_RETURN(double, ReadDouble),
323 
__anon90ce765f1102() 324     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
325         FUZZ_LOGI("ReadUnpadBuffer");
326         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
327         parcel.ReadUnpadBuffer(bufferSize);
328     },
329 
330     PARCEL_NO_INPUT_WITH_RETURN(const char*, ReadCString),
331     PARCEL_NO_INPUT_WITH_RETURN(string, ReadString),
332     PARCEL_REF_INPUT_WITH_BOOL_RETURN(string, ReadString),
333     PARCEL_NO_INPUT_WITH_RETURN(u16string, ReadString16),
334     PARCEL_REF_INPUT_WITH_BOOL_RETURN(u16string, ReadString16),
335 
__anon90ce765f1202() 336     [](FuzzedDataProvider*, Parcel& parcel) {
337         FUZZ_LOGI("ReadString16WithLength");
338         int32_t strlen = 0;
339         parcel.ReadString16WithLength(strlen);
340     },
341 
__anon90ce765f1302() 342     [](FuzzedDataProvider*, Parcel& parcel) {
343         FUZZ_LOGI("ReadString8WithLength");
344         int32_t strlen = 0;
345         parcel.ReadString8WithLength(strlen);
346     },
347 
348     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetReadPosition),
349     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetWritePosition),
350 
351     PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadParcelable<TestParcelable>),
352     PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadStrongParcelable<TestParcelable>),
353     PARCEL_NO_INPUT_WITH_RETURN(bool, CheckOffsets),
354     PARCEL_NO_INPUT_WITH_RETURN(sptr<TestParcelable>, ReadObject<TestParcelable>),
355 
__anon90ce765f1402() 356     [](FuzzedDataProvider*, Parcel& parcel) {
357         FUZZ_LOGI("SetAllocator");
358         parcel.SetAllocator(new DefaultAllocator());
359     },
360 
__anon90ce765f1502() 361     [](FuzzedDataProvider*, Parcel& parcel) {
362         FUZZ_LOGI("InjectOffsets");
363         Parcel parcel2(nullptr);
364         parcel2.InjectOffsets(parcel.GetObjectOffsets(), parcel.GetOffsetsSize());
365     },
366 
__anon90ce765f1602() 367     [](FuzzedDataProvider*, Parcel& parcel) {
368         FUZZ_LOGI("FlushBuffer");
369         parcel.FlushBuffer();
370     },
371 
372     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int8_t, WriteInt8Vector),
373     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int32_t, WriteInt32Vector),
374     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int64_t, WriteInt64Vector),
375     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint8_t, WriteUInt8Vector),
376     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint16_t, WriteUInt16Vector),
377     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint32_t, WriteUInt32Vector),
378     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(uint64_t, WriteUInt64Vector),
379     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(float, WriteFloatVector),
380     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(double, WriteDoubleVector),
381 
__anon90ce765f1702() 382     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
383         FUZZ_LOGI("WriteStringVector");
384         size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE);
385         std::vector<string> testdata(vectorSize);
386         for (size_t i = 0; i < vectorSize; i++) {
387             size_t strlen = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_STRING_LENGTH);
388             std::vector<char> vec = dataProvider->ConsumeBytesWithTerminator<char>(strlen);
389             testdata[i] = vec.data();
390         }
391         parcel.WriteStringVector(testdata);
392     },
393 
__anon90ce765f1802() 394     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
395         FUZZ_LOGI("WriteString16Vector");
396         size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE);
397         std::vector<u16string> testdata(vectorSize);
398         for (size_t i = 0; i < vectorSize; i++) {
399             size_t strlen = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_STRING_LENGTH);
400             std::vector<char> vec = dataProvider->ConsumeBytesWithTerminator<char>(strlen);
401             string str = vec.data();
402             testdata[i] = Str8ToStr16(str);
403         }
404         parcel.WriteString16Vector(testdata);
405     },
406 
407     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int32_t, ReadInt32Vector),
408     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int64_t, ReadInt64Vector),
409     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint32_t, ReadUInt32Vector),
410     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint64_t, ReadUInt64Vector),
411     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(float, ReadFloatVector),
412     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(double, ReadDoubleVector),
413     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(string, ReadStringVector),
414     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(u16string, ReadString16Vector),
415 };
416 
417 const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> unaligned_operations = {
418     // error call ReadDouble after following methods, will crash with "signal SIGBUS: illegal alignment".
__anon90ce765f1902() 419     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
420         FUZZ_LOGI("ReadBuffer");
421         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
422         parcel.ReadBuffer(bufferSize);
423     },
424 
__anon90ce765f1a02() 425     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
426         FUZZ_LOGI("SkipBytes");
427         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
428         parcel.SkipBytes(bufferSize);
429     },
430 
__anon90ce765f1b02() 431     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
432         FUZZ_LOGI("RewindRead");
433         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
434         parcel.RewindRead(bufferSize);
435     },
436 
437     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(bool, ReadBoolVector),
438     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8Vector),
439     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16Vector),
440     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUInt8Vector),
441     PARCEL_POINT_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUInt16Vector),
442 
443     PARCEL_NO_INPUT_WITH_RETURN(bool, ReadBoolUnaligned),
444     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int8_t, ReadInt8Unaligned),
445     PARCEL_REF_INPUT_WITH_BOOL_RETURN(int16_t, ReadInt16Unaligned),
446     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint8_t, ReadUint8Unaligned),
447     PARCEL_REF_INPUT_WITH_BOOL_RETURN(uint16_t, ReadUint16Unaligned),
448 
449     // error call WriteDouble/WriteFloat after RewindWrite, will crash with "signal SIGBUS: illegal alignment".
__anon90ce765f1c02() 450     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
451         FUZZ_LOGI("RewindWrite");
452         size_t bufferSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
453         parcel.RewindWrite(bufferSize);
454     },
__anon90ce765f1d02() 455     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
456         FUZZ_LOGI("WriteBoolVector");
457         size_t vectorSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_VECTOR_SIZE);
458         std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(vectorSize);
459         if (data.size() > 0) {
460             std::vector<bool> testdata(data.size());
461             for (size_t i = 0; i < testdata.size(); i++) {
462                 testdata[i] = 1 & data[i];
463             }
464             parcel.WriteBoolVector(testdata);
465         }
466     },
467 
468     PARCEL_WRITE_VECTOR_WITH_BOOL_RETURN(int16_t, WriteInt16Vector),
469 
__anon90ce765f1e02() 470     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
471         FUZZ_LOGI("WriteBoolUnaligned");
472         bool booltest = dataProvider->ConsumeBool();
473         parcel.WriteBoolUnaligned(booltest);
474     },
475 
476     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int8_t, WriteInt8Unaligned),
477     PARCEL_INT_INPUT_WITH_BOOL_RETURN(int16_t, WriteInt16Unaligned),
478     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint8_t, WriteUint8Unaligned),
479     PARCEL_INT_INPUT_WITH_BOOL_RETURN(uint16_t, WriteUint16Unaligned),
480 };
481 
482 const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> other_operations = {
483     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataSize),
484     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetDataCapacity),
485     PARCEL_NO_INPUT_WITH_RETURN(size_t, GetMaxCapacity),
486 
487     // cannot call randomly with other operations.
__anon90ce765f1f02() 488     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
489         FUZZ_LOGI("SetDataCapacity");
490         size_t capacity = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
491         parcel.SetDataCapacity(capacity);
492     },
493 
__anon90ce765f2002() 494     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
495         FUZZ_LOGI("SetDataSize");
496         size_t dataSize = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
497         parcel.SetDataSize(dataSize);
498     },
499 
__anon90ce765f2102() 500     [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
501         FUZZ_LOGI("SetMaxCapacity");
502         size_t maxCapacity = dataProvider->ConsumeIntegralInRange<size_t>(1, MAX_BUFFER_SIZE);
503         parcel.SetMaxCapacity(maxCapacity);
504     },
505 };
506 
ParcelTestFunc(const uint8_t * data,size_t size,FuzzedDataProvider * dataProvider)507 void ParcelTestFunc(const uint8_t* data, size_t size, FuzzedDataProvider* dataProvider)
508 {
509     FUZZ_LOGI("ParcelTestFunc start");
510     uint8_t opSet = dataProvider->ConsumeIntegralInRange<uint8_t>(GENERAL_GROUP, OTHER_GROUP);
511     uint8_t maxGeneral = operations.size() - 1;
512     uint8_t maxUnaligned = unaligned_operations.size() - 1;
513     uint8_t maxOther = other_operations.size() - 1;
514     Parcel parcel1(nullptr);
515     int opCnt = 0;
516 
517     switch (opSet) {
518         case GENERAL_GROUP:
519             while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_GENERAL) {
520                 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxGeneral);
521                 operations[op](dataProvider, parcel1);
522             }
523             break;
524         case UNALIGNED_GROUP:
525             while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_UNALIGNED) {
526                 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxUnaligned);
527                 unaligned_operations[op](dataProvider, parcel1);
528             }
529             break;
530         case OTHER_GROUP:
531             while (dataProvider->remaining_bytes() > 0 && opCnt++ < MAX_OPERATIONS_OTHER) {
532                 uint8_t op = dataProvider->ConsumeIntegralInRange<uint8_t>(0, maxOther);
533                 other_operations[op](dataProvider, parcel1);
534             }
535             break;
536         default:
537             break;
538     }
539     FUZZ_LOGI("ParcelTestFunc end");
540 }
541 
542 } // namespace OHOS
543 
544 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)545 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
546 {
547     FuzzedDataProvider dataProvider(data, size);
548     OHOS::ParcelTestFunc(data, size, &dataProvider);
549     return 0;
550 }
551