/* * 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 "AutomotiveSvV1_0Fuzzer.h" #include #include #include namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer { using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hidl::allocator::V1_0::IAllocator; constexpr uint32_t kMinConfigDimension = 0; constexpr uint32_t kMaxConfigDimension = 4096; constexpr uint32_t kVertexByteSize = (3 * sizeof(float)) + 4; constexpr uint32_t kIdByteSize = 2; constexpr size_t kMaxCharacters = 30; constexpr size_t kMaxVertices = 10; constexpr size_t kMaxCameraPoints = 10; constexpr size_t kMaxViews = 10; constexpr size_t kMaxOverlays = 10; constexpr size_t kMinSvBuffers = 0; constexpr size_t kMaxSvBuffers = 10; void SurroundViewFuzzer::invoke2dSessionAPI() { sp surroundView2dSession; sp handler; mSurroundViewService->start2dSession( [&surroundView2dSession](const sp& session, SvResult result) { if (result == SvResult::OK) { surroundView2dSession = session; } }); if (surroundView2dSession && !mIs2dStreamStarted) { handler = sp::make(surroundView2dSession); if (surroundView2dSession->startStream(handler) == SvResult::OK) { mIs2dStreamStarted = true; } } while (mFuzzedDataProvider.remaining_bytes() > 0) { auto surroundView2dFunc = mFuzzedDataProvider.PickValueInArray< const std::function>({ [&]() { if (surroundView2dSession) { surroundView2dSession->get2dMappingInfo( []([[maybe_unused]] Sv2dMappingInfo info) {}); } }, [&]() { if (surroundView2dSession && mIs2dStreamStarted) { Sv2dConfig config; config.width = mFuzzedDataProvider.ConsumeIntegralInRange( kMinConfigDimension, kMaxConfigDimension); if (mFuzzedDataProvider.ConsumeBool()) { config.blending = static_cast( mFuzzedDataProvider.ConsumeIntegral()); } else { config.blending = mFuzzedDataProvider.ConsumeBool() ? (SvQuality::HIGH) : (SvQuality::LOW); } surroundView2dSession->set2dConfig(config); } }, [&]() { if (surroundView2dSession) { surroundView2dSession->get2dConfig([&](Sv2dConfig) {}); } }, [&]() { if (surroundView2dSession) { hidl_vec points2dCamera; const size_t camPoints = mFuzzedDataProvider.ConsumeIntegralInRange( 1, kMaxCameraPoints); points2dCamera.resize(camPoints); for (size_t i = 0; i < camPoints; ++i) { points2dCamera[i].x = mFuzzedDataProvider.ConsumeFloatingPoint(); points2dCamera[i].y = mFuzzedDataProvider.ConsumeFloatingPoint(); } hidl_vec cameraIds; mSurroundViewService->getCameraIds( [&cameraIds](const hidl_vec& camIds) { cameraIds = camIds; }); hidl_string cameraId; if (cameraIds.size() > 0 && mFuzzedDataProvider.ConsumeBool()) { const size_t cameraIndex = mFuzzedDataProvider.ConsumeIntegralInRange( 0, cameraIds.size() - 1); cameraId = cameraIds[cameraIndex]; } else { cameraId = mFuzzedDataProvider.ConsumeRandomLengthString(kMaxCharacters); } surroundView2dSession->projectCameraPoints( points2dCamera, cameraId, []([[maybe_unused]] const hidl_vec& outPoints) {}); } }, [&]() { if (surroundView2dSession) { SvFramesDesc frames; frames.timestampNs = mFuzzedDataProvider.ConsumeIntegral(); frames.sequenceId = mFuzzedDataProvider.ConsumeIntegral(); size_t numSvBuffers = mFuzzedDataProvider.ConsumeIntegralInRange( kMinSvBuffers, kMaxSvBuffers); frames.svBuffers.resize(numSvBuffers); for (int i = 0; i < numSvBuffers; ++i) { frames.svBuffers[i].viewId = mFuzzedDataProvider.ConsumeIntegral(); frames.svBuffers[i].hardwareBuffer.nativeHandle = new native_handle_t(); frames.svBuffers[i].hardwareBuffer.description[0] = mFuzzedDataProvider.ConsumeIntegral(); frames.svBuffers[i].hardwareBuffer.description[1] = mFuzzedDataProvider.ConsumeIntegral(); } surroundView2dSession->doneWithFrames(frames); for (int i = 0; i < numSvBuffers; ++i) { delete frames.svBuffers[i].hardwareBuffer.nativeHandle; } } }, [&]() { if (surroundView2dSession) { surroundView2dSession->stopStream(); mIs2dStreamStarted = false; } }, [&]() { SvResult result = mSurroundViewService->stop2dSession( mFuzzedDataProvider.ConsumeBool() ? surroundView2dSession : nullptr); if (result == SvResult::OK) { mIs2dStreamStarted = false; } }, }); surroundView2dFunc(); } if (surroundView2dSession && mIs2dStreamStarted) { surroundView2dSession->stopStream(); } if (surroundView2dSession) { mSurroundViewService->stop2dSession(surroundView2dSession); } } void SurroundViewFuzzer::invoke3dSessionAPI() { sp surroundView3dSession; sp handler; mSurroundViewService->start3dSession( [&surroundView3dSession](const sp& session, SvResult result) { if (result == SvResult::OK) { surroundView3dSession = session; } }); const size_t numViews = mFuzzedDataProvider.ConsumeIntegralInRange(1, kMaxViews); std::vector views(numViews); for (size_t i = 0; i < numViews; ++i) { views[i].viewId = mFuzzedDataProvider.ConsumeIntegral(); } surroundView3dSession->setViews(views); if (surroundView3dSession) { handler = sp::make(surroundView3dSession); if (surroundView3dSession->startStream(handler) == SvResult::OK) { mIs3dStreamStarted = true; } } while (mFuzzedDataProvider.remaining_bytes() > 0) { auto surroundView3dFunc = mFuzzedDataProvider.PickValueInArray< const std::function>({ [&]() { if (surroundView3dSession) { const size_t numViews = mFuzzedDataProvider.ConsumeIntegralInRange(1, kMaxViews); std::vector views(numViews); for (size_t i = 0; i < numViews; ++i) { views[i].viewId = mFuzzedDataProvider.ConsumeIntegral(); } surroundView3dSession->setViews(views); } }, [&]() { if (surroundView3dSession && mIs3dStreamStarted) { Sv3dConfig config; config.width = mFuzzedDataProvider.ConsumeIntegralInRange( kMinConfigDimension, kMaxConfigDimension); config.height = mFuzzedDataProvider.ConsumeIntegralInRange( kMinConfigDimension, kMaxConfigDimension); if (mFuzzedDataProvider.ConsumeBool()) { config.carDetails = static_cast( mFuzzedDataProvider.ConsumeIntegral()); } else { config.carDetails = mFuzzedDataProvider.ConsumeBool() ? (SvQuality::HIGH) : (SvQuality::LOW); } surroundView3dSession->set3dConfig(config); } }, [&]() { if (surroundView3dSession) { surroundView3dSession->get3dConfig([&](Sv3dConfig) {}); } }, [&]() { if (surroundView3dSession) { Point2dInt cameraPoint; cameraPoint.x = mFuzzedDataProvider.ConsumeFloatingPoint(); cameraPoint.y = mFuzzedDataProvider.ConsumeFloatingPoint(); std::vector cameraPoints = {cameraPoint}; hidl_vec cameraIds; mSurroundViewService->getCameraIds( [&cameraIds](const hidl_vec& camIds) { cameraIds = camIds; }); hidl_string cameraId; if (cameraIds.size() > 0 && mFuzzedDataProvider.ConsumeBool()) { const size_t cameraIndex = mFuzzedDataProvider.ConsumeIntegralInRange( 0, cameraIds.size() - 1); cameraId = cameraIds[cameraIndex]; } else { cameraId = mFuzzedDataProvider.ConsumeRandomLengthString(kMaxCharacters); } std::vector points3d; surroundView3dSession->projectCameraPointsTo3dSurface( cameraPoints, cameraId, [&points3d]([[maybe_unused]] const hidl_vec& points3dproj) { points3d = points3dproj; }); } }, [&]() { if (surroundView3dSession) { // success case surroundView3dSession->updateOverlays(mOverlaysdata); } }, [&]() { if (surroundView3dSession) { initSampleOverlaysData(); // Fail with ID mismatch // Set id of second overlay in shared memory to 2 (expected is 1). auto& overlaysDescVector = mOverlaysdata.overlaysMemoryDesc; auto& pIMemory = mMemory; int32_t indexPosition = mFuzzedDataProvider.ConsumeIntegralInRange( 0, mNumOverlays - 1); int32_t mismatchedValueIndex = mFuzzedDataProvider.ConsumeIntegralInRange( 0, mNumOverlays - 1); setIndexOfOverlaysMemory(overlaysDescVector, pIMemory, indexPosition, overlaysDescVector[mismatchedValueIndex].id); surroundView3dSession->updateOverlays(mOverlaysdata); } }, [&]() { if (surroundView3dSession) { // Fail with NULL memory // Set shared memory to null. mOverlaysdata.overlaysMemory = hidl_memory(); surroundView3dSession->updateOverlays(mOverlaysdata); } }, [&]() { if (surroundView3dSession) { SvFramesDesc frames; frames.timestampNs = mFuzzedDataProvider.ConsumeIntegral(); frames.sequenceId = mFuzzedDataProvider.ConsumeIntegral(); size_t numSvBuffers = mFuzzedDataProvider.ConsumeIntegralInRange( kMinSvBuffers, kMaxSvBuffers); frames.svBuffers.resize(numSvBuffers); for (int i = 0; i < numSvBuffers; ++i) { frames.svBuffers[i].viewId = mFuzzedDataProvider.ConsumeIntegral(); frames.svBuffers[i].hardwareBuffer.nativeHandle = new native_handle_t(); frames.svBuffers[i].hardwareBuffer.description[0] = mFuzzedDataProvider.ConsumeIntegral(); frames.svBuffers[i].hardwareBuffer.description[1] = mFuzzedDataProvider.ConsumeIntegral(); } surroundView3dSession->doneWithFrames(frames); for (int i = 0; i < numSvBuffers; ++i) { delete frames.svBuffers[i].hardwareBuffer.nativeHandle; } } }, [&]() { if (surroundView3dSession) { surroundView3dSession->stopStream(); mIs3dStreamStarted = false; } }, [&]() { SvResult result = mSurroundViewService->stop3dSession( mFuzzedDataProvider.ConsumeBool() ? surroundView3dSession : nullptr); if (result == SvResult::OK) { mIs3dStreamStarted = false; } }, }); surroundView3dFunc(); } if (surroundView3dSession && mIs3dStreamStarted) { surroundView3dSession->stopStream(); } if (surroundView3dSession) { mSurroundViewService->stop3dSession(surroundView3dSession); } } void SurroundViewFuzzer::process() { mFuzzedDataProvider.ConsumeBool() ? invoke2dSessionAPI() : invoke3dSessionAPI(); } std::pair> SurroundViewFuzzer::getMappedSharedMemory(int32_t bytesSize) { const auto nullResult = std::make_pair(hidl_memory(), nullptr); sp ashmemAllocator = IAllocator::getService("ashmem"); if (ashmemAllocator.get() == nullptr) { return nullResult; } // Allocate shared memory. hidl_memory hidlMemory; bool allocateSuccess = false; Return result = ashmemAllocator->allocate(bytesSize, [&](bool success, const hidl_memory& hidlMem) { if (!success) { return; } allocateSuccess = success; hidlMemory = hidlMem; }); // Check result of allocated memory. if (!result.isOk() || !allocateSuccess) { return nullResult; } // Map shared memory. sp pIMemory = mapMemory(hidlMemory); if (pIMemory.get() == nullptr) { return nullResult; } return std::make_pair(hidlMemory, pIMemory); } void SurroundViewFuzzer::setIndexOfOverlaysMemory( const std::vector& overlaysMemDesc, sp pIMemory, int32_t indexPosition, uint16_t indexValue) { // Count the number of vertices until the index. int32_t totalVerticesCount = 0; for (int32_t i = 0; i < indexPosition; ++i) { totalVerticesCount += overlaysMemDesc[i].verticesCount; } const int32_t indexBytePosition = (indexPosition * kIdByteSize) + (kVertexByteSize * totalVerticesCount); uint8_t* pSharedMemoryData = (uint8_t*)((void*)pIMemory->getPointer()); pSharedMemoryData += indexBytePosition; uint16_t* pIndex16bit = (uint16_t*)pSharedMemoryData; // Modify shared memory. pIMemory->update(); *pIndex16bit = indexValue; pIMemory->commit(); } void SurroundViewFuzzer::initSampleOverlaysData() { const size_t mNumOverlays = mFuzzedDataProvider.ConsumeIntegralInRange(kMinOverlays, kMaxOverlays); mOverlaysdata.overlaysMemoryDesc.resize(mNumOverlays); int32_t sharedMemBytesSize = 0; std::vector overlaysDescVector = {}; OverlayMemoryDesc overlayMemDesc[mNumOverlays]; for (size_t i = 0; i < mNumOverlays; ++i) { overlayMemDesc[i].id = i; overlayMemDesc[i].verticesCount = mFuzzedDataProvider.ConsumeIntegralInRange(1, kMaxVertices); overlayMemDesc[i].overlayPrimitive = mFuzzedDataProvider.ConsumeBool() ? (OverlayPrimitive::TRIANGLES) : (OverlayPrimitive::TRIANGLES_STRIP); mOverlaysdata.overlaysMemoryDesc[i] = overlayMemDesc[i]; sharedMemBytesSize += kIdByteSize + kVertexByteSize * overlayMemDesc[i].verticesCount; overlaysDescVector.push_back(overlayMemDesc[i]); } std::pair> sharedMem = getMappedSharedMemory(sharedMemBytesSize); sp pIMemory = std::get<1>(sharedMem); if (pIMemory.get() == nullptr) { mOverlaysdata = OverlaysData(); mMemory = nullptr; return; } // Get pointer to shared memory data and set all bytes to 0. uint8_t* pSharedMemoryData = (uint8_t*)((void*)pIMemory->getPointer()); pIMemory->update(); memset(pSharedMemoryData, 0, sharedMemBytesSize); pIMemory->commit(); // Set indexes in shared memory. for (size_t i = 0; i < mNumOverlays; ++i) { setIndexOfOverlaysMemory(overlaysDescVector, pIMemory, i, overlayMemDesc[i].id); } mOverlaysdata.overlaysMemoryDesc = overlaysDescVector; mOverlaysdata.overlaysMemory = std::get<0>(sharedMem); mMemory = pIMemory; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 1) { return 0; } SurroundViewFuzzer surroundViewFuzzer(data, size); surroundViewFuzzer.process(); return 0; } } // namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer