Coverage Report

Created: 2026-01-17 06:54

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.68k
static uint32_t read_table_extents(const skcms_Curve* c) {
18
2.68k
    uint32_t x = 0;
19
2.68k
    if (c->table_entries) {
20
1.48k
        if (c->table_8) {
21
180
            x += c->table_8[0] + c->table_8[c->table_entries - 1];
22
180
        }
23
1.48k
        if (c->table_16) {
24
1.30k
            x += c->table_16[0] + c->table_16[2 * c->table_entries - 1];
25
1.30k
        }
26
1.48k
    }
27
2.68k
    return x;
28
2.68k
}
29
30
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
31
3.00k
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
32
3.00k
    skcms_ICCProfile p;
33
3.00k
    if (!skcms_Parse(data, size, &p)) {
34
2.67k
        return 0;
35
2.67k
    }
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
332
    if (p.tag_count > 0) {
41
332
        skcms_ICCTag tag;
42
332
        skcms_GetTagByIndex(&p,               0, &tag);
43
332
        skcms_GetTagByIndex(&p, p.tag_count - 1, &tag);
44
332
    }
45
46
    // For TRC tables, test that we can read the first and last entries of each table.
47
332
    if (p.has_trc) {
48
136
        for (int i = 0; i < 3; ++i) {
49
102
            g_FoolTheOptimizer += read_table_extents(&p.trc[i]);
50
102
        }
51
34
    }
52
53
    // For A2B data, test that we can read the first and last entries of each table.
54
332
    if (p.has_A2B) {
55
309
        uint32_t x = 0;
56
57
1.03k
        for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
58
728
            x += read_table_extents(&p.A2B.input_curves[i]);
59
728
        }
60
61
309
        if (p.A2B.input_channels) {
62
279
            uint64_t grid_size = p.A2B.output_channels;
63
1.00k
            for (uint32_t i = 0; i < p.A2B.input_channels; ++i) {
64
728
                grid_size *= p.A2B.grid_points[i];
65
728
            }
66
67
279
            if (p.A2B.grid_8) {
68
138
                x += p.A2B.grid_8[0] + p.A2B.grid_8[grid_size - 1];
69
138
            }
70
71
279
            if (p.A2B.grid_16) {
72
141
                x += p.A2B.grid_16[0] + p.A2B.grid_16[2 * grid_size - 1];
73
141
            }
74
279
        }
75
76
1.23k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
77
927
            x += read_table_extents(&p.A2B.matrix_curves[i]);
78
927
        }
79
80
1.23k
        for (uint32_t i = 0; i < p.A2B.output_channels; ++i) {
81
927
            x += read_table_extents(&p.A2B.output_curves[i]);
82
927
        }
83
84
309
        g_FoolTheOptimizer = x;
85
309
    }
86
87
332
    return 0;
88
3.00k
}