Coverage Report

Created: 2024-11-21 06:35

/src/gfwx-fuzzers/encoder.cpp
Line
Count
Source (jump to first uncovered line)
1
/* By Guido Vranken <guidovranken@gmail.com> */
2
3
#include <cstdint>
4
#include <cstddef>
5
#include <cstring>
6
#include <cmath>
7
#include "gfwx.h"
8
#include "fuzzing/datasource/datasource.hpp"
9
10
class Image {
11
    public:
12
        const std::vector<uint8_t> data;
13
        const size_t width;
14
        const size_t height;
15
        const size_t numChannels;
16
        const size_t totalSize;
17
        Image(std::vector<uint8_t> data, size_t width, const size_t height, const size_t numChannels) :
18
3.09k
            data(data), width(width), height(height), numChannels(numChannels), totalSize(width * height * numChannels)
19
3.09k
        { }
20
};
21
22
3.25k
static std::optional<Image> getImage(fuzzing::datasource::Datasource& ds) {
23
3.25k
    const size_t numChannels = 3;
24
25
3.25k
    const auto image = ds.GetData(0);
26
3.25k
    if ( image.empty() ) {
27
23
        return std::nullopt;
28
23
    }
29
3.23k
    const auto totalBytesPerChannel = image.size() / numChannels;
30
3.23k
    if ( totalBytesPerChannel == 0 ) {
31
2
        return std::nullopt;
32
2
    }
33
3.23k
    const auto divisor = ds.Get<uint64_t>() % totalBytesPerChannel;
34
3.23k
    if ( divisor == 0 ) {
35
1
        return std::nullopt;
36
1
    }
37
3.23k
    const auto width = totalBytesPerChannel / divisor;
38
3.23k
    if ( width == 0 ) {
39
0
        return std::nullopt;
40
0
    }
41
3.23k
    const auto height = totalBytesPerChannel / width;
42
3.23k
    if ( height == 0 ) {
43
0
        return std::nullopt;
44
0
    }
45
46
3.23k
    const auto totalSize = width * height * numChannels;
47
48
3.23k
    std::vector<uint8_t> imageResized(totalSize);
49
3.23k
    memcpy(imageResized.data(), image.data(), totalSize);
50
51
3.23k
    return std::make_optional<Image>(imageResized, width, height, numChannels);
52
3.23k
}
53
54
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
55
3.25k
{
56
3.25k
    fuzzing::datasource::Datasource ds(data, size);
57
58
3.25k
    static std::vector<int> encoderChoices({GFWX::EncoderTurbo, GFWX::EncoderFast, GFWX::EncoderContextual});
59
3.25k
    static std::vector<int> intentChoices({ GFWX::IntentGeneric, GFWX::IntentMono, GFWX::IntentBayerRGGB, GFWX::IntentBayerBGGR,
60
3.25k
                                            GFWX::IntentBayerGRBG, GFWX::IntentBayerGBRG, GFWX::IntentBayerGeneric,
61
3.25k
                                            GFWX::IntentRGB, GFWX::IntentRGBA, GFWX::IntentRGBApremult, GFWX::IntentBGR,
62
3.25k
                                            GFWX::IntentBGRA, GFWX::IntentBGRApremult, GFWX::IntentCMYK});
63
3.25k
    static int transform_UYV[] = GFWX_TRANSFORM_UYV;
64
3.25k
    static int transform_A710_BGR[] = GFWX_TRANSFORM_A710_BGR;
65
3.25k
    static int transform_A710_RGB[] = GFWX_TRANSFORM_A710_RGB;
66
67
3.25k
    static std::vector<int*> transformChoices({transform_UYV, transform_A710_BGR, transform_A710_RGB});
68
69
3.25k
    static std::vector<int> filterChoices({GFWX::FilterLinear, GFWX::FilterCubic});
70
71
3.25k
    try {
72
3.25k
        const auto image = getImage(ds);
73
3.25k
        if ( image == std::nullopt ) {
74
26
            return 0;
75
26
        }
76
77
3.23k
        int layers = 1;
78
3.23k
        int channels = image->numChannels;
79
3.23k
        int bitDepth = GFWX::BitDepthAuto;            // BitDepthAuto selects 8 or 16 based on type
80
3.23k
        int quality = (ds.Get<uint16_t>() % 1024) + 1;
81
3.23k
        int chromaScale = (ds.Get<uint16_t>() % 1024) + 1;
82
3.23k
        int blockSize = ds.Get<uint8_t>() % (GFWX::BlockMax+1);
83
3.23k
        int filter = filterChoices[ ds.Get<uint8_t>() % filterChoices.size() ];
84
3.23k
        int quantization = GFWX::QuantizationScalar;
85
3.23k
        int encoder = encoderChoices[ ds.Get<uint8_t>() % encoderChoices.size() ];
86
3.23k
        int intent = intentChoices[ ds.Get<uint8_t>() % intentChoices.size() ];
87
88
3.23k
        const bool useTransform = ds.Get<bool>();
89
3.23k
        int* transform = nullptr; 
90
3.23k
        if ( useTransform ) {
91
808
            transform = transformChoices[ ds.Get<uint8_t>() % transformChoices.size() ];
92
808
        }
93
94
3.23k
        GFWX::Header header(image->width, image->height, layers, channels, bitDepth, quality,
95
3.23k
                chromaScale, blockSize, filter, quantization, encoder, intent);
96
97
3.23k
        const auto outSize = ds.Get<uint64_t>() % (image->totalSize * 2);
98
3.23k
        std::vector<uint8_t> out(outSize);
99
3.23k
        const ptrdiff_t size = GFWX::compress(image->data.data(), header, out.data(), out.size(), transform, 0, 0);
100
3.23k
        if ( size != GFWX::ErrorOverflow ) {
101
284
            fuzzing::memory::memory_test(out);
102
284
        }
103
3.23k
    } catch ( ... ) { }
104
3.23k
    return 0;
105
3.25k
}