From 7168f2726eccdc00210ba59563a4ed3b821cca9d Mon Sep 17 00:00:00 2001 From: Dylan Katz Date: Thu, 2 Jul 2020 11:51:44 -0700 Subject: 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 Change-Id: I2f9f35c18b13338c282fb7f9c3ea4099ecb2c56f --- libutils/RefBase_fuzz.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 libutils/RefBase_fuzz.cpp (limited to 'libutils/RefBase_fuzz.cpp') diff --git a/libutils/RefBase_fuzz.cpp b/libutils/RefBase_fuzz.cpp new file mode 100755 index 000000000..2a92531ee --- /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 +#include + +#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> 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& fuzzOps) { + for (auto op : fuzzOps) { + operations[op % operations.size()](loopRef); + } +} + +void spawnThreads(FuzzedDataProvider* dataProvider) { + std::vector threads = std::vector(); + + // Get the number of threads to generate + uint8_t count = dataProvider->ConsumeIntegralInRange(1, MAX_THREADS); + + // Generate threads + for (uint8_t i = 0; i < count; i++) { + RefBaseSubclass* threadRef = new RefBaseSubclass(); + uint8_t opCount = dataProvider->ConsumeIntegralInRange(1, MAX_OPERATIONS); + std::vector threadOperations = dataProvider->ConsumeBytes(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; +} -- cgit v1.2.3