liblzma: Set all values in lzma_lz_encoder to NULL after allocation.

The first member of lzma_lz_encoder doesn't necessarily need to be set
to NULL since it will always be set before anything tries to use it.
However the function pointer members must be set to NULL since other
functions rely on this NULL value to determine if this behavior is
supported or not.

This fixes a somewhat serious bug, where the options_update() and
set_out_limit() function pointers are not set to NULL. This seems to
have been forgotten since these function pointers were added many years
after the original two (code() and end()).

The problem is that by not setting this to NULL we are relying on the
memory allocation to zero things out if lzma_filters_update() is called
on a LZMA1 encoder. The function pointer for set_out_limit() is less
serious because there is not an API function that could call this in an
incorrect way. set_out_limit() is only called by the MicroLZMA encoder,
which must use LZMA1 where set_out_limit() is always set. Its currently
not possible to call set_out_limit() on an LZMA2 encoder at this time.

So calling lzma_filters_update() on an LZMA1 encoder had undefined
behavior since its possible that memory could be manipulated so the
options_update member pointed to a different instruction sequence.

This is unlikely to be a bug in an existing application since it relies
on calling lzma_filters_update() on an LZMA1 encoder in the first place.
For instance, it does not affect xz because lzma_filters_update() can
only be used when encoding to the .xz format.
This commit is contained in:
Jia Tan 2023-12-16 20:51:38 +08:00
parent 0ba5dd7ba1
commit 8191720eac
1 changed files with 2 additions and 0 deletions

View File

@ -569,6 +569,8 @@ lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
coder->lz.coder = NULL; coder->lz.coder = NULL;
coder->lz.code = NULL; coder->lz.code = NULL;
coder->lz.end = NULL; coder->lz.end = NULL;
coder->lz.options_update = NULL;
coder->lz.set_out_limit = NULL;
// mf.size is initialized to silence Valgrind // mf.size is initialized to silence Valgrind
// when used on optimized binaries (GCC may reorder // when used on optimized binaries (GCC may reorder