Add second batch of fuzzers for libutils
This adds fuzzers for:
- CallStack
- Looper
- LruCache
- Printer
- ProcessCallStack
- PropertyMap
- RWLock
- RefBase
- StopWatch.
Test: Ran each fuzzer for 10 minutes. Rough coverage est. (likely far below actual value): 10.97%
Signed-off-by: Dylan Katz <dylan.katz@leviathansecurity.com>
Change-Id: I2f9f35c18b13338c282fb7f9c3ea4099ecb2c56f
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 9bd15c6..05be220 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -205,6 +205,7 @@
shared_libs: [
"libutils",
"libbase",
+ "liblog",
],
}
@@ -238,6 +239,66 @@
srcs: ["Vector_fuzz.cpp"],
}
+cc_fuzz {
+ name: "libutils_fuzz_printer",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["Printer_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_callstack",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["CallStack_fuzz.cpp"],
+ shared_libs: [
+ "libutilscallstack",
+ ],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_process_callstack",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["ProcessCallStack_fuzz.cpp"],
+ shared_libs: [
+ "libutilscallstack",
+ ],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_stopwatch",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["StopWatch_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_propertymap",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["PropertyMap_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_rwlock",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["RWLock_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_refbase",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["RefBase_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_lrucache",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["LruCache_fuzz.cpp"],
+}
+
+cc_fuzz {
+ name: "libutils_fuzz_looper",
+ defaults: ["libutils_fuzz_defaults"],
+ srcs: ["Looper_fuzz.cpp"],
+}
+
cc_test {
name: "libutils_test",
host_supported: true,
diff --git a/libutils/CallStack_fuzz.cpp b/libutils/CallStack_fuzz.cpp
new file mode 100644
index 0000000..e89b5b7
--- /dev/null
+++ b/libutils/CallStack_fuzz.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 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 <memory.h>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/CallStack.h"
+
+static constexpr int MAX_STRING_SIZE = 500;
+static constexpr int MAX_IGNORE_DEPTH = 200;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ size_t ignoreDepth = dataProvider.ConsumeIntegralInRange<size_t>(0, MAX_IGNORE_DEPTH);
+ int logPriority = dataProvider.ConsumeIntegral<int>();
+ pid_t tid = dataProvider.ConsumeIntegral<pid_t>();
+ std::string logTag = dataProvider.ConsumeRandomLengthString(MAX_STRING_SIZE);
+ std::string prefix = dataProvider.ConsumeRandomLengthString(MAX_STRING_SIZE);
+
+ const char* logTagChars = logTag.c_str();
+ const char* prefixChars = prefix.c_str();
+
+ android::CallStack::CallStackUPtr callStack = android::CallStack::getCurrent(ignoreDepth);
+ android::CallStack* callstackPtr = callStack.get();
+ android::CallStack::logStack(logTagChars, callstackPtr,
+ static_cast<android_LogPriority>(logPriority));
+ android::CallStack::stackToString(prefixChars);
+
+ callstackPtr->log(logTagChars, static_cast<android_LogPriority>(logPriority), prefixChars);
+ callstackPtr->clear();
+ callstackPtr->getCurrent(ignoreDepth);
+ callstackPtr->log(logTagChars, static_cast<android_LogPriority>(logPriority), prefixChars);
+ callstackPtr->update(ignoreDepth, tid);
+ callstackPtr->log(logTagChars, static_cast<android_LogPriority>(logPriority), prefixChars);
+
+ return 0;
+}
diff --git a/libutils/Looper_fuzz.cpp b/libutils/Looper_fuzz.cpp
new file mode 100644
index 0000000..c3ae54e
--- /dev/null
+++ b/libutils/Looper_fuzz.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 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 <sys/select.h>
+
+#include <iostream>
+
+#include <utils/Looper.h>
+
+#include "Looper_test_pipe.h"
+#include "fuzzer/FuzzedDataProvider.h"
+
+using android::Looper;
+using android::sp;
+
+// We don't want this to bog down fuzzing
+static constexpr int MAX_POLL_DELAY = 50;
+static constexpr int MAX_OPERATIONS = 500;
+
+void doNothing() {}
+void* doNothingPointer = reinterpret_cast<void*>(doNothing);
+
+static int noopCallback(int, int, void*) {
+ return 0;
+}
+
+std::vector<std::function<void(FuzzedDataProvider*, sp<Looper>, Pipe)>> operations = {
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe) -> void {
+ looper->pollOnce(dataProvider->ConsumeIntegralInRange<int>(0, MAX_POLL_DELAY));
+ },
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe) -> void {
+ looper->pollAll(dataProvider->ConsumeIntegralInRange<int>(0, MAX_POLL_DELAY));
+ },
+ // events and callback are nullptr
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe pipeObj) -> void {
+ looper->addFd(pipeObj.receiveFd, dataProvider->ConsumeIntegral<int>(),
+ dataProvider->ConsumeIntegral<int>(), nullptr, nullptr);
+ },
+ // Events is nullptr
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe pipeObj) -> void {
+ looper->addFd(pipeObj.receiveFd, dataProvider->ConsumeIntegral<int>(),
+ dataProvider->ConsumeIntegral<int>(), noopCallback, nullptr);
+ },
+ // callback is nullptr
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe pipeObj) -> void {
+ looper->addFd(pipeObj.receiveFd, dataProvider->ConsumeIntegral<int>(),
+ dataProvider->ConsumeIntegral<int>(), nullptr, doNothingPointer);
+ },
+ // callback and events both set
+ [](FuzzedDataProvider* dataProvider, sp<Looper> looper, Pipe pipeObj) -> void {
+ looper->addFd(pipeObj.receiveFd, dataProvider->ConsumeIntegral<int>(),
+ dataProvider->ConsumeIntegral<int>(), noopCallback, doNothingPointer);
+ },
+
+ [](FuzzedDataProvider*, sp<Looper> looper, Pipe) -> void { looper->wake(); },
+ [](FuzzedDataProvider*, sp<Looper>, Pipe pipeObj) -> void { pipeObj.writeSignal(); }};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ Pipe pipeObj;
+ FuzzedDataProvider dataProvider(data, size);
+ sp<Looper> looper = new Looper(dataProvider.ConsumeBool());
+
+ size_t opsRun = 0;
+ while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
+ uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
+ operations[op](&dataProvider, looper, pipeObj);
+ }
+ // Clear our pointer
+ looper.clear();
+ return 0;
+}
diff --git a/libutils/Looper_test.cpp b/libutils/Looper_test.cpp
index 37bdf05..34f424b 100644
--- a/libutils/Looper_test.cpp
+++ b/libutils/Looper_test.cpp
@@ -2,12 +2,13 @@
// Copyright 2010 The Android Open Source Project
//
-#include <utils/Looper.h>
-#include <utils/Timers.h>
-#include <utils/StopWatch.h>
#include <gtest/gtest.h>
-#include <unistd.h>
#include <time.h>
+#include <unistd.h>
+#include <utils/Looper.h>
+#include <utils/StopWatch.h>
+#include <utils/Timers.h>
+#include "Looper_test_pipe.h"
#include <utils/threads.h>
@@ -24,41 +25,6 @@
MSG_TEST4 = 4,
};
-class Pipe {
-public:
- int sendFd;
- int receiveFd;
-
- Pipe() {
- int fds[2];
- ::pipe(fds);
-
- receiveFd = fds[0];
- sendFd = fds[1];
- }
-
- ~Pipe() {
- if (sendFd != -1) {
- ::close(sendFd);
- }
-
- if (receiveFd != -1) {
- ::close(receiveFd);
- }
- }
-
- status_t writeSignal() {
- ssize_t nWritten = ::write(sendFd, "*", 1);
- return nWritten == 1 ? 0 : -errno;
- }
-
- status_t readSignal() {
- char buf[1];
- ssize_t nRead = ::read(receiveFd, buf, 1);
- return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
- }
-};
-
class DelayedTask : public Thread {
int mDelayMillis;
diff --git a/libutils/Looper_test_pipe.h b/libutils/Looper_test_pipe.h
new file mode 100644
index 0000000..77b7b8b
--- /dev/null
+++ b/libutils/Looper_test_pipe.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+#include <unistd.h>
+/**
+ * A pipe class for use when testing or fuzzing Looper
+ */
+class Pipe {
+ public:
+ int sendFd;
+ int receiveFd;
+
+ Pipe() {
+ int fds[2];
+ ::pipe(fds);
+
+ receiveFd = fds[0];
+ sendFd = fds[1];
+ }
+
+ ~Pipe() {
+ if (sendFd != -1) {
+ ::close(sendFd);
+ }
+
+ if (receiveFd != -1) {
+ ::close(receiveFd);
+ }
+ }
+
+ android::status_t writeSignal() {
+ ssize_t nWritten = ::write(sendFd, "*", 1);
+ return nWritten == 1 ? 0 : -errno;
+ }
+
+ android::status_t readSignal() {
+ char buf[1];
+ ssize_t nRead = ::read(receiveFd, buf, 1);
+ return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
+ }
+};
diff --git a/libutils/LruCache_fuzz.cpp b/libutils/LruCache_fuzz.cpp
new file mode 100644
index 0000000..f8bacfc
--- /dev/null
+++ b/libutils/LruCache_fuzz.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020 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 <functional>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/LruCache.h"
+#include "utils/StrongPointer.h"
+
+typedef android::LruCache<size_t, size_t> FuzzCache;
+
+static constexpr uint32_t MAX_CACHE_ENTRIES = 800;
+
+class NoopRemovedCallback : public android::OnEntryRemoved<size_t, size_t> {
+ public:
+ void operator()(size_t&, size_t&) {
+ // noop
+ }
+};
+
+static NoopRemovedCallback callback;
+
+static const std::vector<std::function<void(FuzzedDataProvider*, FuzzCache*)>> operations = {
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void { cache->removeOldest(); },
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void { cache->peekOldestValue(); },
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void { cache->clear(); },
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void { cache->size(); },
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void {
+ android::LruCache<size_t, size_t>::Iterator iter(*cache);
+ while (iter.next()) {
+ iter.key();
+ iter.value();
+ }
+ },
+ [](FuzzedDataProvider* dataProvider, FuzzCache* cache) -> void {
+ size_t key = dataProvider->ConsumeIntegral<size_t>();
+ size_t val = dataProvider->ConsumeIntegral<size_t>();
+ cache->put(key, val);
+ },
+ [](FuzzedDataProvider* dataProvider, FuzzCache* cache) -> void {
+ size_t key = dataProvider->ConsumeIntegral<size_t>();
+ cache->get(key);
+ },
+ [](FuzzedDataProvider* dataProvider, FuzzCache* cache) -> void {
+ size_t key = dataProvider->ConsumeIntegral<size_t>();
+ cache->remove(key);
+ },
+ [](FuzzedDataProvider*, FuzzCache* cache) -> void {
+ cache->setOnEntryRemovedListener(&callback);
+ }};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ FuzzCache cache(MAX_CACHE_ENTRIES);
+ while (dataProvider.remaining_bytes() > 0) {
+ uint8_t op = dataProvider.ConsumeIntegral<uint8_t>() % operations.size();
+ operations[op](&dataProvider, &cache);
+ }
+
+ return 0;
+}
diff --git a/libutils/Printer_fuzz.cpp b/libutils/Printer_fuzz.cpp
new file mode 100755
index 0000000..0180d41
--- /dev/null
+++ b/libutils/Printer_fuzz.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 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 "android-base/file.h"
+#include "android/log.h"
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/Printer.h"
+#include "utils/String8.h"
+static constexpr int MAX_STR_SIZE = 1000;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ android::String8 outStr = android::String8();
+ // Line indent/formatting
+ uint indent = dataProvider.ConsumeIntegral<uint>();
+ std::string prefix = dataProvider.ConsumeRandomLengthString(MAX_STR_SIZE);
+ std::string line = dataProvider.ConsumeRandomLengthString(MAX_STR_SIZE);
+
+ // Misc properties
+ std::string logTag = dataProvider.ConsumeRandomLengthString(MAX_STR_SIZE);
+ android_LogPriority priority =
+ static_cast<android_LogPriority>(dataProvider.ConsumeIntegral<int>());
+ bool ignoreBlankLines = dataProvider.ConsumeBool();
+
+ TemporaryFile tf;
+ android::FdPrinter filePrinter = android::FdPrinter(tf.fd, indent, prefix.c_str());
+ android::String8Printer stringPrinter = android::String8Printer(&outStr);
+ android::PrefixPrinter printer = android::PrefixPrinter(stringPrinter, prefix.c_str());
+ android::LogPrinter logPrinter =
+ android::LogPrinter(logTag.c_str(), priority, prefix.c_str(), ignoreBlankLines);
+
+ printer.printLine(line.c_str());
+ printer.printFormatLine("%s", line.c_str());
+ logPrinter.printLine(line.c_str());
+ logPrinter.printFormatLine("%s", line.c_str());
+ filePrinter.printLine(line.c_str());
+ filePrinter.printFormatLine("%s", line.c_str());
+ return 0;
+}
diff --git a/libutils/ProcessCallStack_fuzz.cpp b/libutils/ProcessCallStack_fuzz.cpp
new file mode 100644
index 0000000..30136cd
--- /dev/null
+++ b/libutils/ProcessCallStack_fuzz.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 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 <atomic>
+#include <thread>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/ProcessCallStack.h"
+using android::ProcessCallStack;
+
+static constexpr int MAX_NAME_SIZE = 1000;
+static constexpr int MAX_LOG_META_SIZE = 1000;
+static constexpr uint8_t MAX_THREADS = 10;
+
+std::atomic_bool ranCallStackUpdate(false);
+void loop() {
+ while (!ranCallStackUpdate.load()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+}
+
+void spawnThreads(FuzzedDataProvider* dataProvider) {
+ std::vector<std::thread> threads = std::vector<std::thread>();
+
+ // Get the number of threads to generate
+ uint8_t count = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_THREADS);
+
+ // Generate threads
+ for (uint8_t i = 0; i < count; i++) {
+ std::string threadName =
+ dataProvider->ConsumeRandomLengthString(MAX_NAME_SIZE).append(std::to_string(i));
+ std::thread th = std::thread(loop);
+ pthread_setname_np(th.native_handle(), threadName.c_str());
+ threads.push_back(move(th));
+ }
+
+ // Collect thread information
+ ProcessCallStack callStack = ProcessCallStack();
+ callStack.update();
+
+ // Tell our patiently waiting threads they can be done now.
+ ranCallStackUpdate.store(true);
+
+ std::string logTag = dataProvider->ConsumeRandomLengthString(MAX_LOG_META_SIZE);
+ std::string prefix = dataProvider->ConsumeRandomLengthString(MAX_LOG_META_SIZE);
+ // Both of these, along with dump, all call print() under the hood,
+ // Which is covered by the Printer fuzzer.
+ callStack.log(logTag.c_str());
+ callStack.toString(prefix.c_str());
+
+ // Check size
+ callStack.size();
+
+ // wait for any remaining threads
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ spawnThreads(&dataProvider);
+ return 0;
+}
diff --git a/libutils/PropertyMap_fuzz.cpp b/libutils/PropertyMap_fuzz.cpp
new file mode 100755
index 0000000..fd50729
--- /dev/null
+++ b/libutils/PropertyMap_fuzz.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2020 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 "android-base/file.h"
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/PropertyMap.h"
+#include "utils/String8.h"
+
+static constexpr int MAX_FILE_SIZE = 256;
+static constexpr int MAX_STR_LEN = 2048;
+static constexpr int MAX_OPERATIONS = 1000;
+
+static const std::vector<std::function<void(FuzzedDataProvider*, android::PropertyMap)>>
+ operations = {
+ [](FuzzedDataProvider*, android::PropertyMap propertyMap) -> void {
+ propertyMap.getProperties();
+ },
+ [](FuzzedDataProvider*, android::PropertyMap propertyMap) -> void {
+ propertyMap.clear();
+ },
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
+ std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ android::String8 key = android::String8(keyStr.c_str());
+ propertyMap.hasProperty(key);
+ },
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
+ std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ android::String8 key = android::String8(keyStr.c_str());
+ android::String8 out;
+ propertyMap.tryGetProperty(key, out);
+ },
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
+ TemporaryFile tf;
+ // Generate file contents
+ std::string contents = dataProvider->ConsumeRandomLengthString(MAX_FILE_SIZE);
+ // If we have string contents, dump them into the file.
+ // Otherwise, just leave it as an empty file.
+ if (contents.length() > 0) {
+ const char* bytes = contents.c_str();
+ android::base::WriteStringToFd(bytes, tf.fd);
+ }
+ android::PropertyMap* mapPtr = &propertyMap;
+ android::PropertyMap::load(android::String8(tf.path), &mapPtr);
+ },
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
+ std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ std::string valStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ android::String8 key = android::String8(keyStr.c_str());
+ android::String8 val = android::String8(valStr.c_str());
+ propertyMap.addProperty(key, val);
+ },
+};
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ android::PropertyMap proprtyMap = android::PropertyMap();
+
+ int opsRun = 0;
+ while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
+ uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
+ operations[op](&dataProvider, proprtyMap);
+ }
+ return 0;
+}
diff --git a/libutils/RWLock_fuzz.cpp b/libutils/RWLock_fuzz.cpp
new file mode 100755
index 0000000..e075905
--- /dev/null
+++ b/libutils/RWLock_fuzz.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 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 <functional>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/RWLock.h"
+
+static constexpr int MAX_OPERATIONS = 100;
+static constexpr int MAX_NAME_LEN = 2048;
+
+static const std::vector<std::function<void(android::RWLock*)>> operations = {
+ [](android::RWLock* lock) -> void {
+ // This might return a non-zero value if already locked
+ // Either way we are definitely locked now.
+ lock->tryWriteLock();
+ },
+ [](android::RWLock* lock) -> void { lock->tryReadLock(); },
+ [](android::RWLock* lock) -> void { lock->unlock(); },
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ std::string nameStr = dataProvider.ConsumeRandomLengthString(MAX_NAME_LEN);
+ int type = dataProvider.ConsumeIntegral<int>();
+ android::RWLock rwLock = android::RWLock(type, nameStr.c_str());
+ std::vector<uint8_t> opsToRun = dataProvider.ConsumeRemainingBytes<uint8_t>();
+ int opsRun = 0;
+ for (auto it : opsToRun) {
+ if (opsRun++ >= MAX_OPERATIONS) {
+ break;
+ }
+ it = it % operations.size();
+ operations[it](&rwLock);
+ }
+ rwLock.unlock();
+ return 0;
+}
diff --git a/libutils/RefBase_fuzz.cpp b/libutils/RefBase_fuzz.cpp
new file mode 100755
index 0000000..2a92531
--- /dev/null
+++ b/libutils/RefBase_fuzz.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020 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 <atomic>
+#include <thread>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "utils/RefBase.h"
+#include "utils/StrongPointer.h"
+using android::RefBase;
+using android::sp;
+using android::wp;
+
+static constexpr int REFBASE_INITIAL_STRONG_VALUE = (1 << 28);
+static constexpr int REFBASE_MAX_COUNT = 0xfffff;
+
+static constexpr int MAX_OPERATIONS = 100;
+static constexpr int MAX_THREADS = 10;
+
+bool canDecrementStrong(RefBase* ref) {
+ // There's an assert around decrementing the strong count too much that causes an artificial
+ // crash This is just running BAD_STRONG from RefBase
+ const int32_t count = ref->getStrongCount() - 1;
+ return !(count == 0 || ((count) & (~(REFBASE_MAX_COUNT | REFBASE_INITIAL_STRONG_VALUE))) != 0);
+}
+bool canDecrementWeak(RefBase* ref) {
+ const int32_t count = ref->getWeakRefs()->getWeakCount() - 1;
+ return !((count) == 0 || ((count) & (~REFBASE_MAX_COUNT)) != 0);
+}
+
+struct RefBaseSubclass : public RefBase {
+ RefBaseSubclass() {}
+ virtual ~RefBaseSubclass() {}
+};
+
+std::vector<std::function<void(RefBaseSubclass*)>> operations = {
+ [](RefBaseSubclass* ref) -> void { ref->getStrongCount(); },
+ [](RefBaseSubclass* ref) -> void { ref->printRefs(); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->printRefs(); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->getWeakCount(); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->refBase(); },
+ [](RefBaseSubclass* ref) -> void { ref->incStrong(nullptr); },
+ [](RefBaseSubclass* ref) -> void {
+ if (canDecrementStrong(ref)) {
+ ref->decStrong(nullptr);
+ }
+ },
+ [](RefBaseSubclass* ref) -> void { ref->forceIncStrong(nullptr); },
+ [](RefBaseSubclass* ref) -> void { ref->createWeak(nullptr); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->attemptIncStrong(nullptr); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->attemptIncWeak(nullptr); },
+ [](RefBaseSubclass* ref) -> void {
+ if (canDecrementWeak(ref)) {
+ ref->getWeakRefs()->decWeak(nullptr);
+ }
+ },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->incWeak(nullptr); },
+ [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->printRefs(); },
+};
+
+void loop(RefBaseSubclass* loopRef, const std::vector<uint8_t>& fuzzOps) {
+ for (auto op : fuzzOps) {
+ operations[op % operations.size()](loopRef);
+ }
+}
+
+void spawnThreads(FuzzedDataProvider* dataProvider) {
+ std::vector<std::thread> threads = std::vector<std::thread>();
+
+ // Get the number of threads to generate
+ uint8_t count = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_THREADS);
+
+ // Generate threads
+ for (uint8_t i = 0; i < count; i++) {
+ RefBaseSubclass* threadRef = new RefBaseSubclass();
+ uint8_t opCount = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_OPERATIONS);
+ std::vector<uint8_t> threadOperations = dataProvider->ConsumeBytes<uint8_t>(opCount);
+ std::thread tmp = std::thread(loop, threadRef, threadOperations);
+ threads.push_back(move(tmp));
+ }
+
+ for (auto& th : threads) {
+ th.join();
+ }
+}
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ spawnThreads(&dataProvider);
+ return 0;
+}
diff --git a/libutils/StopWatch_fuzz.cpp b/libutils/StopWatch_fuzz.cpp
new file mode 100644
index 0000000..63d8a28
--- /dev/null
+++ b/libutils/StopWatch_fuzz.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 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"
+#include "utils/StopWatch.h"
+
+static constexpr int MAX_OPERATIONS = 100;
+static constexpr int MAX_NAME_LEN = 2048;
+
+static const std::vector<std::function<void(android::StopWatch)>> operations = {
+ [](android::StopWatch stopWatch) -> void { stopWatch.reset(); },
+ [](android::StopWatch stopWatch) -> void { stopWatch.lap(); },
+ [](android::StopWatch stopWatch) -> void { stopWatch.elapsedTime(); },
+ [](android::StopWatch stopWatch) -> void { stopWatch.name(); },
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ std::string nameStr = dataProvider.ConsumeRandomLengthString(MAX_NAME_LEN);
+ int clockVal = dataProvider.ConsumeIntegral<int>();
+ android::StopWatch stopWatch = android::StopWatch(nameStr.c_str(), clockVal);
+ std::vector<uint8_t> opsToRun = dataProvider.ConsumeRemainingBytes<uint8_t>();
+ int opsRun = 0;
+ for (auto it : opsToRun) {
+ if (opsRun++ >= MAX_OPERATIONS) {
+ break;
+ }
+ it = it % operations.size();
+ operations[it](stopWatch);
+ }
+ return 0;
+}