/* * Copyright (C) 2022 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 #include #include #include #include #include "camera2common.h" using namespace std; using namespace android; using namespace android::hardware::camera2::params; constexpr int8_t kMaxLoopIterations = 100; constexpr int32_t kSizeMin = 0; constexpr int32_t kSizeMax = 1000; class C2OutputConfigurationFuzzer { public: void process(const uint8_t* data, size_t size); private: void invokeC2OutputConfigFuzzer(); unique_ptr getC2OutputConfig(); sp createIGraphicBufferProducer(); FuzzedDataProvider* mFDP = nullptr; }; sp C2OutputConfigurationFuzzer::createIGraphicBufferProducer() { sp composerClient = new SurfaceComposerClient; sp surfaceControl = composerClient->createSurface( static_cast(mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()) /* name */, mFDP->ConsumeIntegral() /* width */, mFDP->ConsumeIntegral() /* height */, mFDP->ConsumeIntegral() /* format */, mFDP->ConsumeIntegral() /* flags */); if (surfaceControl) { sp surface = surfaceControl->getSurface(); return surface->getIGraphicBufferProducer(); } else { sp gbp; return gbp; } } unique_ptr C2OutputConfigurationFuzzer::getC2OutputConfig() { unique_ptr outputConfiguration = nullptr; auto selectOutputConfigurationConstructor = mFDP->PickValueInArray>({ [&]() { outputConfiguration = make_unique(); }, [&]() { int32_t rotation = mFDP->ConsumeIntegral(); string physicalCameraId = mFDP->ConsumeRandomLengthString(kMaxBytes); int32_t surfaceSetID = mFDP->ConsumeIntegral(); bool isShared = mFDP->ConsumeBool(); sp iGBP = createIGraphicBufferProducer(); outputConfiguration = make_unique( iGBP, rotation, physicalCameraId, surfaceSetID, isShared); }, [&]() { int32_t rotation = mFDP->ConsumeIntegral(); string physicalCameraId = mFDP->ConsumeRandomLengthString(kMaxBytes); int32_t surfaceSetID = mFDP->ConsumeIntegral(); bool isShared = mFDP->ConsumeBool(); size_t iGBPSize = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); vector> iGBPs; for (size_t idx = 0; idx < iGBPSize; ++idx) { sp iGBP = createIGraphicBufferProducer(); iGBPs.push_back(iGBP); } outputConfiguration = make_unique( iGBPs, rotation, physicalCameraId, surfaceSetID, isShared); }, }); selectOutputConfigurationConstructor(); return outputConfiguration; } void C2OutputConfigurationFuzzer::invokeC2OutputConfigFuzzer() { unique_ptr outputConfiguration = getC2OutputConfig(); int8_t count = kMaxLoopIterations; while (--count > 0) { unique_ptr outputConfiguration2 = getC2OutputConfig(); auto callC2OutputConfAPIs = mFDP->PickValueInArray>({ [&]() { outputConfiguration->getRotation(); }, [&]() { outputConfiguration->getSurfaceSetID(); }, [&]() { outputConfiguration->getSurfaceType(); }, [&]() { outputConfiguration->getWidth(); }, [&]() { outputConfiguration->getHeight(); }, [&]() { outputConfiguration->isDeferred(); }, [&]() { outputConfiguration->isShared(); }, [&]() { outputConfiguration->getPhysicalCameraId(); }, [&]() { outputConfiguration->gbpsEqual(*outputConfiguration2); }, [&]() { outputConfiguration->sensorPixelModesUsedEqual(*outputConfiguration2); }, [&]() { outputConfiguration->gbpsLessThan(*outputConfiguration2); }, [&]() { outputConfiguration->sensorPixelModesUsedLessThan(*outputConfiguration2); }, [&]() { outputConfiguration->getGraphicBufferProducers(); }, [&]() { sp gbp = createIGraphicBufferProducer(); outputConfiguration->addGraphicProducer(gbp); }, [&]() { outputConfiguration->isMultiResolution(); }, [&]() { outputConfiguration->getColorSpace(); }, [&]() { outputConfiguration->getStreamUseCase(); }, [&]() { outputConfiguration->getTimestampBase(); }, [&]() { outputConfiguration->getMirrorMode(); }, [&]() { outputConfiguration->useReadoutTimestamp(); }, }); callC2OutputConfAPIs(); } // Not keeping invokeReadWrite() APIs in while loop to avoid possible OOM. invokeReadWriteNullParcel(outputConfiguration.get()); if (mFDP->ConsumeBool()) { invokeReadWriteParcel(outputConfiguration.get()); } else { invokeNewReadWriteParcel(outputConfiguration.get(), *mFDP); } } void C2OutputConfigurationFuzzer::process(const uint8_t* data, size_t size) { mFDP = new FuzzedDataProvider(data, size); invokeC2OutputConfigFuzzer(); delete mFDP; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { C2OutputConfigurationFuzzer c2OutputConfigurationFuzzer; c2OutputConfigurationFuzzer.process(data, size); return 0; }