Coverage Report

Created: 2025-08-03 06:33

/src/skcms/fuzz/fuzz_iccprofile_info.c
Line
Count
Source
1
/*
2
 * Copyright 2018 Google Inc.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
// This fuzz target parses an ICCProfile and then queries several pieces
9
// of info from it.
10
11
#include "../src/skcms_public.h"
12
#include "../src/skcms_internals.h"
13
14
static volatile uint32_t g_FoolTheOptimizer = 0;
15
16
// Read the first and last byte of any tables present in the curve
17
2.23k
static uint32_t read_table_extents(const skcms_Curve* c) {
18
2.23k
    uint32_t x = 0;
19
2.23k
    if (c->table_entries) {
20
1.25k
        if (c->table_8) {
21
115
            x += c->table_8[0] + c->table_8[c->table_entries - 1];
22
115
        }
23
1.25k
        if (c->table_16) {
24
1.14k
            x += c->table_16[0] + c->table_16[2 * c->table_entries - 1];
25
1.14k
        }
26
1.25k
    }
27
2.23k
    return x;
28
2.23k
}
29
30
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
31
2.94k
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
32
2.94k
    skcms_ICCProfile p;
33
2.94k
    if (!skcms_Parse(data, size, &p)) {
34
2.65k
        return 0;
35
2.65k
    }
36
37
    // Instead of testing all tags, just test that we can read the first and last.
38
    // This does _not_ imply all the middle will work fine, but these calls should
39
    // be enough for the fuzzer to find a way to break us.
40
292
    if (p.tag_count > 0) {
41
292
        skcms_ICCTag tag;
42
292
        skcms_GetTagByIndex(&p,               0, &tag);
43
292
        skcms_GetTagByIndex(&p, p.tag_count - 1, &tag);
44
292
    }
45
46
    // For TRC tables, test that we can read the first and last entries of each table.
47
292
    if (p.has_trc) {
48
184
        for (int i = 0; i < 3; ++i) {
49
138
            g_FoolTheOptimizer += read_table_extents(&p.trc[i]);
50
138
        }
51
46
    }
52
53
    // For A2B data, test that we can read the first and last entries of each table.
54
292
    if (p.has_A2B) {
55
259
        uint32_t x = 0;
56
57
803
        for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
58
544
            x += read_table_extents(&p.A2B.input_curves[i]);
59
544
        }
60
61
259
        if (p.A2B.input_channels) {
62
204
            uint64_t grid_size = p.A2B.output_channels;
63
748
            for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
64
544
                grid_size *= p.A2B.grid_points[i];
65
544
            }
66
67
204
            if (p.A2B.grid_8) {
68
115
                x += p.A2B.grid_8[0] + p.A2B.grid_8[grid_size - 1];
69
115
            }
70
71
204
            if (p.A2B.grid_16) {
72
89
                x += p.A2B.grid_16[0] + p.A2B.grid_16[2 * grid_size - 1];
73
89
            }
74
204
        }
75
76
1.03k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
77
777
            x += read_table_extents(&p.A2B.matrix_curves[i]);
78
777
        }
79
80
1.03k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
81
777
            x += read_table_extents(&p.A2B.output_curves[i]);
82
777
        }
83
84
259
        g_FoolTheOptimizer = x;
85
259
    }
86
87
292
    return 0;
88
2.94k
}