1 /*
2 * Copyright (C) 2022 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 <VendorTagDescriptor.h>
18 #include <binder/Parcel.h>
19 #include <camera_metadata_tests_fake_vendor.h>
20 #include <fuzzer/FuzzedDataProvider.h>
21 #include <system/camera_vendor_tags.h>
22
23 #include <camera_metadata_hidden.h>
24 #include "camera2common.h"
25
26 using namespace std;
27 using namespace android;
28
29 constexpr int32_t kRangeMin = 0;
30 constexpr int32_t kRangeMax = 1000;
31 constexpr int32_t kVendorTagDescriptorId = -1;
32 constexpr int8_t kMinLoopIterations = 1;
33 constexpr int8_t kMaxLoopIterations = 50;
34
35 extern "C" {
36
zero_get_tag_count(const vendor_tag_ops_t *)37 static int zero_get_tag_count(const vendor_tag_ops_t*) {
38 return 0;
39 }
40
default_get_tag_count(const vendor_tag_ops_t *)41 static int default_get_tag_count(const vendor_tag_ops_t*) {
42 return VENDOR_TAG_COUNT_ERR;
43 }
44
default_get_all_tags(const vendor_tag_ops_t *,uint32_t *)45 static void default_get_all_tags(const vendor_tag_ops_t*, uint32_t*) {}
46
default_get_section_name(const vendor_tag_ops_t *,uint32_t)47 static const char* default_get_section_name(const vendor_tag_ops_t*, uint32_t) {
48 return VENDOR_SECTION_NAME_ERR;
49 }
50
default_get_tag_name(const vendor_tag_ops_t *,uint32_t)51 static const char* default_get_tag_name(const vendor_tag_ops_t*, uint32_t) {
52 return VENDOR_TAG_NAME_ERR;
53 }
54
default_get_tag_type(const vendor_tag_ops_t *,uint32_t)55 static int default_get_tag_type(const vendor_tag_ops_t*, uint32_t) {
56 return VENDOR_TAG_TYPE_ERR;
57 }
58
59 } /*extern "C"*/
60
FillWithDefaults(vendor_tag_ops_t * vOps)61 static void FillWithDefaults(vendor_tag_ops_t* vOps) {
62 vOps->get_tag_count = default_get_tag_count;
63 vOps->get_all_tags = default_get_all_tags;
64 vOps->get_section_name = default_get_section_name;
65 vOps->get_tag_name = default_get_tag_name;
66 vOps->get_tag_type = default_get_tag_type;
67 }
68
69 class VendorTagDescriptorFuzzer {
70 public:
71 void process(const uint8_t* data, size_t size);
~VendorTagDescriptorFuzzer()72 ~VendorTagDescriptorFuzzer() {
73 mVendorTagDescriptor.clear();
74 mVendorTagDescriptorCache.clear();
75 }
76
77 private:
78 void initVendorTagDescriptor();
79 void invokeVendorTagDescriptor();
80 void invokeVendorTagDescriptorCache();
81 void invokeVendorTagErrorConditions();
82 sp<VendorTagDescriptor> mVendorTagDescriptor = nullptr;
83 sp<VendorTagDescriptorCache> mVendorTagDescriptorCache = nullptr;
84 FuzzedDataProvider* mFDP = nullptr;
85 };
86
initVendorTagDescriptor()87 void VendorTagDescriptorFuzzer::initVendorTagDescriptor() {
88 if (mFDP->ConsumeBool()) {
89 mVendorTagDescriptor = new VendorTagDescriptor();
90 } else {
91 const vendor_tag_ops_t* vOps = &fakevendor_ops;
92 VendorTagDescriptor::createDescriptorFromOps(vOps, mVendorTagDescriptor);
93 }
94 }
95
invokeVendorTagDescriptor()96 void VendorTagDescriptorFuzzer::invokeVendorTagDescriptor() {
97 initVendorTagDescriptor();
98
99 sp<VendorTagDescriptor> vdesc = new VendorTagDescriptor();
100
101 int8_t count = mFDP->ConsumeIntegralInRange<int8_t>(kMinLoopIterations, kMaxLoopIterations);
102 while (--count > 0) {
103 auto callVendorTagDescriptor = mFDP->PickValueInArray<const std::function<void()>>({
104 [&]() {
105 int32_t tagCount = mVendorTagDescriptor->getTagCount();
106 if (tagCount > 0) {
107 uint32_t tagArray[tagCount];
108 mVendorTagDescriptor->getTagArray(tagArray);
109 uint32_t tag;
110 for (int32_t i = 0; i < tagCount; ++i) {
111 tag = tagArray[i];
112 get_local_camera_metadata_section_name_vendor_id(
113 tag, kVendorTagDescriptorId);
114 get_local_camera_metadata_tag_name_vendor_id(tag,
115 kVendorTagDescriptorId);
116 get_local_camera_metadata_tag_type_vendor_id(tag,
117 kVendorTagDescriptorId);
118 mVendorTagDescriptor->getSectionIndex(tag);
119 }
120 }
121 },
122 [&]() {
123 if (mVendorTagDescriptor->getTagCount() > 0) {
124 mVendorTagDescriptor->getAllSectionNames();
125 }
126 },
127 [&]() { vdesc->copyFrom(*mVendorTagDescriptor); },
128 [&]() {
129 VendorTagDescriptor::setAsGlobalVendorTagDescriptor(mVendorTagDescriptor);
130 },
131 [&]() { VendorTagDescriptor::getGlobalVendorTagDescriptor(); },
132 [&]() {
133 String8 name((mFDP->ConsumeRandomLengthString()).c_str());
134 String8 section((mFDP->ConsumeRandomLengthString()).c_str());
135 uint32_t lookupTag;
136 mVendorTagDescriptor->lookupTag(name, section, &lookupTag);
137 },
138 [&]() {
139 int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
140 int32_t verbosity = mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
141 int32_t indentation =
142 mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
143 mVendorTagDescriptor->dump(fd, verbosity, indentation);
144 close(fd);
145 },
146 });
147 callVendorTagDescriptor();
148 }
149
150 // Do not keep invokeReadWrite() APIs in while loop to avoid possible OOM.
151 if (mFDP->ConsumeBool()) {
152 invokeReadWriteParcelsp<VendorTagDescriptor>(mVendorTagDescriptor);
153 } else {
154 invokeNewReadWriteParcelsp<VendorTagDescriptor>(mVendorTagDescriptor, *mFDP);
155 }
156 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
157 }
158
invokeVendorTagDescriptorCache()159 void VendorTagDescriptorFuzzer::invokeVendorTagDescriptorCache() {
160 mVendorTagDescriptorCache = new VendorTagDescriptorCache();
161 uint64_t id = mFDP->ConsumeIntegral<uint64_t>();
162 initVendorTagDescriptor();
163
164 int8_t count = mFDP->ConsumeIntegralInRange<int8_t>(kMinLoopIterations, kMaxLoopIterations);
165 while (--count > 0) {
166 auto callVendorTagDescriptorCache = mFDP->PickValueInArray<const std::function<void()>>({
167 [&]() { mVendorTagDescriptorCache->addVendorDescriptor(id, mVendorTagDescriptor); },
168 [&]() {
169 VendorTagDescriptorCache::setAsGlobalVendorTagCache(mVendorTagDescriptorCache);
170 },
171 [&]() { VendorTagDescriptorCache::getGlobalVendorTagCache(); },
172 [&]() {
173 sp<VendorTagDescriptor> tagDesc;
174 mVendorTagDescriptorCache->getVendorTagDescriptor(id, &tagDesc);
175 },
176 [&]() {
177 int32_t tagCount = mVendorTagDescriptorCache->getTagCount(id);
178 if (tagCount > 0) {
179 uint32_t tagArray[tagCount];
180 mVendorTagDescriptorCache->getTagArray(tagArray, id);
181 uint32_t tag;
182 for (int32_t i = 0; i < tagCount; ++i) {
183 tag = tagArray[i];
184 get_local_camera_metadata_section_name_vendor_id(tag, id);
185 get_local_camera_metadata_tag_name_vendor_id(tag, id);
186 get_local_camera_metadata_tag_type_vendor_id(tag, id);
187 }
188 }
189 },
190 [&]() {
191 int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
192 int32_t verbosity = mFDP->ConsumeIntegralInRange<int>(kRangeMin, kRangeMax);
193 int32_t indentation = mFDP->ConsumeIntegralInRange<int>(kRangeMin, kRangeMax);
194 mVendorTagDescriptorCache->dump(fd, verbosity, indentation);
195 close(fd);
196 },
197 [&]() { VendorTagDescriptorCache::isVendorCachePresent(id); },
198 [&]() { mVendorTagDescriptorCache->getVendorIdsAndTagDescriptors(); },
199 });
200 callVendorTagDescriptorCache();
201 }
202
203 // Do not keep invokeReadWrite() APIs in while loop to avoid possible OOM.
204 if (mFDP->ConsumeBool()) {
205 invokeReadWriteParcelsp<VendorTagDescriptorCache>(mVendorTagDescriptorCache);
206 } else {
207 invokeNewReadWriteParcelsp<VendorTagDescriptorCache>(mVendorTagDescriptorCache, *mFDP);
208 }
209 mVendorTagDescriptorCache->clearGlobalVendorTagCache();
210 }
211
invokeVendorTagErrorConditions()212 void VendorTagDescriptorFuzzer::invokeVendorTagErrorConditions() {
213 sp<VendorTagDescriptor> vDesc;
214 vendor_tag_ops_t vOps;
215 FillWithDefaults(&vOps);
216 vOps.get_tag_count = zero_get_tag_count;
217
218 if (mFDP->ConsumeBool()) {
219 VendorTagDescriptor::createDescriptorFromOps(/*vOps*/ NULL, vDesc);
220 } else {
221 VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc);
222
223 int8_t count = mFDP->ConsumeIntegralInRange<int8_t>(kMinLoopIterations, kMaxLoopIterations);
224 while (--count > 0) {
225 int32_t tagCount = vDesc->getTagCount();
226 uint32_t badTag = mFDP->ConsumeIntegral<uint32_t>();
227 uint32_t badTagArray[tagCount + 1];
228 auto callVendorTagErrorConditions =
229 mFDP->PickValueInArray<const std::function<void()>>({
230 [&]() { vDesc->getTagArray(badTagArray); },
231 [&]() { vDesc->getSectionName(badTag); },
232 [&]() { vDesc->getTagName(badTag); },
233 [&]() { vDesc->getTagType(badTag); },
234 [&]() { VendorTagDescriptor::clearGlobalVendorTagDescriptor(); },
235 [&]() { VendorTagDescriptor::getGlobalVendorTagDescriptor(); },
236 [&]() { VendorTagDescriptor::setAsGlobalVendorTagDescriptor(vDesc); },
237 });
238 callVendorTagErrorConditions();
239 }
240 invokeReadWriteNullParcelsp<VendorTagDescriptor>(vDesc);
241 }
242 vDesc.clear();
243 }
244
process(const uint8_t * data,size_t size)245 void VendorTagDescriptorFuzzer::process(const uint8_t* data, size_t size) {
246 mFDP = new FuzzedDataProvider(data, size);
247 while (mFDP->remaining_bytes()) {
248 auto invokeVendorTagDescriptorFuzzer = mFDP->PickValueInArray<const std::function<void()>>({
249 [&]() { invokeVendorTagDescriptor(); },
250 [&]() { invokeVendorTagDescriptorCache(); },
251 [&]() { invokeVendorTagErrorConditions(); },
252 });
253 invokeVendorTagDescriptorFuzzer();
254 }
255 delete mFDP;
256 }
257
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)258 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
259 VendorTagDescriptorFuzzer vendorTagDescriptorFuzzer;
260 vendorTagDescriptorFuzzer.process(data, size);
261 return 0;
262 }
263