Commit e5e63d50 for xz

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

    liblzma: Clean up after a filter chain initialization error

    Filter coders are initialized using lzma_next_filter_init(). If filter
    chain initialization fails, the entire filter chain should be cleaned up
    with lzma_next_end(). lzma_raw_encoder_init() and lzma_raw_decoder_init()
    have always done this via lzma_raw_coder_init() in filter_common.c.
    (Separate cleanup is weird, but it must have made sense to the young me.)

    The following decoders initialize LZMA1 filter directly without using the
    raw filter chain API. This avoids needlessly pulling in all other filters
    when a program is linked against static liblzma. These functions didn't
    call lzma_next_end() after an initialization error, which left the state
    available for later reinitialization.

      - lzma_alone_decoder()
      - lzma_lzip_decoder()
      - lzma_auto_decoder() [*]
      - lzma_microlzma_decoder()

    [*] lzma_auto_decoder() is only indirectly affected due to the first two
        functions. lzma_auto_decoder() itself doesn't need a fix.

    There are also encoder functions that initialize the LZMA1 encoder
    directly. They don't have this issue because the whole lzma_stream
    is cleaned up when encoder initialization fails.

    Reported-by: GitHub user christos-cantina-security (christos-spearbit)

diff --git a/src/liblzma/common/alone_decoder.c b/src/liblzma/common/alone_decoder.c
index 8ebbbe8a..174b3b1d 100644
--- a/src/liblzma/common/alone_decoder.c
+++ b/src/liblzma/common/alone_decoder.c
@@ -152,8 +152,12 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
 			}
 		};

-		return_if_error(lzma_next_filter_init(&coder->next,
-				allocator, filters));
+		const lzma_ret ret = lzma_next_filter_init(&coder->next,
+				allocator, filters);
+		if (ret != LZMA_OK) {
+			lzma_next_end(&coder->next, allocator);
+			return ret;
+		}

 		coder->sequence = SEQ_CODE;
 		break;
diff --git a/src/liblzma/common/lzip_decoder.c b/src/liblzma/common/lzip_decoder.c
index 5630039f..d6f929d2 100644
--- a/src/liblzma/common/lzip_decoder.c
+++ b/src/liblzma/common/lzip_decoder.c
@@ -237,8 +237,12 @@ lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
 			}
 		};

-		return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
-				allocator, filters));
+		const lzma_ret ret = lzma_next_filter_init(
+				&coder->lzma_decoder, allocator, filters);
+		if (ret != LZMA_OK) {
+			lzma_next_end(&coder->lzma_decoder, allocator);
+			return ret;
+		}

 		coder->crc32 = 0;
 		coder->sequence = SEQ_LZMA_STREAM;
diff --git a/src/liblzma/common/microlzma_decoder.c b/src/liblzma/common/microlzma_decoder.c
index 882cb2c8..a7720cc2 100644
--- a/src/liblzma/common/microlzma_decoder.c
+++ b/src/liblzma/common/microlzma_decoder.c
@@ -108,8 +108,12 @@ microlzma_decode(void *coder_ptr, const lzma_allocator *allocator,
 			}
 		};

-		return_if_error(lzma_next_filter_init(&coder->lzma,
-				allocator, filters));
+		const lzma_ret ret = lzma_next_filter_init(&coder->lzma,
+				allocator, filters);
+		if (ret != LZMA_OK) {
+			lzma_next_end(&coder->lzma, allocator);
+			return ret;
+		}

 		// Pass one dummy 0x00 byte to the LZMA decoder since that
 		// is what it expects the first byte to be.