/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "camera2common.h" using namespace std; using namespace android; using namespace android::hardware; constexpr int32_t kSizeMin = 0; constexpr int32_t kSizeMax = 1000; constexpr int32_t kMinMetadataCapacity = 0; constexpr int32_t kMaxMetadataCapacity = 1000; constexpr int32_t kRangeMin = 0; constexpr int32_t kRangeMax = 1000; class CameraMetadataFuzzer { public: void process(const uint8_t* data, size_t size); private: void initCameraMetadata(); void invokeCameraMetadata(); CameraMetadata* mCameraMetadata = nullptr; FuzzedDataProvider* mFDP = nullptr; camera_metadata* mMetaBuffer = nullptr; bool mMetadataLocked = false; template void callCameraMetadataUpdate(size_t dataCount, T data) { uint32_t tag = mFDP->ConsumeIntegral(); mCameraMetadata->update(tag, &data, dataCount); } }; void CameraMetadataFuzzer::initCameraMetadata() { auto selectMetadataConstructor = mFDP->PickValueInArray>({ [&]() { mMetaBuffer = allocate_camera_metadata( mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* entry_capacity */, mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* data_capacity */); mCameraMetadata = new CameraMetadata(mMetaBuffer); }, [&]() { mCameraMetadata = new CameraMetadata(); }, [&]() { size_t entryCapacity = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); size_t dataCapacity = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); mCameraMetadata = new CameraMetadata(entryCapacity, dataCapacity); }, }); selectMetadataConstructor(); } void CameraMetadataFuzzer::invokeCameraMetadata() { initCameraMetadata(); const camera_metadata_t* metadataBuffer = nullptr; mMetadataLocked = mFDP->ConsumeBool(); if (mMetadataLocked) { metadataBuffer = mCameraMetadata->getAndLock(); } size_t dataCount = 1; while (mFDP->remaining_bytes()) { auto callMetadataAPIs = mFDP->PickValueInArray>({ [&]() { mCameraMetadata->entryCount(); }, [&]() { mCameraMetadata->isEmpty(); }, [&]() { mCameraMetadata->bufferSize(); }, [&]() { mCameraMetadata->sort(); }, [&]() { uint8_t dataUint8 = mFDP->ConsumeIntegral(); callCameraMetadataUpdate(dataCount, dataUint8); }, [&]() { int32_t dataInt32 = mFDP->ConsumeIntegral(); callCameraMetadataUpdate(dataCount, dataInt32); }, [&]() { int64_t dataInt64 = mFDP->ConsumeIntegral(); callCameraMetadataUpdate(dataCount, dataInt64); }, [&]() { float dataFloat = mFDP->ConsumeFloatingPoint(); callCameraMetadataUpdate(dataCount, dataFloat); }, [&]() { double dataDouble = mFDP->ConsumeFloatingPoint(); callCameraMetadataUpdate(dataCount, dataDouble); }, [&]() { camera_metadata_rational dataRational; dataRational.numerator = mFDP->ConsumeIntegral(); dataRational.denominator = mFDP->ConsumeIntegral(); callCameraMetadataUpdate(dataCount, dataRational); }, [&]() { uint32_t tag = mFDP->ConsumeIntegral(); string dataStr = mFDP->ConsumeRandomLengthString(kMaxBytes); String8 dataString(dataStr.c_str()); mCameraMetadata->update(tag, dataString); }, [&]() { uint32_t tag = mFDP->ConsumeIntegral(); uint32_t tagExists = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->exists(tagExists); }, [&]() { uint32_t tag = mFDP->ConsumeIntegral(); uint32_t tagFind = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->find(tagFind); }, [&]() { uint32_t tag = mFDP->ConsumeIntegral(); uint32_t tagErase = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->erase(tagErase); }, [&]() { mCameraMetadata->unlock(metadataBuffer); }, [&]() { std::vector tagsRemoved; uint64_t vendorId = mFDP->ConsumeIntegral(); mCameraMetadata->removePermissionEntries(vendorId, &tagsRemoved); }, [&]() { string name = mFDP->ConsumeRandomLengthString(kMaxBytes); VendorTagDescriptor vTags; uint32_t tagName = mFDP->ConsumeIntegral(); mCameraMetadata->getTagFromName(name.c_str(), &vTags, &tagName); }, [&]() { int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT); int32_t verbosity = mFDP->ConsumeIntegralInRange(kRangeMin, kRangeMax); int32_t indentation = mFDP->ConsumeIntegralInRange(kRangeMin, kRangeMax); mCameraMetadata->dump(fd, verbosity, indentation); close(fd); }, [&]() { CameraMetadata metadataCopy(mCameraMetadata->release()); }, [&]() { if (mFDP->ConsumeBool()) { CameraMetadata otherCameraMetadata; mCameraMetadata->swap(otherCameraMetadata); } else { std::vector entryCapacityVector = mFDP->ConsumeBytes(kMaxBytes); /** * Resizing vector to a size between 1 to 1000 so that vector is not empty. */ entryCapacityVector.resize(0, mFDP->ConsumeIntegralInRange( kMinCapacity, kMaxCapacity)); CameraMetadata otherCameraMetadata(entryCapacityVector.size()); mCameraMetadata->swap(otherCameraMetadata); } }, [&]() { if (!mMetadataLocked) { camera_metadata* metaBuffer = allocate_camera_metadata( mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* entry_capacity */, mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* data_capacity */); mCameraMetadata->acquire(metaBuffer); } }, [&]() { if (!mMetadataLocked) { camera_metadata* metaBuffer = allocate_camera_metadata( mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* entry_capacity */, mFDP->ConsumeIntegralInRange( kMinMetadataCapacity, kMaxMetadataCapacity) /* data_capacity */); mCameraMetadata->append(metaBuffer); free_camera_metadata(metaBuffer); } }, }); callMetadataAPIs(); // Not keeping invokeReadWrite() APIs in while loop to avoid possible OOM. invokeReadWriteNullParcel(mCameraMetadata); if (mFDP->ConsumeBool()) { invokeReadWriteParcel(mCameraMetadata); } else { invokeNewReadWriteParcel(mCameraMetadata, *mFDP); } } delete mCameraMetadata; } void CameraMetadataFuzzer::process(const uint8_t* data, size_t size) { mFDP = new FuzzedDataProvider(data, size); invokeCameraMetadata(); delete mFDP; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { CameraMetadataFuzzer cameraMetadataFuzzer; cameraMetadataFuzzer.process(data, size); return 0; }