/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 | } |