blob: a609e19d3489ded058083ceb284b07626d318e7e [file] [log] [blame]
/*
* 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 <CameraBase.h>
#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 <typename T>
void callCameraMetadataUpdate(size_t dataCount, T data) {
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->update(tag, &data, dataCount);
}
};
void CameraMetadataFuzzer::initCameraMetadata() {
auto selectMetadataConstructor = mFDP->PickValueInArray<const std::function<void()>>({
[&]() {
mMetaBuffer = allocate_camera_metadata(
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity, kMaxMetadataCapacity) /* entry_capacity */,
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity, kMaxMetadataCapacity) /* data_capacity */);
mCameraMetadata = new CameraMetadata(mMetaBuffer);
},
[&]() {
mCameraMetadata = new CameraMetadata();
},
[&]() {
size_t entryCapacity = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
size_t dataCapacity = mFDP->ConsumeIntegralInRange<size_t>(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<const std::function<void()>>({
[&]() { mCameraMetadata->entryCount(); },
[&]() { mCameraMetadata->isEmpty(); },
[&]() { mCameraMetadata->bufferSize(); },
[&]() { mCameraMetadata->sort(); },
[&]() {
uint8_t dataUint8 = mFDP->ConsumeIntegral<uint8_t>();
callCameraMetadataUpdate(dataCount, dataUint8);
},
[&]() {
int32_t dataInt32 = mFDP->ConsumeIntegral<int32_t>();
callCameraMetadataUpdate(dataCount, dataInt32);
},
[&]() {
int64_t dataInt64 = mFDP->ConsumeIntegral<int64_t>();
callCameraMetadataUpdate(dataCount, dataInt64);
},
[&]() {
float dataFloat = mFDP->ConsumeFloatingPoint<float>();
callCameraMetadataUpdate(dataCount, dataFloat);
},
[&]() {
double dataDouble = mFDP->ConsumeFloatingPoint<double>();
callCameraMetadataUpdate(dataCount, dataDouble);
},
[&]() {
camera_metadata_rational dataRational;
dataRational.numerator = mFDP->ConsumeIntegral<int32_t>();
dataRational.denominator = mFDP->ConsumeIntegral<int32_t>();
callCameraMetadataUpdate(dataCount, dataRational);
},
[&]() {
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
string dataStr = mFDP->ConsumeRandomLengthString(kMaxBytes);
String8 dataString(dataStr.c_str());
mCameraMetadata->update(tag, dataString);
},
[&]() {
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
uint32_t tagExists =
mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->exists(tagExists);
},
[&]() {
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
uint32_t tagFind =
mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->find(tagFind);
},
[&]() {
uint32_t tag = mFDP->ConsumeIntegral<uint32_t>();
uint32_t tagErase =
mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->erase(tagErase);
},
[&]() { mCameraMetadata->unlock(metadataBuffer); },
[&]() {
std::vector<int32_t> tagsRemoved;
uint64_t vendorId = mFDP->ConsumeIntegral<uint64_t>();
mCameraMetadata->removePermissionEntries(vendorId, &tagsRemoved);
},
[&]() {
string name = mFDP->ConsumeRandomLengthString(kMaxBytes);
VendorTagDescriptor vTags;
uint32_t tagName = mFDP->ConsumeIntegral<uint32_t>();
mCameraMetadata->getTagFromName(name.c_str(), &vTags, &tagName);
},
[&]() {
int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
int32_t verbosity = mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
int32_t indentation =
mFDP->ConsumeIntegralInRange<int32_t>(kRangeMin, kRangeMax);
mCameraMetadata->dump(fd, verbosity, indentation);
close(fd);
},
[&]() { CameraMetadata metadataCopy(mCameraMetadata->release()); },
[&]() {
if (mFDP->ConsumeBool()) {
CameraMetadata otherCameraMetadata;
mCameraMetadata->swap(otherCameraMetadata);
} else {
std::vector<int8_t> entryCapacityVector =
mFDP->ConsumeBytes<int8_t>(kMaxBytes);
/**
* Resizing vector to a size between 1 to 1000 so that vector is not empty.
*/
entryCapacityVector.resize(0, mFDP->ConsumeIntegralInRange<int32_t>(
kMinCapacity, kMaxCapacity));
CameraMetadata otherCameraMetadata(entryCapacityVector.size());
mCameraMetadata->swap(otherCameraMetadata);
}
},
[&]() {
if (!mMetadataLocked) {
camera_metadata* metaBuffer = allocate_camera_metadata(
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity,
kMaxMetadataCapacity) /* entry_capacity */,
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity,
kMaxMetadataCapacity) /* data_capacity */);
mCameraMetadata->acquire(metaBuffer);
}
},
[&]() {
if (!mMetadataLocked) {
camera_metadata* metaBuffer = allocate_camera_metadata(
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity,
kMaxMetadataCapacity) /* entry_capacity */,
mFDP->ConsumeIntegralInRange<size_t>(
kMinMetadataCapacity,
kMaxMetadataCapacity) /* data_capacity */);
mCameraMetadata->append(metaBuffer);
free_camera_metadata(metaBuffer);
}
},
});
callMetadataAPIs();
// Not keeping invokeReadWrite() APIs in while loop to avoid possible OOM.
invokeReadWriteNullParcel<CameraMetadata>(mCameraMetadata);
if (mFDP->ConsumeBool()) {
invokeReadWriteParcel<CameraMetadata>(mCameraMetadata);
} else {
invokeNewReadWriteParcel<CameraMetadata>(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;
}