1
0
mirror of https://git.tukaani.org/xz.git synced 2026-10-31 03:14:56 +00:00

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.
This commit is contained in:
Lasse Collin 2026-07-20 20:00:06 +03:00
parent 2187b27c64
commit bd3bfe8346
No known key found for this signature in database
GPG Key ID: 38EE757D69184620

View File

@ -28,6 +28,10 @@ typedef struct {
/// Memory usage limit /// Memory usage limit
uint64_t memlimit; 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 /// Target Index
lzma_index *index; lzma_index *index;
@ -103,7 +107,13 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
FALLTHROUGH; FALLTHROUGH;
case SEQ_MEMUSAGE: 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; ret = LZMA_MEMLIMIT_ERROR;
goto out; goto out;
} }
@ -237,7 +247,10 @@ index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
{ {
lzma_index_coder *coder = coder_ptr; 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; *old_memlimit = coder->memlimit;
if (new_memlimit != 0) { if (new_memlimit != 0) {
@ -270,7 +283,7 @@ index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
// Initialize the rest. // Initialize the rest.
coder->sequence = SEQ_INDICATOR; coder->sequence = SEQ_INDICATOR;
coder->memlimit = my_max(1, memlimit); 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->pos = 0;
coder->crc32 = 0; coder->crc32 = 0;
@ -368,7 +381,7 @@ lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
} else if (ret == LZMA_MEMLIMIT_ERROR) { } else if (ret == LZMA_MEMLIMIT_ERROR) {
// Tell the caller how much memory would have // Tell the caller how much memory would have
// been needed. // been needed.
*memlimit = lzma_index_memusage(1, coder.count); *memlimit = coder.memused;
} }
} }