From 513cabcf7f5ce1c3ed0619e791393fc53d1dbbd0 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Thu, 3 Apr 2025 14:34:43 +0300 Subject: [PATCH] Tests: Call lzma_code() in smaller chunks in fuzz_common.h This makes it easy to crash fuzz_decode_stream_mt when tested against the code from 5.8.0. Obviously this might make it harder to reach some other code path now. The previous code has been in use since 2018 when fuzzing was added in 106d1a663d4b ("Tests: Add a fuzz test program and a config file for OSS-Fuzz."). --- tests/ossfuzz/fuzz_common.h | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tests/ossfuzz/fuzz_common.h b/tests/ossfuzz/fuzz_common.h index 4537f1bd..b47a3bdf 100644 --- a/tests/ossfuzz/fuzz_common.h +++ b/tests/ossfuzz/fuzz_common.h @@ -20,6 +20,9 @@ // prevent extreme allocations when fuzzing. #define MEM_LIMIT (300 << 20) // 300 MiB +// Amount of input to pass to lzma_code() per call at most. +#define IN_CHUNK_SIZE 2047 + static void fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { @@ -27,15 +30,29 @@ fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { // cares about the actual data written here. uint8_t outbuf[4096]; - // Give the whole input buffer at once to liblzma. - // Output buffer isn't initialized as liblzma only writes to it. + // Pass half of the input on the first call and then proceed in + // chunks. It's fine that this rounds to 0 when inbuf_size is 1. stream->next_in = inbuf; - stream->avail_in = inbuf_size; - stream->next_out = outbuf; - stream->avail_out = sizeof(outbuf); + stream->avail_in = inbuf_size / 2; + + lzma_action action = LZMA_RUN; lzma_ret ret; - while ((ret = lzma_code(stream, LZMA_FINISH)) == LZMA_OK) { + do { + if (stream->avail_in == 0 && inbuf_size > 0) { + const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE + ? inbuf_size : IN_CHUNK_SIZE; + + stream->next_in = inbuf; + stream->avail_in = chunk_size; + + inbuf += chunk_size; + inbuf_size -= chunk_size; + + if (inbuf_size == 0) + action = LZMA_FINISH; + } + if (stream->avail_out == 0) { // outbuf became full. We don't care about the // uncompressed data there, so we simply reuse @@ -43,7 +60,7 @@ fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { stream->next_out = outbuf; stream->avail_out = sizeof(outbuf); } - } + } while ((ret = lzma_code(stream, action)) == LZMA_OK); // LZMA_PROG_ERROR should never happen as long as the code calling // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign