Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b238df4f authored by Kunal Rai's avatar Kunal Rai
Browse files

Added camera_metadata_fuzzer

exec/s: 3189
Test: ./camera_metadata_fuzzer
Bug: 309571245

Change-Id: I85da0a917cdb45d94ec32537e69f90b5ce0d6068
parent 1a285fc8
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -163,3 +163,13 @@ cc_fuzz {
        "camera_defaults",
    ],
}

cc_fuzz {
    name: "camera_metadata_fuzzer",
    srcs: [
        "camera_metadata_fuzzer.cpp",
    ],
    defaults: [
        "camera_defaults",
    ],
}
+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ Build the fuzzer
  $ mm -j$(nproc) camera_SessionStats_fuzzer
  $ mm -j$(nproc) camera_captureResult_fuzzer
  $ mm -j$(nproc) camera_utils_fuzzer
  $ mm -j$(nproc) camera_metadata_fuzzer
```
#### Steps to run
To run on device
@@ -69,6 +70,7 @@ To run on device
  $ adb shell /data/fuzz/${TARGET_ARCH}/camera_SessionStats_fuzzer/camera_SessionStats_fuzzer
  $ adb shell /data/fuzz/${TARGET_ARCH}/camera_captureResult_fuzzer/camera_captureResult_fuzzer
  $ adb shell /data/fuzz/${TARGET_ARCH}/camera_utils_fuzzer/camera_utils_fuzzer
  $ adb shell /data/fuzz/${TARGET_ARCH}/camera_metadata_fuzzer/camera_metadata_fuzzer
```

## References:
+223 −0
Original line number Diff line number Diff line
/*
 * 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;
}