1 /*
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 #include <fuzzer/FuzzedDataProvider.h>
17 #include <log/log.h>
18 #include <utils/Vector.h>
19
20 #include <functional>
21
22 using android::Vector;
23
24 static constexpr uint16_t MAX_VEC_SIZE = 100;
25 static constexpr bool kLog = false;
26
27 struct NonTrivialDestructor {
NonTrivialDestructorNonTrivialDestructor28 NonTrivialDestructor() : mInit(1) {}
~NonTrivialDestructorNonTrivialDestructor29 ~NonTrivialDestructor() {
30 LOG_ALWAYS_FATAL_IF(mInit != 1, "mInit should be 1, but it's: %d", mInit);
31 mInit--;
32 LOG_ALWAYS_FATAL_IF(mInit != 0, "mInit should be 0, but it's: %d", mInit);
33 }
34
35 private:
36 uint8_t mInit;
37 };
38
39 template <typename T>
40 struct VectorFuzzerData {
41 Vector<T> vector;
42 const std::vector<std::function<void(FuzzedDataProvider&, Vector<T>&)>> funcs = {
__anond5f1cc6d0102VectorFuzzerData43 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
44 (void)provider;
45 // operator= Vector<TYPE>, still needs for SortedVector
46 if (kLog) ALOGI("operator=");
47 vector = testVector(provider);
48 },
__anond5f1cc6d0202VectorFuzzerData49 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
50 (void)provider;
51 if (kLog) ALOGI("clear");
52 vector.clear();
53 },
__anond5f1cc6d0302VectorFuzzerData54 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
55 (void)provider;
56 if (kLog) ALOGI("size");
57 vector.size();
58 },
__anond5f1cc6d0402VectorFuzzerData59 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
60 (void)provider;
61 if (kLog) ALOGI("isEmpty");
62 vector.isEmpty();
63 },
__anond5f1cc6d0502VectorFuzzerData64 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
65 (void)provider;
66 if (kLog) ALOGI("capacity");
67 vector.capacity();
68 },
__anond5f1cc6d0602VectorFuzzerData69 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
70 size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
71 if (kLog) ALOGI("setCapacity");
72 vector.setCapacity(vectorSize);
73 },
__anond5f1cc6d0702VectorFuzzerData74 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
75 size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
76 if (kLog) ALOGI("resize");
77 vector.resize(vectorSize);
78 },
__anond5f1cc6d0802VectorFuzzerData79 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
80 (void)provider;
81 if (kLog) ALOGI("array");
82 vector.array();
83 },
__anond5f1cc6d0902VectorFuzzerData84 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
85 (void)provider;
86 if (kLog) ALOGI("editArray");
87 vector.editArray();
88 },
__anond5f1cc6d0a02VectorFuzzerData89 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
90 if (vector.size() == 0) return;
91 size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
92 if (kLog) ALOGI("operator[]");
93 vector[idx]; // returns a const value for Vector
94 },
__anond5f1cc6d0b02VectorFuzzerData95 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
96 if (vector.size() == 0) return;
97 size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
98 if (kLog) ALOGI("itemAt");
99 vector.itemAt(idx);
100 },
__anond5f1cc6d0c02VectorFuzzerData101 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
102 (void)provider;
103 if (vector.size() == 0) return;
104 if (kLog) ALOGI("top");
105 vector.top();
106 },
__anond5f1cc6d0d02VectorFuzzerData107 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
108 if (vector.size() == 0) return;
109 size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
110 if (kLog) ALOGI("editItemAt");
111 vector.editItemAt(idx);
112 },
__anond5f1cc6d0e02VectorFuzzerData113 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
114 (void)provider;
115 if (vector.size() == 0) return;
116 if (kLog) ALOGI("editTop");
117 vector.editTop() = T{};
118 },
__anond5f1cc6d0f02VectorFuzzerData119 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
120 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
121 Vector vec2 = testVector(provider);
122 if (vec2.size() == 0) return; // TODO: maybe we should support this?
123 if (kLog) ALOGI("insertVectorAt %d of size %zu", idx, vec2.size());
124 vector.insertVectorAt(vec2, idx);
125 },
__anond5f1cc6d1002VectorFuzzerData126 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
127 if (kLog) ALOGI("appendVector");
128 vector.appendVector(testVector(provider));
129 },
130 // TODO: insertArrayAt
131 // TODO: appendArray
__anond5f1cc6d1102VectorFuzzerData132 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
133 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
134 uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
135 if (kLog) ALOGI("insertAt");
136 vector.insertAt(idx, numItems);
137 },
__anond5f1cc6d1202VectorFuzzerData138 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
139 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
140 uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
141 if (kLog) ALOGI("insertAt");
142 vector.insertAt(T{}, idx, numItems);
143 },
__anond5f1cc6d1302VectorFuzzerData144 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
145 (void)provider;
146 if (vector.size() == 0) return;
147 if (kLog) ALOGI("pop");
148 vector.pop();
149 },
__anond5f1cc6d1402VectorFuzzerData150 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
151 (void)provider;
152 if (kLog) ALOGI("push");
153 vector.push();
154 },
__anond5f1cc6d1502VectorFuzzerData155 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
156 (void)provider;
157 if (kLog) ALOGI("add");
158 vector.add();
159 },
__anond5f1cc6d1602VectorFuzzerData160 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
161 (void)provider;
162 if (kLog) ALOGI("add");
163 vector.add(T{});
164 },
__anond5f1cc6d1702VectorFuzzerData165 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
166 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
167 if (kLog) ALOGI("replaceAt");
168 vector.replaceAt(idx);
169 },
__anond5f1cc6d1802VectorFuzzerData170 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
171 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
172 if (kLog) ALOGI("replaceAt");
173 vector.replaceAt(T{}, idx);
174 },
__anond5f1cc6d1902VectorFuzzerData175 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
176 if (vector.size() == 0) return;
177 uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
178 if (kLog) ALOGI("remoteItemsAt");
179 vector.removeItemsAt(idx); // TODO: different count
180 },
181 // removeAt is alias for removeItemsAt
182 // TODO: sort
__anond5f1cc6d1a02VectorFuzzerData183 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
184 (void)provider;
185 if (kLog) ALOGI("getItemSize");
186 vector.getItemSize();
187 },
188 // TODO: iterators
189 };
190
testVectorVectorFuzzerData191 Vector<T> testVector(FuzzedDataProvider& provider) {
192 Vector<T> vec;
193 size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
194 return vec;
195 }
196
fuzzVectorFuzzerData197 void fuzz(FuzzedDataProvider&& provider) {
198 while (provider.remaining_bytes()) {
199 size_t funcIdx = provider.ConsumeIntegralInRange<size_t>(0, funcs.size() - 1);
200 funcs[funcIdx](provider, vector);
201 }
202 }
203 };
204
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)205 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
206 FuzzedDataProvider provider(data, size);
207
208 provider.PickValueInArray<std::function<void()>>({
209 [&]() { VectorFuzzerData<uint8_t>().fuzz(std::move(provider)); },
210 [&]() { VectorFuzzerData<int32_t>().fuzz(std::move(provider)); },
211 [&]() { VectorFuzzerData<NonTrivialDestructor>().fuzz(std::move(provider)); },
212 })();
213
214 return 0;
215 }
216