LZMA2 decoder cleanups. Make it require new LZMA properties
also in the first LZMA chunk after a dictionary reset in uncompressed chunk.
This commit is contained in:
parent
656ec87882
commit
cd70801520
@ -70,76 +70,63 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
|
|||||||
// at least one byte of input.
|
// at least one byte of input.
|
||||||
while (*in_pos < in_size || coder->sequence == SEQ_LZMA)
|
while (*in_pos < in_size || coder->sequence == SEQ_LZMA)
|
||||||
switch (coder->sequence) {
|
switch (coder->sequence) {
|
||||||
case SEQ_CONTROL:
|
case SEQ_CONTROL: {
|
||||||
if (in[*in_pos] & 0x80) {
|
const uint32_t control = in[*in_pos];
|
||||||
// Get the highest five bits of uncompressed size.
|
++*in_pos;
|
||||||
coder->uncompressed_size
|
|
||||||
= (uint32_t)(in[*in_pos] & 0x1F) << 16;
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
coder->sequence = SEQ_UNCOMPRESSED_1;
|
||||||
|
|
||||||
// See if we need to reset dictionary or state.
|
// See if there are new properties or if we need to
|
||||||
switch ((in[(*in_pos)++] >> 5) & 3) {
|
// reset the state.
|
||||||
case 3:
|
if (control >= 0xC0) {
|
||||||
dict_reset(dict);
|
// When there are new properties, state reset
|
||||||
coder->need_dictionary_reset = false;
|
// is done at SEQ_PROPERTIES.
|
||||||
|
|
||||||
// Fall through
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
if (coder->need_dictionary_reset)
|
|
||||||
return LZMA_DATA_ERROR;
|
|
||||||
|
|
||||||
coder->need_properties = false;
|
coder->need_properties = false;
|
||||||
coder->next_sequence = SEQ_PROPERTIES;
|
coder->next_sequence = SEQ_PROPERTIES;
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
} else if (coder->need_properties) {
|
||||||
if (coder->need_properties)
|
return LZMA_DATA_ERROR;
|
||||||
return LZMA_DATA_ERROR;
|
|
||||||
|
|
||||||
coder->lzma.reset(coder->lzma.coder,
|
|
||||||
&coder->options);
|
|
||||||
|
|
||||||
|
} else {
|
||||||
coder->next_sequence = SEQ_LZMA;
|
coder->next_sequence = SEQ_LZMA;
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
// If only state reset is wanted with old
|
||||||
if (coder->need_properties)
|
// properties, do the resetting here for
|
||||||
return LZMA_DATA_ERROR;
|
// simplicity.
|
||||||
|
if (control >= 0xA0)
|
||||||
coder->next_sequence = SEQ_LZMA;
|
coder->lzma.reset(coder->lzma.coder,
|
||||||
break;
|
&coder->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (in[(*in_pos)++]) {
|
// End marker
|
||||||
case 0:
|
if (control == 0x00)
|
||||||
// End of payload marker
|
|
||||||
return LZMA_STREAM_END;
|
return LZMA_STREAM_END;
|
||||||
|
|
||||||
case 1:
|
// Invalid control values
|
||||||
// Dictionary reset
|
if (control > 2)
|
||||||
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:
|
|
||||||
return LZMA_DATA_ERROR;
|
return LZMA_DATA_ERROR;
|
||||||
}
|
|
||||||
|
// It's uncompressed chunk
|
||||||
|
coder->sequence = SEQ_COMPRESSED_0;
|
||||||
|
coder->next_sequence = SEQ_COPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SEQ_UNCOMPRESSED_1:
|
case SEQ_UNCOMPRESSED_1:
|
||||||
coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8;
|
coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8;
|
||||||
|
Loading…
Reference in New Issue
Block a user