Added libHidlBase_parcel_fuzzer

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

Change-Id: I2e77ccc12afaaa76c45580676a6e916ea9924ebf
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
new file mode 100644
index 0000000..5f95ce7
--- /dev/null
+++ b/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+cc_defaults {
+    name: "libHidlBase_fuzzer_defaults",
+    host_supported: true,
+    static_libs: [
+        "libhidlbase",
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libprocessgroup",
+        "libjsoncpp",
+        "libcgrouprc",
+        "libcgrouprc_format",
+        "libfmq",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libvndksupport",
+            ],
+        },
+    },
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzers target the APIs of libhidlbase library",
+        vector: "local_no_privileges_required",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
+    },
+}
+
+cc_fuzz {
+    name: "libHidlBase_parcel_fuzzer",
+    srcs: ["libHidlBase_parcel_fuzzer.cpp",],
+    defaults: ["libHidlBase_fuzzer_defaults"],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
new file mode 100644
index 0000000..709cc19
--- /dev/null
+++ b/fuzzer/README.md
@@ -0,0 +1,29 @@
+# Fuzzer for libhidlbase
+
+## Table of contents
++ [libHidlBase_parcel_fuzzer](#libHidlBaseParcel)
+
+# <a name="libHidlBaseParcel"></a> Fuzzer for libHidlBaseParcel
+
+libHidlBaseParcel supports the following parameters:
+
+1. ParentHandle (parameter name: "parentHandle")
+2. ParentOffset (parameter name: "parentOffset")
+3. HidlString (parameter name: "hidlString")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`parentHandle`| `Integer` |Value obtained from FuzzedDataProvider|
+|`parentOffset`| `Integer` |Value obtained from FuzzedDataProvider|
+|`hidlString`| `Structure` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ make libHidlBase_parcel_fuzzer
+```
+2. To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/libHidlBase_parcel_fuzzer/libHidlBase_parcel_fuzzer
+```
diff --git a/fuzzer/libHidlBase_fuzzer_helper.h b/fuzzer/libHidlBase_fuzzer_helper.h
new file mode 100644
index 0000000..53726dc
--- /dev/null
+++ b/fuzzer/libHidlBase_fuzzer_helper.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _LIBHIDLBASE_FUZZER_HELPER_H
+#define _LIBHIDLBASE_FUZZER_HELPER_H
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl/HidlBinderSupport.h>
+
+using namespace android;
+using namespace hardware;
+using namespace details;
+
+constexpr uint32_t kMaxBytes = 256;
+constexpr uint32_t kMin = 0;
+
+hidl_string createHidlString(FuzzedDataProvider& fdp) {
+    auto invokeHidlString = fdp.PickValueInArray<const std::function<hidl_string()>>({
+            [&]() { return hidl_string(fdp.ConsumeRandomLengthString(kMaxBytes)); },
+            [&]() { return hidl_string((fdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); },
+            [&]() {
+                std::string testString = fdp.ConsumeRandomLengthString(kMaxBytes);
+                return hidl_string(testString.c_str(),
+                                   fdp.ConsumeIntegralInRange<uint32_t>(kMin, testString.length()));
+            },
+            [&]() { return fdp.ConsumeRandomLengthString(kMaxBytes); },
+    });
+    return invokeHidlString();
+}
+
+hidl_memory createHidlMemory(FuzzedDataProvider& fdp) {
+    if (fdp.ConsumeBool()) {
+        return hidl_memory();
+    }
+    return hidl_memory(createHidlString(fdp), hidl_handle(),
+                       fdp.ConsumeIntegral<uint64_t>() /* size */);
+}
+
+Status createStatus(FuzzedDataProvider& fdp) {
+    auto invokeStatus = fdp.PickValueInArray<const std::function<Status()>>({
+            [&]() { return Status::fromExceptionCode(fdp.ConsumeIntegral<uint32_t>()); },
+            [&]() {
+                return Status::fromExceptionCode(
+                        fdp.ConsumeIntegral<uint32_t>(),
+                        (fdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
+            },
+            [&]() { return Status::fromStatusT(fdp.ConsumeIntegral<uint32_t>()); },
+            [&]() { return Status(); },
+    });
+    return invokeStatus();
+}
+
+#endif  // _LIBHIDLBASE_FUZZER_HELPER_H
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;
+}