/* * 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. */ #ifndef CAMERA2COMMON_H #define CAMERA2COMMON_H #include #include #include #include #include #include #include #include #include using namespace android; const std::string kFetchCameraService = "media.camera"; constexpr int8_t kMinIterations = 0; constexpr int8_t kMaxIterations = 20; constexpr int8_t kMinExtraFDs = 0; constexpr int8_t kMinExtraBinder = 0; constexpr int32_t kMaxFDs = 1000; constexpr int32_t kMinBytes = 0; constexpr int32_t kMaxBytes = 20; constexpr int32_t kMinCapacity = 1; constexpr int32_t kMaxCapacity = 1000; const int32_t kValidFacing[] = {android::hardware::CameraSessionStats::CAMERA_FACING_BACK, android::hardware::CameraSessionStats::CAMERA_FACING_FRONT}; const int32_t kValidOrientation[] = {0, 90, 180, 270}; void randomizeParcel(Parcel* parcel, FuzzedDataProvider& provider) { sp sm = defaultServiceManager(); sp binder = sm->getService(String16(kFetchCameraService.c_str())); RandomParcelOptions options{ .extraBinders = {binder}, .extraFds = {}, }; auto retFds = parcel->debugReadAllFileDescriptors(); for (size_t i = 0; i < retFds.size(); ++i) { options.extraFds.push_back(base::unique_fd(dup(retFds[i]))); } int8_t iterations = provider.ConsumeIntegralInRange(kMinIterations, kMaxIterations); while (--iterations >= 0) { auto fillFunc = provider.PickValueInArray>({ // write data [&]() { size_t toWrite = provider.ConsumeIntegralInRange(kMinBytes, kMaxBytes); std::vector data = provider.ConsumeBytes(toWrite); CHECK(OK == parcel->write(data.data(), data.size())); }, // write FD [&]() { if (options.extraFds.size() > 0 && provider.ConsumeBool()) { const base::unique_fd& fd = options.extraFds.at(provider.ConsumeIntegralInRange( kMinExtraFDs, options.extraFds.size() - 1)); CHECK(OK == parcel->writeFileDescriptor(fd.get(), false /*takeOwnership*/)); } else { // b/260119717 - Adding more FDs can eventually lead to FD limit exhaustion if (options.extraFds.size() > kMaxFDs) { return; } std::vector fds = getRandomFds(&provider); CHECK(OK == parcel->writeFileDescriptor(fds.begin()->release(), true /*takeOwnership*/)); options.extraFds.insert(options.extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); } }, // write binder [&]() { sp binder; if (options.extraBinders.size() > 0 && provider.ConsumeBool()) { binder = options.extraBinders.at(provider.ConsumeIntegralInRange( kMinExtraBinder, options.extraBinders.size() - 1)); } else { binder = getRandomBinder(&provider); } CHECK(OK == parcel->writeStrongBinder(binder)); }, }); fillFunc(); } } template void invokeReadWriteNullParcel(type* obj) { Parcel* parcelNull = nullptr; obj->writeToParcel(parcelNull); obj->readFromParcel(parcelNull); } template void invokeReadWriteNullParcelsp(sp obj) { Parcel* parcelNull = nullptr; obj->writeToParcel(parcelNull); obj->readFromParcel(parcelNull); } template void invokeReadWriteParcel(type* obj) { Parcel* parcel = new Parcel(); obj->writeToParcel(parcel); parcel->setDataPosition(0); obj->readFromParcel(parcel); delete parcel; } template void invokeReadWriteParcelsp(sp obj) { Parcel* parcel = new Parcel(); obj->writeToParcel(parcel); parcel->setDataPosition(0); obj->readFromParcel(parcel); delete parcel; } template void invokeNewReadWriteParcel(type* obj, FuzzedDataProvider& provider) { Parcel* parcel = new Parcel(); obj->writeToParcel(parcel); randomizeParcel(parcel, provider); parcel->setDataPosition(0); obj->readFromParcel(parcel); delete parcel; } template void invokeNewReadWriteParcelsp(sp obj, FuzzedDataProvider& provider) { Parcel* parcel = new Parcel(); obj->writeToParcel(parcel); randomizeParcel(parcel, provider); parcel->setDataPosition(0); obj->readFromParcel(parcel); delete parcel; } #endif // CAMERA2COMMON_H