1
0
Fork 0
mirror of https://git.tukaani.org/xz.git synced 2024-04-04 12:36:23 +02:00

Fix data corruption in LZMA2 decoder.

This commit is contained in:
Lasse Collin 2008-12-15 10:01:59 +02:00
parent 1ceebcf7e1
commit ff7fb2c605
3 changed files with 32 additions and 8 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;
} }