1cc1dc7a3Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 2cc1dc7a3Sopenharmony_ci// ---------------------------------------------------------------------------- 3cc1dc7a3Sopenharmony_ci// Copyright 2020-2021 Arm Limited 4cc1dc7a3Sopenharmony_ci// 5cc1dc7a3Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); you may not 6cc1dc7a3Sopenharmony_ci// use this file except in compliance with the License. You may obtain a copy 7cc1dc7a3Sopenharmony_ci// of the License at: 8cc1dc7a3Sopenharmony_ci// 9cc1dc7a3Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 10cc1dc7a3Sopenharmony_ci// 11cc1dc7a3Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 12cc1dc7a3Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13cc1dc7a3Sopenharmony_ci// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14cc1dc7a3Sopenharmony_ci// License for the specific language governing permissions and limitations 15cc1dc7a3Sopenharmony_ci// under the License. 16cc1dc7a3Sopenharmony_ci// ---------------------------------------------------------------------------- 17cc1dc7a3Sopenharmony_ci 18cc1dc7a3Sopenharmony_ci/** 19cc1dc7a3Sopenharmony_ci * @brief Fuzz target for physical_to_symbolic(). 20cc1dc7a3Sopenharmony_ci * 21cc1dc7a3Sopenharmony_ci * This function is the first entrypoint for decompressing a 16 byte block of 22cc1dc7a3Sopenharmony_ci * input ASTC data from disk. The 16 bytes can contain arbitrary data; they 23cc1dc7a3Sopenharmony_ci * are read from an external source, but the block size used must be a valid 24cc1dc7a3Sopenharmony_ci * ASTC block footprint. 25cc1dc7a3Sopenharmony_ci */ 26cc1dc7a3Sopenharmony_ci 27cc1dc7a3Sopenharmony_ci 28cc1dc7a3Sopenharmony_ci#include "astcenc_internal.h" 29cc1dc7a3Sopenharmony_ci 30cc1dc7a3Sopenharmony_ci#include <fuzzer/FuzzedDataProvider.h> 31cc1dc7a3Sopenharmony_ci#include <array> 32cc1dc7a3Sopenharmony_ci#include <vector> 33cc1dc7a3Sopenharmony_ci 34cc1dc7a3Sopenharmony_cistruct BlockSizes 35cc1dc7a3Sopenharmony_ci{ 36cc1dc7a3Sopenharmony_ci int x; 37cc1dc7a3Sopenharmony_ci int y; 38cc1dc7a3Sopenharmony_ci int z; 39cc1dc7a3Sopenharmony_ci}; 40cc1dc7a3Sopenharmony_ci 41cc1dc7a3Sopenharmony_cistd::array<BlockSizes, 3> testSz {{ 42cc1dc7a3Sopenharmony_ci { 4, 4, 1}, // Highest bitrate 43cc1dc7a3Sopenharmony_ci {12, 12, 1}, // Largest 2D block 44cc1dc7a3Sopenharmony_ci {6, 6, 6} // Largest 3D block 45cc1dc7a3Sopenharmony_ci}}; 46cc1dc7a3Sopenharmony_ci 47cc1dc7a3Sopenharmony_cistd::array<block_size_descriptor, 3> testBSD; 48cc1dc7a3Sopenharmony_ci 49cc1dc7a3Sopenharmony_ci/** 50cc1dc7a3Sopenharmony_ci * @brief Utility function to create all of the block size descriptors needed. 51cc1dc7a3Sopenharmony_ci * 52cc1dc7a3Sopenharmony_ci * This is triggered once via a static initializer. 53cc1dc7a3Sopenharmony_ci * 54cc1dc7a3Sopenharmony_ci * Triggering once is important so that we only create a single BSD per block 55cc1dc7a3Sopenharmony_ci * size we need, rather than one per fuzzer iteration (it's expensive). This 56cc1dc7a3Sopenharmony_ci * improves fuzzer throughput by ~ 1000x! 57cc1dc7a3Sopenharmony_ci * 58cc1dc7a3Sopenharmony_ci * Triggering via a static initializer, rather than a lazy init in the fuzzer 59cc1dc7a3Sopenharmony_ci * function, is important because is means that the BSD is allocated before 60cc1dc7a3Sopenharmony_ci * fuzzing starts. This means that leaksanitizer will ignore the fact that we 61cc1dc7a3Sopenharmony_ci * "leak" the dynamic allocations inside the BSD (we never call term()). 62cc1dc7a3Sopenharmony_ci */ 63cc1dc7a3Sopenharmony_cibool bsd_initializer() 64cc1dc7a3Sopenharmony_ci{ 65cc1dc7a3Sopenharmony_ci for (int i = 0; i < testSz.size(); i++) 66cc1dc7a3Sopenharmony_ci { 67cc1dc7a3Sopenharmony_ci init_block_size_descriptor( 68cc1dc7a3Sopenharmony_ci testSz[i].x, 69cc1dc7a3Sopenharmony_ci testSz[i].y, 70cc1dc7a3Sopenharmony_ci testSz[i].z, 71cc1dc7a3Sopenharmony_ci false, 72cc1dc7a3Sopenharmony_ci 4, 73cc1dc7a3Sopenharmony_ci 1.0f, 74cc1dc7a3Sopenharmony_ci testBSD[i]); 75cc1dc7a3Sopenharmony_ci } 76cc1dc7a3Sopenharmony_ci 77cc1dc7a3Sopenharmony_ci return true; 78cc1dc7a3Sopenharmony_ci} 79cc1dc7a3Sopenharmony_ci 80cc1dc7a3Sopenharmony_ciextern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 81cc1dc7a3Sopenharmony_ci{ 82cc1dc7a3Sopenharmony_ci // Preinitialize the block size descriptors we need 83cc1dc7a3Sopenharmony_ci static bool init = bsd_initializer(); 84cc1dc7a3Sopenharmony_ci 85cc1dc7a3Sopenharmony_ci // Must have 4 (select block size) and 16 (payload) bytes 86cc1dc7a3Sopenharmony_ci if (size < 4 + 16) 87cc1dc7a3Sopenharmony_ci { 88cc1dc7a3Sopenharmony_ci return 0; 89cc1dc7a3Sopenharmony_ci } 90cc1dc7a3Sopenharmony_ci 91cc1dc7a3Sopenharmony_ci FuzzedDataProvider stream(data, size); 92cc1dc7a3Sopenharmony_ci 93cc1dc7a3Sopenharmony_ci // Select a block size to test 94cc1dc7a3Sopenharmony_ci int i = stream.ConsumeIntegralInRange<int>(0, testSz.size() - 1); 95cc1dc7a3Sopenharmony_ci 96cc1dc7a3Sopenharmony_ci // Populate the physical block 97cc1dc7a3Sopenharmony_ci uint8_t pcb[16]; 98cc1dc7a3Sopenharmony_ci std::vector<uint8_t> buffer = stream.ConsumeBytes<uint8_t>(16); 99cc1dc7a3Sopenharmony_ci std::memcpy(pcb, buffer.data(), 16); 100cc1dc7a3Sopenharmony_ci 101cc1dc7a3Sopenharmony_ci // Call the function under test 102cc1dc7a3Sopenharmony_ci symbolic_compressed_block scb; 103cc1dc7a3Sopenharmony_ci physical_to_symbolic(testBSD[i], pcb, scb); 104cc1dc7a3Sopenharmony_ci 105cc1dc7a3Sopenharmony_ci return 0; 106cc1dc7a3Sopenharmony_ci} 107