Added libHidlBase_parcel_fuzzer

Test: ./libHidlBase_parcel_fuzzer
exec/s: 1000
Bug: 193202093

Change-Id: I2e77ccc12afaaa76c45580676a6e916ea9924ebf
diff --git a/fuzzer/libHidlBase_parcel_fuzzer.cpp b/fuzzer/libHidlBase_parcel_fuzzer.cpp
new file mode 100644
index 0000000..88c20c3
--- /dev/null
+++ b/fuzzer/libHidlBase_parcel_fuzzer.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <hidl/HidlBinderSupport.h>
+#include <libHidlBase_fuzzer_helper.h>
+
+constexpr size_t kMinByte = 0;
+constexpr size_t kMaxByte = 256;
+constexpr uint32_t kNumFds = 0;
+constexpr uint32_t kNumInts = 1;
+constexpr uint32_t kMinSize = 1;
+constexpr uint32_t kMaxSize = 1000;
+constexpr uint32_t kMax = 1024;
+
+class HidlBaseParcelFuzzer {
+  public:
+    HidlBaseParcelFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    void createRandomParcel(Parcel& parcel);
+
+    FuzzedDataProvider mFdp;
+};
+
+void HidlBaseParcelFuzzer::createRandomParcel(Parcel& parcel) {
+    uint32_t iterCount = mFdp.ConsumeIntegralInRange<uint32_t>(kMin, kMax);
+    for (uint32_t idx = 0; idx < iterCount; ++idx) {
+        auto invokeHidlBaseParcelWriteAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    hidl_memory memory;
+                    native_handle_t* testNativeHandle = nullptr;
+                    if (mFdp.ConsumeBool()) {
+                        memory = createHidlMemory(mFdp);
+                    } else {
+                        hidl_string hidlString = createHidlString(mFdp);
+                        testNativeHandle = native_handle_create(
+                                mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_FDS),
+                                mFdp.ConsumeIntegralInRange<uint32_t>(kMin,
+                                                                      NATIVE_HANDLE_MAX_INTS));
+                        memory = hidl_memory(hidlString, testNativeHandle,
+                                             mFdp.ConsumeIntegral<uint64_t>());
+                    }
+                    writeEmbeddedToParcel(
+                            memory, &parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                    native_handle_close(testNativeHandle);
+                    native_handle_delete(testNativeHandle);
+                },
+                [&]() {
+                    MQDescriptorSync<uint8_t> descriptorSync;
+                    auto testHandle = native_handle_create(kNumFds, kNumInts);
+                    uint32_t size = sizeof(uint8_t);
+                    testHandle->data[0] = size;
+                    uint32_t bufferSize = mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize);
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<GrantorDescriptor> grantDescriptor(bufferSize);
+                        for (size_t idx = 0; idx < bufferSize; ++idx) {
+                            grantDescriptor[idx] = {mFdp.ConsumeIntegral<uint32_t>() /* flags */,
+                                                    mFdp.ConsumeIntegral<uint32_t>() /* fdIndex */,
+                                                    mFdp.ConsumeIntegral<uint32_t>() /* offset */,
+                                                    mFdp.ConsumeIntegral<uint64_t>() /* extent */};
+                        }
+                        descriptorSync =
+                                MQDescriptorSync<uint8_t>{grantDescriptor, testHandle, size};
+                    } else {
+                        descriptorSync = MQDescriptorSync<uint8_t>{bufferSize, testHandle, size,
+                                                                   mFdp.ConsumeBool()};
+                    }
+                    writeEmbeddedToParcel(
+                            descriptorSync, &parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    native_handle_t* testNativeHandle = native_handle_create(
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_FDS),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_INTS));
+                    writeEmbeddedToParcel(
+                            testNativeHandle, &parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                    native_handle_close(testNativeHandle);
+                    native_handle_delete(testNativeHandle);
+                },
+                [&]() {
+                    Status status = createStatus(mFdp);
+                    writeToParcel(status, &parcel);
+                },
+                [&]() {
+                    auto parcelSize = mFdp.ConsumeIntegralInRange<size_t>(kMinByte, kMaxByte);
+                    std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(parcelSize);
+                    parcel.write(data.data(), data.size());
+                },
+        });
+        invokeHidlBaseParcelWriteAPI();
+    }
+}
+
+void HidlBaseParcelFuzzer::process() {
+    Parcel parcel;
+    size_t originalPosition = parcel.dataPosition();
+    createRandomParcel(parcel);
+    parcel.setDataPosition(originalPosition);
+    while (mFdp.remaining_bytes()) {
+        auto invokeHidlBaseParcelAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    hidl_memory memory = createHidlMemory(mFdp);
+                    readEmbeddedFromParcel(
+                            memory, parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    MQDescriptorSync<uint8_t> descriptorSync;
+                    readEmbeddedFromParcel(
+                            descriptorSync, parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    hidl_handle handle;
+                    readEmbeddedFromParcel(
+                            handle, parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    hidl_string hidlString = createHidlString(mFdp);
+                    readEmbeddedFromParcel(
+                            hidlString, parcel,
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    Status status = createStatus(mFdp);
+                    readFromParcel(&status, parcel);
+                },
+        });
+        invokeHidlBaseParcelAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    HidlBaseParcelFuzzer hidlBaseParcelFuzzer(data, size);
+    hidlBaseParcelFuzzer.process();
+    return 0;
+}