inputflinger_input_reader_fuzzer: Bug Fix

Resolved OOB read getting triggered due to FuzzedDataProvider's
shared_ptr which is used among different classes. Implemented
ThreadSafe instance of FuzzedDataProvider as bug-fix.

Test: ./inputflinger_input_reader_fuzzer clusterfuzz-testcase
-minimized-inputflinger_input_reader_fuzzer-6227827124207616
Test: ./inputflinger_input_reader_fuzzer clusterfuzz-testcase
-minimized-inputflinger_input_reader_fuzzer-5394273856782336

Bug: 253728999
Bug: 254590389

Change-Id: I42d53d1d7da18c8085d381c939bedf14fe18dc87
(cherry picked from commit 08aa517eee8e7cdf65bf0bd303239e25ed1d50e8)
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
index cc523e1..be85026 100644
--- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -16,11 +16,10 @@
 
 #include <CursorInputMapper.h>
 #include <FuzzContainer.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
-static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) {
     // Pick a random property to set for the mapper to have set.
     fdp->PickValueInArray<std::function<void()>>(
             {[&]() -> void { fuzzer.addProperty("cursor.mode", "pointer"); },
@@ -35,7 +34,8 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
-    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
+            std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
     FuzzContainer fuzzer(fdp);
 
     CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>();
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
index 1e0764f..76d2bcd 100644
--- a/services/inputflinger/tests/fuzzers/FuzzContainer.h
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -20,7 +20,6 @@
 #include <InputMapper.h>
 #include <InputReader.h>
 #include <MapperHelpers.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
@@ -31,10 +30,10 @@
     std::unique_ptr<FuzzInputReaderContext> mFuzzContext;
     std::unique_ptr<InputDevice> mFuzzDevice;
     InputReaderConfiguration mPolicyConfig;
-    std::shared_ptr<FuzzedDataProvider> mFdp;
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 public:
-    FuzzContainer(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(fdp) {
+    FuzzContainer(std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) : mFdp(fdp) {
         // Setup parameters.
         std::string deviceName = mFdp->ConsumeRandomLengthString(16);
         std::string deviceLocation = mFdp->ConsumeRandomLengthString(12);
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index 2eed997..d100a57 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -166,7 +166,8 @@
 };
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
-    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
+            std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
 
     FuzzInputListener fuzzListener;
     sp<FuzzInputReaderPolicy> fuzzPolicy = sp<FuzzInputReaderPolicy>::make(fdp);
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
index e880f55..8e2d677 100644
--- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -16,13 +16,12 @@
 
 #include <FuzzContainer.h>
 #include <KeyboardInputMapper.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
 const int32_t kMaxKeycodes = 100;
 
-static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) {
     // Pick a random property to set for the mapper to have set.
     fdp->PickValueInArray<std::function<void()>>(
             {[&]() -> void { fuzzer.addProperty("keyboard.orientationAware", "1"); },
@@ -41,7 +40,8 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
-    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
+            std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
     FuzzContainer fuzzer(fdp);
 
     KeyboardInputMapper& mapper =
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 445ed18..81e4816 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -13,13 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <InputDevice.h>
 #include <InputMapper.h>
 #include <InputReader.h>
-#include <fuzzer/FuzzedDataProvider.h>
+#include <ThreadSafeFuzzedDataProvider.h>
 #include "android/hardware/input/InputDeviceCountryCode.h"
 
 using android::hardware::input::InputDeviceCountryCode;
@@ -114,10 +113,10 @@
     InputDeviceIdentifier mIdentifier;
     std::vector<TouchVideoFrame> mVideoFrames;
     PropertyMap mFuzzConfig;
-    std::shared_ptr<FuzzedDataProvider> mFdp;
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 public:
-    FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {}
+    FuzzEventHub(std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {}
     ~FuzzEventHub() {}
     void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); }
 
@@ -263,10 +262,10 @@
 };
 
 class FuzzPointerController : public PointerControllerInterface {
-    std::shared_ptr<FuzzedDataProvider> mFdp;
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 public:
-    FuzzPointerController(std::shared_ptr<FuzzedDataProvider> mFdp) : mFdp(mFdp) {}
+    FuzzPointerController(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
     ~FuzzPointerController() {}
     bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
         return mFdp->ConsumeBool();
@@ -289,13 +288,13 @@
 class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
     TouchAffineTransformation mTransform;
     std::shared_ptr<FuzzPointerController> mPointerController;
-    std::shared_ptr<FuzzedDataProvider> mFdp;
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 protected:
     ~FuzzInputReaderPolicy() {}
 
 public:
-    FuzzInputReaderPolicy(std::shared_ptr<FuzzedDataProvider> mFdp) : mFdp(mFdp) {
+    FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {
         mPointerController = std::make_shared<FuzzPointerController>(mFdp);
     }
     void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
@@ -333,13 +332,13 @@
 class FuzzInputReaderContext : public InputReaderContext {
     std::shared_ptr<EventHubInterface> mEventHub;
     sp<InputReaderPolicyInterface> mPolicy;
-    std::shared_ptr<FuzzedDataProvider> mFdp;
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
 
 public:
     FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
                            const sp<InputReaderPolicyInterface>& policy,
                            InputListenerInterface& listener,
-                           std::shared_ptr<FuzzedDataProvider> mFdp)
+                           std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp)
           : mEventHub(eventHub), mPolicy(policy), mFdp(mFdp) {}
     ~FuzzInputReaderContext() {}
     void updateGlobalMetaState() override {}
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
index 99fd083..011455b 100644
--- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -16,13 +16,12 @@
 
 #include <FuzzContainer.h>
 #include <MultiTouchInputMapper.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
 const int32_t kMaxKeycodes = 100;
 
-static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) {
     // Pick a random property to set for the mapper to have set.
     fdp->PickValueInArray<std::function<void()>>(
             {[&]() -> void { fuzzer.addProperty("touch.deviceType", "touchScreen"); },
@@ -58,7 +57,8 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
-    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
+            std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
     FuzzContainer fuzzer(fdp);
 
     MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>();
diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
index 7416ce9..c4938f2 100644
--- a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
@@ -16,12 +16,12 @@
 
 #include <FuzzContainer.h>
 #include <SwitchInputMapper.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
-    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
+            std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
     FuzzContainer fuzzer(fdp);
 
     SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>();
diff --git a/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h b/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h
new file mode 100644
index 0000000..2f76f18
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2022 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 <fuzzer/FuzzedDataProvider.h>
+
+/**
+ * A thread-safe interface to the FuzzedDataProvider
+ */
+class ThreadSafeFuzzedDataProvider : FuzzedDataProvider {
+private:
+    std::mutex mLock;
+
+public:
+    ThreadSafeFuzzedDataProvider(const uint8_t* data, size_t size)
+          : FuzzedDataProvider(data, size) {}
+
+    template <typename T>
+    std::vector<T> ConsumeBytes(size_t num_bytes) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeBytes<T>(num_bytes);
+    }
+
+    template <typename T>
+    std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeBytesWithTerminator<T>(num_bytes, terminator);
+    }
+
+    template <typename T>
+    std::vector<T> ConsumeRemainingBytes() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeRemainingBytes<T>();
+    }
+
+    std::string ConsumeBytesAsString(size_t num_bytes) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeBytesAsString(num_bytes);
+    }
+
+    std::string ConsumeRandomLengthString(size_t max_length) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeRandomLengthString(max_length);
+    }
+
+    std::string ConsumeRandomLengthString() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeRandomLengthString();
+    }
+
+    std::string ConsumeRemainingBytesAsString() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeRemainingBytesAsString();
+    }
+
+    template <typename T>
+    T ConsumeIntegral() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeIntegral<T>();
+    }
+
+    template <typename T>
+    T ConsumeIntegralInRange(T min, T max) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeIntegralInRange<T>(min, max);
+    }
+
+    template <typename T>
+    T ConsumeFloatingPoint() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeFloatingPoint<T>();
+    }
+
+    template <typename T>
+    T ConsumeFloatingPointInRange(T min, T max) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeFloatingPointInRange<T>(min, max);
+    }
+
+    template <typename T>
+    T ConsumeProbability() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeProbability<T>();
+    }
+
+    bool ConsumeBool() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeBool();
+    }
+
+    template <typename T>
+    T ConsumeEnum() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeEnum<T>();
+    }
+
+    template <typename T, size_t size>
+    T PickValueInArray(const T (&array)[size]) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::PickValueInArray(array);
+    }
+
+    template <typename T, size_t size>
+    T PickValueInArray(const std::array<T, size>& array) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::PickValueInArray(array);
+    }
+
+    template <typename T>
+    T PickValueInArray(std::initializer_list<const T> list) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::PickValueInArray(list);
+    }
+
+    size_t ConsumeData(void* destination, size_t num_bytes) {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::ConsumeData(destination, num_bytes);
+    }
+
+    size_t remaining_bytes() {
+        std::scoped_lock _l(mLock);
+        return FuzzedDataProvider::remaining_bytes();
+    }
+};