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

Commit 05ff67be authored by Dichen Zhang's avatar Dichen Zhang Committed by Android (Google) Code Review
Browse files

Merge "ultrahdr: Add fuzz application for decode api" into udc-dev

parents cd3f6373 d136b8a2
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -24,7 +24,17 @@ package {
cc_defaults {
    name: "ultrahdr_fuzzer_defaults",
    host_supported: true,
    static_libs: ["liblog"],
    shared_libs: [
        "libimage_io",
        "libjpeg",
    ],
    static_libs: [
        "libjpegdecoder",
        "libjpegencoder",
        "libultrahdr",
        "libutils",
        "liblog",
    ],
    target: {
        darwin: {
            enabled: false,
@@ -37,6 +47,8 @@ cc_defaults {
        description: "The fuzzers target the APIs of jpeg hdr",
        service_privilege: "constrained",
        users: "multi_user",
        fuzzed_code_usage: "future_version",
        vector: "local_no_privileges_required",
    },
}

@@ -46,20 +58,12 @@ cc_fuzz {
    srcs: [
        "ultrahdr_enc_fuzzer.cpp",
    ],
    shared_libs: [
        "libimage_io",
        "libjpeg",
        "liblog",
    ],
    static_libs: [
        "libjpegdecoder",
        "libjpegencoder",
        "libultrahdr",
        "libutils",
    ],
    fuzz_config: {
        fuzzed_code_usage: "future_version",
        vector: "local_no_privileges_required",
    },
}

cc_fuzz {
    name: "ultrahdr_dec_fuzzer",
    defaults: ["ultrahdr_fuzzer_defaults"],
    srcs: [
        "ultrahdr_dec_fuzzer.cpp",
    ],
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

// System include files
#include <fuzzer/FuzzedDataProvider.h>
#include <iostream>
#include <vector>

// User include files
#include "ultrahdr/jpegr.h"

using namespace android::ultrahdr;

// Transfer functions for image data, sync with ultrahdr.h
const int kOfMin = ULTRAHDR_OUTPUT_UNSPECIFIED + 1;
const int kOfMax = ULTRAHDR_OUTPUT_MAX;

class UltraHdrDecFuzzer {
public:
    UltraHdrDecFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
    void process();

private:
    FuzzedDataProvider mFdp;
};

void UltraHdrDecFuzzer::process() {
    // hdr_of
    auto of = static_cast<ultrahdr_output_format>(mFdp.ConsumeIntegralInRange<int>(kOfMin, kOfMax));
    auto buffer = mFdp.ConsumeRemainingBytes<uint8_t>();
    jpegr_compressed_struct jpegImgR{buffer.data(), (int)buffer.size(), (int)buffer.size(),
                                     ULTRAHDR_COLORGAMUT_UNSPECIFIED};

    std::vector<uint8_t> iccData(0);
    std::vector<uint8_t> exifData(0);
    jpegr_info_struct info{0, 0, &iccData, &exifData};
    JpegR jpegHdr;
    (void)jpegHdr.getJPEGRInfo(&jpegImgR, &info);
//#define DUMP_PARAM
#ifdef DUMP_PARAM
    std::cout << "input buffer size " << jpegImgR.length << std::endl;
    std::cout << "image dimensions " << info.width << " x " << info.width << std::endl;
#endif
    size_t outSize = info.width * info.height * ((of == ULTRAHDR_OUTPUT_SDR) ? 4 : 8);
    jpegr_uncompressed_struct decodedJpegR;
    auto decodedRaw = std::make_unique<uint8_t[]>(outSize);
    decodedJpegR.data = decodedRaw.get();
    ultrahdr_metadata_struct metadata;
    jpegr_uncompressed_struct decodedGainMap{};
    (void)jpegHdr.decodeJPEGR(&jpegImgR, &decodedJpegR,
                              mFdp.ConsumeFloatingPointInRange<float>(1.0, FLT_MAX), nullptr, of,
                              &decodedGainMap, &metadata);
    if (decodedGainMap.data) free(decodedGainMap.data);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    UltraHdrDecFuzzer fuzzHandle(data, size);
    fuzzHandle.process();
    return 0;
}
+10 −11
Original line number Diff line number Diff line
@@ -55,12 +55,9 @@ const int kOfMax = ULTRAHDR_OUTPUT_MAX;
const int kQfMin = 0;
const int kQfMax = 100;

// seed
const unsigned kSeed = 0x7ab7;

class JpegHDRFuzzer {
class UltraHdrEncFuzzer {
public:
    JpegHDRFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
    UltraHdrEncFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
    void process();
    void fillP010Buffer(uint16_t* data, int width, int height, int stride);
    void fill420Buffer(uint8_t* data, int size);
@@ -69,7 +66,7 @@ private:
    FuzzedDataProvider mFdp;
};

void JpegHDRFuzzer::fillP010Buffer(uint16_t* data, int width, int height, int stride) {
void UltraHdrEncFuzzer::fillP010Buffer(uint16_t* data, int width, int height, int stride) {
    uint16_t* tmp = data;
    std::vector<uint16_t> buffer(16);
    for (int i = 0; i < buffer.size(); i++) {
@@ -78,22 +75,24 @@ void JpegHDRFuzzer::fillP010Buffer(uint16_t* data, int width, int height, int st
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i += buffer.size()) {
            memcpy(data + i, buffer.data(), std::min((int)buffer.size(), (width - i)));
            std::shuffle(buffer.begin(), buffer.end(), std::default_random_engine(kSeed));
            std::shuffle(buffer.begin(), buffer.end(),
                         std::default_random_engine(std::random_device{}()));
        }
        tmp += stride;
    }
}

void JpegHDRFuzzer::fill420Buffer(uint8_t* data, int size) {
void UltraHdrEncFuzzer::fill420Buffer(uint8_t* data, int size) {
    std::vector<uint8_t> buffer(16);
    mFdp.ConsumeData(buffer.data(), buffer.size());
    for (int i = 0; i < size; i += buffer.size()) {
        memcpy(data + i, buffer.data(), std::min((int)buffer.size(), (size - i)));
        std::shuffle(buffer.begin(), buffer.end(), std::default_random_engine(kSeed));
        std::shuffle(buffer.begin(), buffer.end(),
                     std::default_random_engine(std::random_device{}()));
    }
}

void JpegHDRFuzzer::process() {
void UltraHdrEncFuzzer::process() {
    while (mFdp.remaining_bytes()) {
        struct jpegr_uncompressed_struct p010Img {};
        struct jpegr_uncompressed_struct yuv420Img {};
@@ -293,7 +292,7 @@ void JpegHDRFuzzer::process() {
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    JpegHDRFuzzer fuzzHandle(data, size);
    UltraHdrEncFuzzer fuzzHandle(data, size);
    fuzzHandle.process();
    return 0;
}
+4 −0
Original line number Diff line number Diff line
@@ -25,6 +25,10 @@ extern "C" {
}
#include <utils/Errors.h>
#include <vector>

static const int kMaxWidth = 8192;
static const int kMaxHeight = 8192;

namespace android::ultrahdr {
/*
 * Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format.
+6 −0
Original line number Diff line number Diff line
@@ -213,6 +213,12 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA)
        }
    }

    if (cinfo.image_width > kMaxWidth || cinfo.image_height > kMaxHeight) {
        // constraint on max width and max height is only due to alloc constraints
        // tune these values basing on the target device
        return false;
    }

    mWidth = cinfo.image_width;
    mHeight = cinfo.image_height;

Loading