1 1.1 christos // SPDX-License-Identifier: 0BSD 2 1.1 christos 3 1.1 christos /////////////////////////////////////////////////////////////////////////////// 4 1.1 christos // 5 1.1 christos /// \file fuzz_common.h 6 1.1 christos /// \brief Common macros and functions needed by the fuzz targets 7 1.1 christos // 8 1.1 christos // Authors: Maksym Vatsyk 9 1.1 christos // Lasse Collin 10 1.1 christos // 11 1.1 christos /////////////////////////////////////////////////////////////////////////////// 12 1.1 christos 13 1.1 christos #include <inttypes.h> 14 1.1 christos #include <stdlib.h> 15 1.1 christos #include <stdio.h> 16 1.1 christos #include "lzma.h" 17 1.1 christos 18 1.1 christos // Some header values can make liblzma allocate a lot of RAM 19 1.1 christos // (up to about 4 GiB with liblzma 5.2.x). We set a limit here to 20 1.1 christos // prevent extreme allocations when fuzzing. 21 1.1 christos #define MEM_LIMIT (300 << 20) // 300 MiB 22 1.1 christos 23 1.1 christos // Amount of input to pass to lzma_code() per call at most. 24 1.1 christos #define IN_CHUNK_SIZE 2047 25 1.1 christos 26 1.1 christos 27 1.1 christos static void 28 1.1 christos fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { 29 1.1 christos // Output buffer for decompressed data. This is write only; nothing 30 1.1 christos // cares about the actual data written here. 31 1.1 christos uint8_t outbuf[4096]; 32 1.1 christos 33 1.1 christos // Pass half of the input on the first call and then proceed in 34 1.1 christos // chunks. It's fine that this rounds to 0 when inbuf_size is 1. 35 1.1 christos stream->next_in = inbuf; 36 1.1 christos stream->avail_in = inbuf_size / 2; 37 1.1 christos 38 1.1 christos lzma_action action = LZMA_RUN; 39 1.1 christos 40 1.1 christos lzma_ret ret; 41 1.1 christos do { 42 1.1 christos if (stream->avail_in == 0 && inbuf_size > 0) { 43 1.1 christos const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE 44 1.1 christos ? inbuf_size : IN_CHUNK_SIZE; 45 1.1 christos 46 1.1 christos stream->next_in = inbuf; 47 1.1 christos stream->avail_in = chunk_size; 48 1.1 christos 49 1.1 christos inbuf += chunk_size; 50 1.1 christos inbuf_size -= chunk_size; 51 1.1 christos 52 1.1 christos if (inbuf_size == 0) 53 1.1 christos action = LZMA_FINISH; 54 1.1 christos } 55 1.1 christos 56 1.1 christos if (stream->avail_out == 0) { 57 1.1 christos // outbuf became full. We don't care about the 58 1.1 christos // uncompressed data there, so we simply reuse 59 1.1 christos // the outbuf and overwrite the old data. 60 1.1 christos stream->next_out = outbuf; 61 1.1 christos stream->avail_out = sizeof(outbuf); 62 1.1 christos } 63 1.1 christos } while ((ret = lzma_code(stream, action)) == LZMA_OK); 64 1.1 christos 65 1.1 christos // LZMA_PROG_ERROR should never happen as long as the code calling 66 1.1 christos // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign 67 1.1 christos // of a bug in either this function or in liblzma. 68 1.1 christos if (ret == LZMA_PROG_ERROR) { 69 1.1 christos fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); 70 1.1 christos abort(); 71 1.1 christos } 72 1.1 christos } 73