Fix data corruption in LZMA2 decoder.
This commit is contained in:
parent
1ceebcf7e1
commit
ff7fb2c605
|
@ -58,6 +58,17 @@ struct lzma_coder_s {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lz_decoder_reset(lzma_coder *coder)
|
||||||
|
{
|
||||||
|
coder->dict.pos = 0;
|
||||||
|
coder->dict.full = 0;
|
||||||
|
coder->dict.buf[coder->dict.size - 1] = '\0';
|
||||||
|
coder->dict.need_reset = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static lzma_ret
|
static lzma_ret
|
||||||
decode_buffer(lzma_coder *coder,
|
decode_buffer(lzma_coder *coder,
|
||||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||||
|
@ -93,6 +104,10 @@ decode_buffer(lzma_coder *coder,
|
||||||
copy_size);
|
copy_size);
|
||||||
*out_pos += copy_size;
|
*out_pos += copy_size;
|
||||||
|
|
||||||
|
// Reset the dictionary if so requested by process().
|
||||||
|
if (coder->dict.need_reset)
|
||||||
|
lz_decoder_reset(coder);
|
||||||
|
|
||||||
// Return if everything got decoded or an error occurred, or
|
// Return if everything got decoded or an error occurred, or
|
||||||
// if there's no more data to decode.
|
// if there's no more data to decode.
|
||||||
if (ret != LZMA_OK || *out_pos == out_size
|
if (ret != LZMA_OK || *out_pos == out_size
|
||||||
|
@ -235,7 +250,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||||
next->coder->dict.size = dict_size;
|
next->coder->dict.size = dict_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
dict_reset(&next->coder->dict);
|
lz_decoder_reset(next->coder);
|
||||||
|
|
||||||
// Miscellaneous initializations
|
// Miscellaneous initializations
|
||||||
next->coder->next_finished = false;
|
next->coder->next_finished = false;
|
||||||
|
|
|
@ -45,6 +45,9 @@ typedef struct {
|
||||||
/// Size of the dictionary
|
/// Size of the dictionary
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
/// True when dictionary should be reset before decoding more data.
|
||||||
|
bool need_reset;
|
||||||
|
|
||||||
} lzma_dict;
|
} lzma_dict;
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,9 +227,8 @@ dict_write(lzma_dict *restrict dict, const uint8_t *restrict in,
|
||||||
static inline void
|
static inline void
|
||||||
dict_reset(lzma_dict *dict)
|
dict_reset(lzma_dict *dict)
|
||||||
{
|
{
|
||||||
dict->pos = 0;
|
dict->need_reset = true;
|
||||||
dict->full = 0;
|
return;
|
||||||
dict->buf[dict->size - 1] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -74,12 +74,11 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
|
||||||
const uint32_t control = in[*in_pos];
|
const uint32_t control = in[*in_pos];
|
||||||
++*in_pos;
|
++*in_pos;
|
||||||
|
|
||||||
// Dictionary reset implies that next LZMA chunk has to set
|
|
||||||
// new properties.
|
|
||||||
if (control >= 0xE0 || control == 1) {
|
if (control >= 0xE0 || control == 1) {
|
||||||
dict_reset(dict);
|
// Dictionary reset implies that next LZMA chunk has
|
||||||
coder->need_dictionary_reset = false;
|
// to set new properties.
|
||||||
coder->need_properties = true;
|
coder->need_properties = true;
|
||||||
|
coder->need_dictionary_reset = true;
|
||||||
} else if (coder->need_dictionary_reset) {
|
} else if (coder->need_dictionary_reset) {
|
||||||
return LZMA_DATA_ERROR;
|
return LZMA_DATA_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +124,14 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
|
||||||
coder->next_sequence = SEQ_COPY;
|
coder->next_sequence = SEQ_COPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coder->need_dictionary_reset) {
|
||||||
|
// Finish the dictionary reset and let the caller
|
||||||
|
// flush the dictionary to the actual output buffer.
|
||||||
|
coder->need_dictionary_reset = false;
|
||||||
|
dict_reset(dict);
|
||||||
|
return LZMA_OK;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue