Index decoder fixes.

The Index decoder code didn't perfectly match the API docs,
which said that *i will be set to point to the decoded Index
only after decoding has succeeded. The docs were a bit unclear
too.

Now the decoder will initially set *i to NULL. *i will be set
to point to the decoded Index once decoding has succeeded.
This simplifies applications too, since it avoids dangling
pointers.
This commit is contained in:
Lasse Collin 2009-11-25 12:52:56 +02:00
parent 465d1b0d65
commit 1f19690914
2 changed files with 32 additions and 17 deletions

View File

@ -317,12 +317,13 @@ extern LZMA_API(lzma_ret) lzma_index_encoder(lzma_stream *strm, lzma_index *i)
* \brief Initialize .xz Index decoder * \brief Initialize .xz Index decoder
* *
* \param strm Pointer to properly prepared lzma_stream * \param strm Pointer to properly prepared lzma_stream
* \param i Pointer to a pointer that will be made to point * \param i The decoded Index will be made available via
* to the final decoded Index once lzma_code() has * this pointer. Initially this function will
* returned LZMA_STREAM_END. That is, * set *i to NULL (the old value is ignored). If
* lzma_index_decoder() always takes care of * decoding succeeds (lzma_code() returns
* allocating a new lzma_index structure, and *i * LZMA_STREAM_END), *i will be set to point
* doesn't need to be initialized by the caller. * to the decoded Index, which the application
* has to later free with lzma_index_end().
* \param memlimit How much memory the resulting Index is allowed * \param memlimit How much memory the resulting Index is allowed
* to require. * to require.
* *
@ -373,11 +374,11 @@ extern LZMA_API(lzma_ret) lzma_index_buffer_encode(lzma_index *i,
/** /**
* \brief Single-call .xz Index decoder * \brief Single-call .xz Index decoder
* *
* \param i Pointer to a pointer that will be made to point * \param i If decoding succeeds, *i will point to the
* to the final decoded Index if decoding is * decoded Index, which the application has to
* successful. That is, lzma_index_buffer_decode() * later free with lzma_index_end(). If an error
* always takes care of allocating a new * occurs, *i will be NULL. The old value of *i
* lzma_index structure, and *i doesn't need to be * is always ignored and thus doesn't need to be
* initialized by the caller. * initialized by the caller.
* \param memlimit Pointer to how much memory the resulting Index * \param memlimit Pointer to how much memory the resulting Index
* is allowed to require. The value pointed by * is allowed to require. The value pointed by

View File

@ -32,6 +32,10 @@ struct lzma_coder_s {
/// Target Index /// Target Index
lzma_index *index; lzma_index *index;
/// Pointer give by the application, which is set after
/// successful decoding.
lzma_index **index_ptr;
/// Number of Records left to decode. /// Number of Records left to decode.
lzma_vli count; lzma_vli count;
@ -174,6 +178,10 @@ index_decode(lzma_coder *coder, lzma_allocator *allocator,
} while (++coder->pos < 4); } while (++coder->pos < 4);
// Decoding was successful, now we can let the application
// see the decoded Index.
*coder->index_ptr = coder->index;
// Make index NULL so we don't free it unintentionally. // Make index NULL so we don't free it unintentionally.
coder->index = NULL; coder->index = NULL;
@ -222,15 +230,21 @@ static lzma_ret
index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator, index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
lzma_index **i, uint64_t memlimit) lzma_index **i, uint64_t memlimit)
{ {
// Remember the pointer given by the application. We will set it
// to point to the decoded Index only if decoding is successful.
// Before that, keep it NULL so that applications can always safely
// pass it to lzma_index_end() no matter did decoding succeed or not.
coder->index_ptr = i;
*i = NULL;
// We always allocate a new lzma_index. // We always allocate a new lzma_index.
*i = lzma_index_init(NULL, allocator); coder->index = lzma_index_init(NULL, allocator);
if (*i == NULL) if (coder->index == NULL)
return LZMA_MEM_ERROR; return LZMA_MEM_ERROR;
// Initialize the rest. // Initialize the rest.
coder->sequence = SEQ_INDICATOR; coder->sequence = SEQ_INDICATOR;
coder->memlimit = memlimit; coder->memlimit = memlimit;
coder->index = *i;
coder->count = 0; // Needs to be initialized due to _memconfig(). coder->count = 0; // Needs to be initialized due to _memconfig().
coder->pos = 0; coder->pos = 0;
coder->crc32 = 0; coder->crc32 = 0;
@ -282,7 +296,8 @@ lzma_index_buffer_decode(
const uint8_t *in, size_t *in_pos, size_t in_size) const uint8_t *in, size_t *in_pos, size_t in_size)
{ {
// Sanity checks // Sanity checks
if (i == NULL || in == NULL || in_pos == NULL || *in_pos > in_size) if (i == NULL || memlimit == NULL
|| in == NULL || in_pos == NULL || *in_pos > in_size)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
// Initialize the decoder. // Initialize the decoder.
@ -302,8 +317,7 @@ lzma_index_buffer_decode(
} else { } else {
// Something went wrong, free the Index structure and restore // Something went wrong, free the Index structure and restore
// the input position. // the input position.
lzma_index_end(*i, allocator); lzma_index_end(coder.index, allocator);
*i = NULL;
*in_pos = in_start; *in_pos = in_start;
if (ret == LZMA_OK) { if (ret == LZMA_OK) {