Commit d4217668 for xz

commit d4217668a79e6ca440e673115155559c81e89b84
Author: Lasse Collin <lasse.collin@tukaani.org>
Date:   Wed Sep 9 14:14:40 2026 +0300

    Tests: Reinitialize decoders twice in fuzzers

diff --git a/tests/ossfuzz/fuzz_decode_alone.c b/tests/ossfuzz/fuzz_decode_alone.c
index e11aa6be..79f3c64f 100644
--- a/tests/ossfuzz/fuzz_decode_alone.c
+++ b/tests/ossfuzz/fuzz_decode_alone.c
@@ -21,20 +21,25 @@ extern int
 LLVMFuzzerTestOneInput(const uint8_t *inbuf, size_t inbuf_size)
 {
 	lzma_stream strm = LZMA_STREAM_INIT;
+	strm.next_in = inbuf;
+	strm.avail_in = inbuf_size;

-	// Initialize a LZMA alone decoder using the memory usage limit
-	// defined in fuzz_common.h
-	lzma_ret ret = lzma_alone_decoder(&strm, MEM_LIMIT);
+	lzma_ret ret;

-	if (ret != LZMA_OK) {
-		// This should never happen unless the system has
-		// no free memory or address space to allow the small
-		// allocations that the initialization requires.
-		fprintf(stderr, "lzma_alone_decoder() failed (%d)\n", ret);
-		abort();
-	}
+	for (int i = 0; i < 3; ++i) {
+		ret = lzma_alone_decoder(&strm, MEM_LIMIT);
+
+		if (ret != LZMA_OK) {
+			// This should never happen unless the system has
+			// no free memory or address space to allow the small
+			// allocations that the initialization requires.
+			fprintf(stderr, "lzma_alone_decoder() failed (%d)\n",
+					ret);
+			abort();
+		}

-	fuzz_code(&strm, inbuf, inbuf_size);
+		fuzz_code(&strm, strm.next_in, strm.avail_in);
+	}

 	// Free the allocated memory.
 	lzma_end(&strm);
diff --git a/tests/ossfuzz/fuzz_decode_stream.c b/tests/ossfuzz/fuzz_decode_stream.c
index c5675056..550c4118 100644
--- a/tests/ossfuzz/fuzz_decode_stream.c
+++ b/tests/ossfuzz/fuzz_decode_stream.c
@@ -21,31 +21,43 @@ extern int
 LLVMFuzzerTestOneInput(const uint8_t *inbuf, size_t inbuf_size)
 {
 	lzma_stream strm = LZMA_STREAM_INIT;
+	strm.next_in = inbuf;
+	strm.avail_in = inbuf_size;

-	// Initialize a .xz decoder using the memory usage limit
-	// defined in fuzz_common.h
-	//
-	// Enable support for concatenated .xz files which is used when
-	// decompressing regular .xz files (instead of data embedded inside
-	// some other file format). Integrity checks on the uncompressed
-	// data are ignored to make fuzzing more effective (incorrect check
-	// values won't prevent the decoder from processing more input).
-	//
-	// The flag LZMA_IGNORE_CHECK doesn't disable verification of
-	// header CRC32 values. Those checks are disabled when liblzma is
-	// built with the #define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION.
-	lzma_ret ret = lzma_stream_decoder(&strm, MEM_LIMIT,
-			LZMA_CONCATENATED | LZMA_IGNORE_CHECK);
-
-	if (ret != LZMA_OK) {
-		// This should never happen unless the system has
-		// no free memory or address space to allow the small
-		// allocations that the initialization requires.
-		fprintf(stderr, "lzma_stream_decoder() failed (%d)\n", ret);
-		abort();
-	}
+	lzma_ret ret;
+
+	for (int i = 0; i < 3; ++i) {
+		// Initialize a .xz decoder using the memory usage limit
+		// defined in fuzz_common.h
+		//
+		// After the first two iterations, enable support for
+		// concatenated .xz files which is used when decompressing
+		// regular .xz files (instead of data embedded inside some
+		// other file format). This way the first iteration won't
+		// consume all the input until the input is invalid.
+		//
+		// Integrity checks on the uncompressed data are ignored to
+		// make fuzzing more effective (incorrect check values won't
+		// prevent the decoder from processing more input).
+		//
+		// The flag LZMA_IGNORE_CHECK doesn't disable verification
+		// of header CRC32 values. Those checks are disabled when
+		// liblzma is built with the
+		// #define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION.
+		ret = lzma_stream_decoder(&strm, MEM_LIMIT, LZMA_IGNORE_CHECK
+				| (i >= 2 ? LZMA_CONCATENATED : 0));

-	fuzz_code(&strm, inbuf, inbuf_size);
+		if (ret != LZMA_OK) {
+			// This should never happen unless the system has
+			// no free memory or address space to allow the small
+			// allocations that the initialization requires.
+			fprintf(stderr, "lzma_stream_decoder() failed (%d)\n",
+					ret);
+			abort();
+		}
+
+		fuzz_code(&strm, inbuf, inbuf_size);
+	}

 	// Free the allocated memory.
 	lzma_end(&strm);
diff --git a/tests/ossfuzz/fuzz_decode_stream_mt.c b/tests/ossfuzz/fuzz_decode_stream_mt.c
index 23ea9765..6beb68c5 100644
--- a/tests/ossfuzz/fuzz_decode_stream_mt.c
+++ b/tests/ossfuzz/fuzz_decode_stream_mt.c
@@ -20,26 +20,36 @@ extern int
 LLVMFuzzerTestOneInput(const uint8_t *inbuf, size_t inbuf_size)
 {
 	lzma_stream strm = LZMA_STREAM_INIT;
+	strm.next_in = inbuf;
+	strm.avail_in = inbuf_size;

 	lzma_mt mt = {
-		.flags = LZMA_CONCATENATED | LZMA_IGNORE_CHECK,
+		.flags = /*LZMA_CONCATENATED |*/ LZMA_IGNORE_CHECK,
 		.threads = 2,
 		.timeout = 0,
 		.memlimit_threading = MEM_LIMIT / 2,
 		.memlimit_stop = MEM_LIMIT,
 	};

-	lzma_ret ret = lzma_stream_decoder_mt(&strm, &mt);
+	lzma_ret ret;

-	if (ret != LZMA_OK) {
-		// This should never happen unless the system has
-		// no free memory or address space to allow the small
-		// allocations that the initialization requires.
-		fprintf(stderr, "lzma_stream_decoder_mt() failed (%d)\n", ret);
-		abort();
-	}
+	for (int i = 0; i < 3; ++i) {
+		if (i == 2)
+			mt.flags |= LZMA_CONCATENATED;
+
+		ret = lzma_stream_decoder_mt(&strm, &mt);

-	fuzz_code(&strm, inbuf, inbuf_size);
+		if (ret != LZMA_OK) {
+			// This should never happen unless the system has
+			// no free memory or address space to allow the small
+			// allocations that the initialization requires.
+			fprintf(stderr, "lzma_stream_decoder_mt() "
+					"failed (%d)\n", ret);
+			abort();
+		}
+
+		fuzz_code(&strm, strm.next_in, strm.avail_in);
+	}

 	lzma_end(&strm);