| // SPDX-License-Identifier: Apache-2.0 |
| // ---------------------------------------------------------------------------- |
| // Copyright 2020-2021 Arm Limited |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy |
| // of the License at: |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations |
| // under the License. |
| // ---------------------------------------------------------------------------- |
| |
| /** |
| * @brief Fuzz target for physical_to_symbolic(). |
| * |
| * This function is the first entrypoint for decompressing a 16 byte block of |
| * input ASTC data from disk. The 16 bytes can contain arbitrary data; they |
| * are read from an external source, but the block size used must be a valid |
| * ASTC block footprint. |
| */ |
| |
| |
| #include "astcenc_internal.h" |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| #include <array> |
| #include <vector> |
| |
| struct BlockSizes |
| { |
| int x; |
| int y; |
| int z; |
| }; |
| |
| std::array<BlockSizes, 3> testSz {{ |
| { 4, 4, 1}, // Highest bitrate |
| {12, 12, 1}, // Largest 2D block |
| {6, 6, 6} // Largest 3D block |
| }}; |
| |
| std::array<block_size_descriptor, 3> testBSD; |
| |
| /** |
| * @brief Utility function to create all of the block size descriptors needed. |
| * |
| * This is triggered once via a static initializer. |
| * |
| * Triggering once is important so that we only create a single BSD per block |
| * size we need, rather than one per fuzzer iteration (it's expensive). This |
| * improves fuzzer throughput by ~ 1000x! |
| * |
| * Triggering via a static initializer, rather than a lazy init in the fuzzer |
| * function, is important because is means that the BSD is allocated before |
| * fuzzing starts. This means that leaksanitizer will ignore the fact that we |
| * "leak" the dynamic allocations inside the BSD (we never call term()). |
| */ |
| bool bsd_initializer() |
| { |
| for (int i = 0; i < testSz.size(); i++) |
| { |
| init_block_size_descriptor( |
| testSz[i].x, |
| testSz[i].y, |
| testSz[i].z, |
| false, |
| 4, |
| 1.0f, |
| testBSD[i]); |
| } |
| |
| return true; |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
| { |
| // Preinitialize the block size descriptors we need |
| static bool init = bsd_initializer(); |
| |
| // Must have 4 (select block size) and 16 (payload) bytes |
| if (size < 4 + 16) |
| { |
| return 0; |
| } |
| |
| FuzzedDataProvider stream(data, size); |
| |
| // Select a block size to test |
| int i = stream.ConsumeIntegralInRange<int>(0, testSz.size() - 1); |
| |
| // Populate the physical block |
| physical_compressed_block pcb; |
| std::vector<uint8_t> buffer = stream.ConsumeBytes<uint8_t>(16); |
| std::memcpy(&pcb, buffer.data(), 16); |
| |
| // Call the function under test |
| symbolic_compressed_block scb; |
| physical_to_symbolic(testBSD[i], pcb, scb); |
| |
| return 0; |
| } |