Commit bd3bfe83 for xz

commit bd3bfe834620b664d73b15952894864660a9bef1
Author: Lasse Collin <lasse.collin@tukaani.org>
Date:   Mon Jul 20 20:00:06 2026 +0300

    liblzma: Index decoder: Fix lzma_memusage()

    If lzma_stream was initialized using lzma_index_decoder() or
    lzma_file_info_decoder(), and lzma_memusage() was called after a few
    Records had already been decoded, the return value was too low because
    it was calculated based on the number of Records that haven't been
    decoded yet. So near the end of a big Index, the return value would be
    tiny compared to the actual memory usage.

    It worked correctly in the primary use case, that is, after
    LZMA_MEMLIMIT_ERROR. Thus, in practice this bug didn't matter much.

diff --git a/src/liblzma/common/index_decoder.c b/src/liblzma/common/index_decoder.c
index 5a867109..a279fd95 100644
--- a/src/liblzma/common/index_decoder.c
+++ b/src/liblzma/common/index_decoder.c
@@ -28,6 +28,10 @@ typedef struct {
 	/// Memory usage limit
 	uint64_t memlimit;

+	// Memory used for lzma_index once it has been allocated.
+	// Before that, this holds a tiny value.
+	uint64_t memused;
+
 	/// Target Index
 	lzma_index *index;

@@ -103,7 +107,13 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
 		FALLTHROUGH;

 	case SEQ_MEMUSAGE:
-		if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
+		coder->memused = lzma_index_memusage(1, coder->count);
+
+		// We sanity-checked coder->count in SEQ_COUNT, which
+		// guarantees that lzma_index_memusage() won't fail.
+		assert(coder->memused != UINT64_MAX);
+
+		if (coder->memused > coder->memlimit) {
 			ret = LZMA_MEMLIMIT_ERROR;
 			goto out;
 		}
@@ -237,7 +247,10 @@ index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
 {
 	lzma_index_coder *coder = coder_ptr;

-	*memusage = lzma_index_memusage(1, coder->count);
+	// Index decoder is special in sense that the returned memusage
+	// doesn't include the memory usage of the decoder itself; only
+	// the resulting lzma_index is counted.
+	*memusage = coder->memused;
 	*old_memlimit = coder->memlimit;

 	if (new_memlimit != 0) {
@@ -270,7 +283,7 @@ index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
 	// Initialize the rest.
 	coder->sequence = SEQ_INDICATOR;
 	coder->memlimit = my_max(1, memlimit);
-	coder->count = 0; // Needs to be initialized due to _memconfig().
+	coder->memused = 1; // If _memconfig() is called before SEQ_MEMUSAGE.
 	coder->pos = 0;
 	coder->crc32 = 0;

@@ -368,7 +381,7 @@ lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
 		} else if (ret == LZMA_MEMLIMIT_ERROR) {
 			// Tell the caller how much memory would have
 			// been needed.
-			*memlimit = lzma_index_memusage(1, coder.count);
+			*memlimit = coder.memused;
 		}
 	}