xref: /aosp_15_r20/frameworks/av/camera/tests/fuzzer/camera_vendorTagDescriptor_fuzzer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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