Coverage Report

Created: 2025-11-09 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.77k
static uint32_t read_table_extents(const skcms_Curve* c) {
18
2.77k
    uint32_t x = 0;
19
2.77k
    if (c->table_entries) {
20
1.55k
        if (c->table_8) {
21
177
            x += c->table_8[0] + c->table_8[c->table_entries - 1];
22
177
        }
23
1.55k
        if (c->table_16) {
24
1.37k
            x += c->table_16[0] + c->table_16[2 * c->table_entries - 1];
25
1.37k
        }
26
1.55k
    }
27
2.77k
    return x;
28
2.77k
}
29
30
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
31
2.99k
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
32
2.99k
    skcms_ICCProfile p;
33
2.99k
    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
347
    if (p.tag_count > 0) {
41
347
        skcms_ICCTag tag;
42
347
        skcms_GetTagByIndex(&p,               0, &tag);
43
347
        skcms_GetTagByIndex(&p, p.tag_count - 1, &tag);
44
347
    }
45
46
    // For TRC tables, test that we can read the first and last entries of each table.
47
347
    if (p.has_trc) {
48
152
        for (int i = 0; i < 3; ++i) {
49
114
            g_FoolTheOptimizer += read_table_extents(&p.trc[i]);
50
114
        }
51
38
    }
52
53
    // For A2B data, test that we can read the first and last entries of each table.
54
347
    if (p.has_A2B) {
55
323
        uint32_t x = 0;
56
57
1.04k
        for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
58
720
            x += read_table_extents(&p.A2B.input_curves[i]);
59
720
        }
60
61
323
        if (p.A2B.input_channels) {
62
273
            uint64_t grid_size = p.A2B.output_channels;
63
993
            for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
64
720
                grid_size *= p.A2B.grid_points[i];
65
720
            }
66
67
273
            if (p.A2B.grid_8) {
68
153
                x += p.A2B.grid_8[0] + p.A2B.grid_8[grid_size - 1];
69
153
            }
70
71
273
            if (p.A2B.grid_16) {
72
120
                x += p.A2B.grid_16[0] + p.A2B.grid_16[2 * grid_size - 1];
73
120
            }
74
273
        }
75
76
1.29k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
77
969
            x += read_table_extents(&p.A2B.matrix_curves[i]);
78
969
        }
79
80
1.29k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
81
969
            x += read_table_extents(&p.A2B.output_curves[i]);
82
969
        }
83
84
323
        g_FoolTheOptimizer = x;
85
323
    }
86
87
347
    return 0;
88
2.99k
}