blob: 2a92531ee88633436ae486d2d9e68057ee2c20e7 [file] [log] [blame]
Dylan Katz7168f272020-07-02 11:51:44 -07001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <atomic>
18#include <thread>
19
20#include "fuzzer/FuzzedDataProvider.h"
21#include "utils/RefBase.h"
22#include "utils/StrongPointer.h"
23using android::RefBase;
24using android::sp;
25using android::wp;
26
27static constexpr int REFBASE_INITIAL_STRONG_VALUE = (1 << 28);
28static constexpr int REFBASE_MAX_COUNT = 0xfffff;
29
30static constexpr int MAX_OPERATIONS = 100;
31static constexpr int MAX_THREADS = 10;
32
33bool canDecrementStrong(RefBase* ref) {
34 // There's an assert around decrementing the strong count too much that causes an artificial
35 // crash This is just running BAD_STRONG from RefBase
36 const int32_t count = ref->getStrongCount() - 1;
37 return !(count == 0 || ((count) & (~(REFBASE_MAX_COUNT | REFBASE_INITIAL_STRONG_VALUE))) != 0);
38}
39bool canDecrementWeak(RefBase* ref) {
40 const int32_t count = ref->getWeakRefs()->getWeakCount() - 1;
41 return !((count) == 0 || ((count) & (~REFBASE_MAX_COUNT)) != 0);
42}
43
44struct RefBaseSubclass : public RefBase {
45 RefBaseSubclass() {}
46 virtual ~RefBaseSubclass() {}
47};
48
49std::vector<std::function<void(RefBaseSubclass*)>> operations = {
50 [](RefBaseSubclass* ref) -> void { ref->getStrongCount(); },
51 [](RefBaseSubclass* ref) -> void { ref->printRefs(); },
52 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->printRefs(); },
53 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->getWeakCount(); },
54 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->refBase(); },
55 [](RefBaseSubclass* ref) -> void { ref->incStrong(nullptr); },
56 [](RefBaseSubclass* ref) -> void {
57 if (canDecrementStrong(ref)) {
58 ref->decStrong(nullptr);
59 }
60 },
61 [](RefBaseSubclass* ref) -> void { ref->forceIncStrong(nullptr); },
62 [](RefBaseSubclass* ref) -> void { ref->createWeak(nullptr); },
63 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->attemptIncStrong(nullptr); },
64 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->attemptIncWeak(nullptr); },
65 [](RefBaseSubclass* ref) -> void {
66 if (canDecrementWeak(ref)) {
67 ref->getWeakRefs()->decWeak(nullptr);
68 }
69 },
70 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->incWeak(nullptr); },
71 [](RefBaseSubclass* ref) -> void { ref->getWeakRefs()->printRefs(); },
72};
73
74void loop(RefBaseSubclass* loopRef, const std::vector<uint8_t>& fuzzOps) {
75 for (auto op : fuzzOps) {
76 operations[op % operations.size()](loopRef);
77 }
78}
79
80void spawnThreads(FuzzedDataProvider* dataProvider) {
81 std::vector<std::thread> threads = std::vector<std::thread>();
82
83 // Get the number of threads to generate
84 uint8_t count = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_THREADS);
85
86 // Generate threads
87 for (uint8_t i = 0; i < count; i++) {
88 RefBaseSubclass* threadRef = new RefBaseSubclass();
89 uint8_t opCount = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_OPERATIONS);
90 std::vector<uint8_t> threadOperations = dataProvider->ConsumeBytes<uint8_t>(opCount);
91 std::thread tmp = std::thread(loop, threadRef, threadOperations);
92 threads.push_back(move(tmp));
93 }
94
95 for (auto& th : threads) {
96 th.join();
97 }
98}
99extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
100 FuzzedDataProvider dataProvider(data, size);
101 spawnThreads(&dataProvider);
102 return 0;
103}