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