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
24using namespace std;
25
26namespace OHOS {
27const uint8_t MAX_BUFFER_SIZE = 255;
28const uint8_t MAX_STRING_LENGTH = 255;
29const uint8_t MAX_VECTOR_SIZE = 10;
30const int MAX_OPERATIONS_GENERAL = 500;
31const int MAX_OPERATIONS_UNALIGNED = 100;
32const int MAX_OPERATIONS_OTHER = 15;
33
34enum 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
84class TestParcelable : public virtual Parcelable {
85public:
86    TestParcelable() = default;
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
97public:
98    int32_t int32Write_ = -0x12345678;
99    int32_t int32Read_;
100};
101
102bool TestParcelable::Marshalling(Parcel& parcel) const
103{
104    bool result = parcel.WriteInt32(this->int32Write_);
105    return result;
106}
107
108TestParcelable* TestParcelable::Unmarshalling(Parcel& parcel)
109{
110    auto* read = new TestParcelable();
111    read->int32Read_ = parcel.ReadInt32();
112    return read;
113}
114
115bool TestParcelable::Marshalling(Parcel& parcel, const sptr<TestParcelable>& object)
116{
117    bool result = parcel.WriteInt32(object->int32Write_);
118    return result;
119}
120
121class RemoteObject : public virtual Parcelable {
122public:
123    RemoteObject()
124    {
125        asRemote_ = true;
126    };
127    bool Marshalling(Parcel& parcel) const override;
128    static sptr<RemoteObject> Unmarshalling(Parcel& parcel);
129};
130
131bool 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
146sptr<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
156const 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
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
181    [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
182        FUZZ_LOGI("WriteFloat");
183        float floattest = dataProvider->ConsumeFloatingPoint<float>();
184        parcel.WriteFloat(floattest);
185    },
186
187    [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
188        FUZZ_LOGI("WriteDouble");
189        double doubletest = dataProvider->ConsumeFloatingPoint<double>();
190        parcel.WriteDouble(doubletest);
191    },
192
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
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
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
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
232    [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
233        FUZZ_LOGI("WriteString");
234        string teststr = dataProvider->ConsumeRandomLengthString(MAX_STRING_LENGTH);
235        parcel.WriteString(teststr);
236    },
237
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
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
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
260    [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
261        FUZZ_LOGI("WriteParcelable");
262        bool remoteFlag = dataProvider->ConsumeBool();
263        TestParcelable parcelableWrite(remoteFlag);
264        parcel.WriteParcelable(&parcelableWrite);
265    },
266
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
274    [](FuzzedDataProvider* dataProvider, Parcel& parcel) {
275        FUZZ_LOGI("WriteRemoteObject");
276        RemoteObject obj;
277        parcel.WriteRemoteObject(&obj);
278    },
279
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
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
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
336    [](FuzzedDataProvider*, Parcel& parcel) {
337        FUZZ_LOGI("ReadString16WithLength");
338        int32_t strlen = 0;
339        parcel.ReadString16WithLength(strlen);
340    },
341
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
356    [](FuzzedDataProvider*, Parcel& parcel) {
357        FUZZ_LOGI("SetAllocator");
358        parcel.SetAllocator(new DefaultAllocator());
359    },
360
361    [](FuzzedDataProvider*, Parcel& parcel) {
362        FUZZ_LOGI("InjectOffsets");
363        Parcel parcel2(nullptr);
364        parcel2.InjectOffsets(parcel.GetObjectOffsets(), parcel.GetOffsetsSize());
365    },
366
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
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
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
417const std::vector<std::function<void(FuzzedDataProvider*, Parcel&)>> unaligned_operations = {
418    // error call ReadDouble after following methods, will crash with "signal SIGBUS: illegal alignment".
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
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
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".
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    },
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
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
482const 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.
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
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
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
507void 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 */
545extern "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