diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2008-12-01 22:50:28 +0200 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2008-12-01 22:50:28 +0200 |
commit | cd708015202dbf7585b84a8781462a20c42a324b (patch) | |
tree | 11cb0ffd1684562722384c7466c3166fbce28a95 /src/liblzma/lzma/lzma2_decoder.c | |
parent | Added lzma_delta_coder_memusage() which also validates (diff) | |
download | xz-cd708015202dbf7585b84a8781462a20c42a324b.tar.xz |
LZMA2 decoder cleanups. Make it require new LZMA properties
also in the first LZMA chunk after a dictionary reset in
uncompressed chunk.
Diffstat (limited to '')
-rw-r--r-- | src/liblzma/lzma/lzma2_decoder.c | 95 |
1 files changed, 41 insertions, 54 deletions
diff --git a/src/liblzma/lzma/lzma2_decoder.c b/src/liblzma/lzma/lzma2_decoder.c index af1da746..7f1f45f4 100644 --- a/src/liblzma/lzma/lzma2_decoder.c +++ b/src/liblzma/lzma/lzma2_decoder.c @@ -70,76 +70,63 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict, // at least one byte of input. while (*in_pos < in_size || coder->sequence == SEQ_LZMA) switch (coder->sequence) { - case SEQ_CONTROL: - if (in[*in_pos] & 0x80) { - // Get the highest five bits of uncompressed size. - coder->uncompressed_size - = (uint32_t)(in[*in_pos] & 0x1F) << 16; - coder->sequence = SEQ_UNCOMPRESSED_1; - - // See if we need to reset dictionary or state. - switch ((in[(*in_pos)++] >> 5) & 3) { - case 3: - dict_reset(dict); - coder->need_dictionary_reset = false; - - // Fall through + case SEQ_CONTROL: { + const uint32_t control = in[*in_pos]; + ++*in_pos; + + // Dictionary reset implies that next LZMA chunk has to set + // new properties. + if (control >= 0xE0 || control == 1) { + dict_reset(dict); + coder->need_dictionary_reset = false; + coder->need_properties = true; + } else if (coder->need_dictionary_reset) { + return LZMA_DATA_ERROR; + } - case 2: - if (coder->need_dictionary_reset) - return LZMA_DATA_ERROR; + if (control >= 0x80) { + // LZMA chunk. The highest five bits of the + // uncompressed size are taken from the control byte. + coder->uncompressed_size = (control & 0x1F) << 16; + coder->sequence = SEQ_UNCOMPRESSED_1; + // See if there are new properties or if we need to + // reset the state. + if (control >= 0xC0) { + // When there are new properties, state reset + // is done at SEQ_PROPERTIES. coder->need_properties = false; coder->next_sequence = SEQ_PROPERTIES; - break; - - case 1: - if (coder->need_properties) - return LZMA_DATA_ERROR; - coder->lzma.reset(coder->lzma.coder, - &coder->options); + } else if (coder->need_properties) { + return LZMA_DATA_ERROR; + } else { coder->next_sequence = SEQ_LZMA; - break; - - case 0: - if (coder->need_properties) - return LZMA_DATA_ERROR; - coder->next_sequence = SEQ_LZMA; - break; + // If only state reset is wanted with old + // properties, do the resetting here for + // simplicity. + if (control >= 0xA0) + coder->lzma.reset(coder->lzma.coder, + &coder->options); } - } else { - switch (in[(*in_pos)++]) { - case 0: - // End of payload marker + // End marker + if (control == 0x00) return LZMA_STREAM_END; - case 1: - // Dictionary reset - dict_reset(dict); - coder->need_dictionary_reset = false; - - // Fall through - - case 2: - if (coder->need_dictionary_reset) - return LZMA_DATA_ERROR; - - // Uncompressed chunk; we need to read total - // size first. - coder->sequence = SEQ_COMPRESSED_0; - coder->next_sequence = SEQ_COPY; - break; - - default: + // Invalid control values + if (control > 2) return LZMA_DATA_ERROR; - } + + // It's uncompressed chunk + coder->sequence = SEQ_COMPRESSED_0; + coder->next_sequence = SEQ_COPY; } break; + } case SEQ_UNCOMPRESSED_1: coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8; |