blob: 6fd2baf17ca2b43db9c988a82aaffd337062604c [file] [log] [blame]
Dylan Katz9d5845b2020-05-11 15:44:01 -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 */
Steven Moreland379d5c82023-07-01 00:27:23 +000016#include <fuzzer/FuzzedDataProvider.h>
17#include <utils/Log.h>
18#include <utils/Vector.h>
Dylan Katz9d5845b2020-05-11 15:44:01 -070019
Steven Moreland379d5c82023-07-01 00:27:23 +000020#include <functional>
Dylan Katz9d5845b2020-05-11 15:44:01 -070021
Steven Moreland379d5c82023-07-01 00:27:23 +000022using android::Vector;
23
24static constexpr uint16_t MAX_VEC_SIZE = 100;
25static constexpr bool kLog = false;
26
27struct NonTrivialDestructor {
28 NonTrivialDestructor() : mInit(1) {}
29 ~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);
Dylan Katz9d5845b2020-05-11 15:44:01 -070033 }
34
Steven Moreland379d5c82023-07-01 00:27:23 +000035 private:
36 uint8_t mInit;
37};
38
39template <typename T>
40struct VectorFuzzerData {
41 Vector<T> vector;
42 const std::vector<std::function<void(FuzzedDataProvider&, Vector<T>&)>> funcs = {
43 [&](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 },
49 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
50 (void)provider;
51 if (kLog) ALOGI("clear");
52 vector.clear();
53 },
54 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
55 (void)provider;
56 if (kLog) ALOGI("size");
57 vector.size();
58 },
59 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
60 (void)provider;
61 if (kLog) ALOGI("isEmpty");
62 vector.isEmpty();
63 },
64 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
65 (void)provider;
66 if (kLog) ALOGI("capacity");
67 vector.capacity();
68 },
69 [&](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 },
74 [&](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 },
79 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
80 (void)provider;
81 if (kLog) ALOGI("array");
82 vector.array();
83 },
84 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
85 (void)provider;
86 if (kLog) ALOGI("editArray");
87 vector.editArray();
88 },
89 [&](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 },
95 [&](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 },
101 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
102 (void)provider;
103 if (vector.size() == 0) return;
104 if (kLog) ALOGI("top");
105 vector.top();
106 },
107 [&](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 },
113 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
114 (void)provider;
115 if (vector.size() == 0) return;
116 if (kLog) ALOGI("editTop");
117 vector.editTop() = T{};
118 },
119 [&](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 },
126 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
127 if (kLog) ALOGI("appendVector");
128 vector.appendVector(testVector(provider));
129 },
130 // TODO: insertArrayAt
131 // TODO: appendArray
132 [&](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 },
138 [&](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 },
144 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
145 (void)provider;
146 if (vector.size() == 0) return;
147 if (kLog) ALOGI("pop");
148 vector.pop();
149 },
150 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
151 (void)provider;
152 if (kLog) ALOGI("push");
153 vector.push();
154 },
155 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
156 (void)provider;
157 if (kLog) ALOGI("add");
158 vector.add();
159 },
160 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
161 (void)provider;
162 if (kLog) ALOGI("add");
163 vector.add(T{});
164 },
165 [&](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 },
170 [&](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 },
175 [&](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
183 [&](FuzzedDataProvider& provider, Vector<T>& vector) {
184 (void)provider;
185 if (kLog) ALOGI("getItemSize");
186 vector.getItemSize();
187 },
188 // TODO: iterators
189 };
190
191 Vector<T> testVector(FuzzedDataProvider& provider) {
192 Vector<T> vec;
193 size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
194 return vec;
Dylan Katz9d5845b2020-05-11 15:44:01 -0700195 }
Steven Moreland379d5c82023-07-01 00:27:23 +0000196
197 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 }
Dylan Katz9d5845b2020-05-11 15:44:01 -0700202 }
Steven Moreland379d5c82023-07-01 00:27:23 +0000203};
204
Dylan Katz9d5845b2020-05-11 15:44:01 -0700205extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
Steven Moreland379d5c82023-07-01 00:27:23 +0000206 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
Dylan Katz9d5845b2020-05-11 15:44:01 -0700214 return 0;
215}