| /* |
| * Copyright 2018 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| // This fuzz target parses an ICCProfile and then queries several pieces |
| // of info from it. |
| |
| #include "../skcms.h" |
| #include "../src/Macros.h" |
| |
| static volatile uint32_t g_FoolTheOptimizer = 0; |
| |
| // Read the first and last byte of any tables present in the curve |
| static uint32_t read_table_extents(const skcms_Curve* c) { |
| uint32_t x = 0; |
| if (c->table_entries) { |
| if (c->table_8) { |
| x += c->table_8[0] + c->table_8[c->table_entries - 1]; |
| } |
| if (c->table_16) { |
| x += c->table_16[0] + c->table_16[2 * c->table_entries - 1]; |
| } |
| } |
| return x; |
| } |
| |
| int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); |
| int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| skcms_ICCProfile p; |
| if (!skcms_Parse(data, size, &p)) { |
| return 0; |
| } |
| |
| // Instead of testing all tags, just test that we can read the first and last. |
| // This does _not_ imply all the middle will work fine, but these calls should |
| // be enough for the fuzzer to find a way to break us. |
| if (p.tag_count > 0) { |
| skcms_ICCTag tag; |
| skcms_GetTagByIndex(&p, 0, &tag); |
| skcms_GetTagByIndex(&p, p.tag_count - 1, &tag); |
| } |
| |
| // For TRC tables, test that we can read the first and last entries of each table. |
| if (p.has_trc) { |
| for (int i = 0; i < ARRAY_COUNT(p.trc); ++i) { |
| g_FoolTheOptimizer += read_table_extents(&p.trc[i]); |
| } |
| } |
| |
| // For A2B data, test that we can read the first and last entries of each table. |
| if (p.has_A2B) { |
| uint32_t x = 0; |
| |
| for (uint32_t i = 0; i < p.A2B.input_channels; ++i) { |
| x += read_table_extents(&p.A2B.input_curves[i]); |
| } |
| |
| if (p.A2B.input_channels) { |
| uint64_t grid_size = p.A2B.output_channels; |
| for (uint32_t i = 0; i < p.A2B.input_channels; ++i) { |
| grid_size *= p.A2B.grid_points[i]; |
| } |
| |
| if (p.A2B.grid_8) { |
| x += p.A2B.grid_8[0] + p.A2B.grid_8[grid_size - 1]; |
| } |
| |
| if (p.A2B.grid_16) { |
| x += p.A2B.grid_16[0] + p.A2B.grid_16[2 * grid_size - 1]; |
| } |
| } |
| |
| for (uint32_t i = 0; i < p.A2B.output_channels; ++i) { |
| x += read_table_extents(&p.A2B.matrix_curves[i]); |
| } |
| |
| for (uint32_t i = 0; i < p.A2B.output_channels; ++i) { |
| x += read_table_extents(&p.A2B.output_curves[i]); |
| } |
| |
| g_FoolTheOptimizer = x; |
| } |
| |
| return 0; |
| } |