aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/liblzma/lz/lz_decoder.h14
-rw-r--r--src/liblzma/lzma/lzma_decoder.c720
2 files changed, 521 insertions, 213 deletions
diff --git a/src/liblzma/lz/lz_decoder.h b/src/liblzma/lz/lz_decoder.h
index 65acf0b1..3b41649c 100644
--- a/src/liblzma/lz/lz_decoder.h
+++ b/src/liblzma/lz/lz_decoder.h
@@ -180,12 +180,22 @@ dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len)
}
+static inline void
+dict_put(lzma_dict *dict, uint8_t byte)
+{
+ dict->buf[dict->pos++] = byte;
+
+ if (dict->pos > dict->full)
+ dict->full = dict->pos;
+}
+
+
/// Puts one byte into the dictionary. Returns true if the dictionary was
/// already full and the byte couldn't be added.
static inline bool
-dict_put(lzma_dict *dict, uint8_t byte)
+dict_put_safe(lzma_dict *dict, uint8_t byte)
{
- if (unlikely(dict->pos == dict->limit))
+ if (dict->pos == dict->limit)
return true;
dict->buf[dict->pos++] = byte;
diff --git a/src/liblzma/lzma/lzma_decoder.c b/src/liblzma/lzma/lzma_decoder.c
index 2e8393d6..6203bae9 100644
--- a/src/liblzma/lzma/lzma_decoder.c
+++ b/src/liblzma/lzma/lzma_decoder.c
@@ -7,6 +7,7 @@
///
// Authors: Igor Pavlov
// Lasse Collin
+// Jia Tan
//
///////////////////////////////////////////////////////////////////////////////
@@ -21,8 +22,12 @@
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
+// Minimum number of input bytes to safely decode one LZMA symbol.
+// The worst case is that we decode 22 bits using probabilities and 26
+// direct bits. This may decode at maximum 20 bytes of input plus one
+// extra byte after the final EOPM normalization.
+#define LZMA_IN_REQUIRED 21
-#ifdef HAVE_SMALL
// Macros for (somewhat) size-optimized code.
// This is used to decode the match length (how many bytes must be repeated
@@ -193,22 +198,26 @@ typedef struct {
enum {
SEQ_NORMALIZE,
SEQ_IS_MATCH,
- seq_8(SEQ_LITERAL),
- seq_8(SEQ_LITERAL_MATCHED),
+ SEQ_LITERAL,
+ SEQ_LITERAL_MATCHED,
SEQ_LITERAL_WRITE,
SEQ_IS_REP,
- seq_len(SEQ_MATCH_LEN),
- seq_6(SEQ_DIST_SLOT),
+ SEQ_MATCH_LEN_CHOICE,
+ SEQ_MATCH_LEN_CHOICE2,
+ SEQ_MATCH_LEN_BITTREE,
+ SEQ_DIST_SLOT,
SEQ_DIST_MODEL,
SEQ_DIRECT,
- seq_4(SEQ_ALIGN),
+ SEQ_ALIGN,
SEQ_EOPM,
SEQ_IS_REP0,
SEQ_SHORTREP,
SEQ_IS_REP0_LONG,
SEQ_IS_REP1,
SEQ_IS_REP2,
- seq_len(SEQ_REP_LEN),
+ SEQ_REP_LEN_CHOICE,
+ SEQ_REP_LEN_CHOICE2,
+ SEQ_REP_LEN_BITTREE,
SEQ_COPY,
} sequence;
@@ -309,8 +318,42 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
might_finish_without_eopm = true;
}
- // The main decoder loop. The "switch" is used to restart the decoder at
- // correct location. Once restarted, the "switch" is no longer used.
+ // Lookup table used to update the literal state.
+ // Compared to other state updates, this would need two branches.
+ // The lookup table is used by both Resumable and Non-resumable modes.
+ static const lzma_lzma_state next_state[] = {
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_MATCH_LIT_LIT,
+ STATE_REP_LIT_LIT,
+ STATE_SHORTREP_LIT_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT,
+ STATE_SHORTREP_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT
+ };
+
+ // The main decoder loop. The "switch" is used to resume the decoder at
+ // correct location. Once resumed, the "switch" is no longer used.
+ // The decoder loops is split into two modes:
+ //
+ // 1 - Non-resumable mode (fast). This is used when it is guaranteed
+ // there is enough input to decode the next symbol. If the output
+ // limit is reached, then the decoder loop will save the place
+ // for the resumable mode to continue. This mode is not used if
+ // HAVE_SMALL is defined. This is faster than Resumable mode
+ // because it reduces the number of branches needed and allows
+ // for more compiler optimizations.
+ //
+ // 2 - Resumable mode (slow). This is used when a previous decoder
+ // loop did not have enough space in the input or output buffers
+ // to complete. It uses sequence enum values to set remind
+ // coder->sequence where to resume in the decoder loop. This
+ // is the only mode used when HAVE_SMALL is defined.
+
switch (coder->sequence)
while (true) {
// Calculate new pos_state. This is skipped on the first loop
@@ -318,40 +361,32 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// variables.
pos_state = dict.pos & pos_mask;
- case SEQ_NORMALIZE:
- case SEQ_IS_MATCH:
- if (unlikely(might_finish_without_eopm
- && dict.pos == dict.limit)) {
- // In rare cases there is a useless byte that needs
- // to be read anyway.
- rc_normalize(SEQ_NORMALIZE);
+#ifndef HAVE_SMALL
- // If the range decoder state is such that we can
- // be at the end of the LZMA stream, then the
- // decoding is finished.
- if (rc_is_finished(rc)) {
- ret = LZMA_STREAM_END;
- goto out;
- }
+ ///////////////////////////////
+ // Non-resumable Mode (fast) //
+ ///////////////////////////////
- // If the caller hasn't allowed EOPM to be present
- // together with known uncompressed size, then the
- // LZMA stream is corrupt.
- if (!coder->allow_eopm) {
- ret = LZMA_DATA_ERROR;
- goto out;
- }
+ // If there is not enough room for another LZMA symbol
+ // go to Resumable mode.
+ if (rc_in_pos + LZMA_IN_REQUIRED > in_size
+ || dict.pos == dict.limit)
+ goto slow;
- // Otherwise continue decoding with the expectation
- // that the next LZMA symbol is EOPM.
- eopm_is_valid = true;
- }
+ // Decode the first bit from the next LZMA symbol.
+ // If the bit is a 0, then we handle it as a literal.
+ // If the bit is a 1, then it is a match of previously
+ // decoded data.
+ rc_if_0(coder->is_match[state][pos_state]) {
+ /////////////////////
+ // Decode literal. //
+ /////////////////////
- rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
+ // Update the RC that we have decoded a 0.
rc_update_0(coder->is_match[state][pos_state]);
- // It's a literal i.e. a single 8-bit byte.
-
+ // Get the correct probability array from lp and
+ // lc params.
probs = literal_subcoder(coder->literal,
literal_context_bits, literal_pos_mask,
dict.pos, dict_get(&dict, 0));
@@ -359,21 +394,17 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
if (is_literal_state(state)) {
// Decode literal without match byte.
-#ifdef HAVE_SMALL
- case SEQ_LITERAL:
- do {
- rc_bit(probs[symbol], , , SEQ_LITERAL);
- } while (symbol < (1 << 8));
-#else
- rc_bit_case(probs[symbol], , , SEQ_LITERAL0);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL1);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL2);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL3);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL4);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL5);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL6);
- rc_bit_case(probs[symbol], , , SEQ_LITERAL7);
-#endif
+ // We need to decode 8 bits, so instead
+ // of looping from 1 - 8, we unroll the
+ // loop for a speed optimization.
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
} else {
// Decode literal with match byte.
//
@@ -381,6 +412,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// ("match byte") to "len" to minimize the
// number of variables we need to store
// between decoder calls.
+
len = (uint32_t)(dict_get(&dict, rep0)) << 1;
// The usage of "offset" allows omitting some
@@ -389,99 +421,68 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// set to zero if match_bit didn't match.
offset = 0x100;
-#ifdef HAVE_SMALL
- case SEQ_LITERAL_MATCHED:
- do {
- const uint32_t match_bit
- = len & offset;
- const uint32_t subcoder_index
- = offset + match_bit
- + symbol;
-
- rc_bit(probs[subcoder_index],
- offset &= ~match_bit,
- offset &= match_bit,
- SEQ_LITERAL_MATCHED);
-
- // It seems to be faster to do this
- // here instead of putting it to the
- // beginning of the loop and then
- // putting the "case" in the middle
- // of the loop.
- len <<= 1;
-
- } while (symbol < (1 << 8));
-#else
// Unroll the loop.
uint32_t match_bit;
uint32_t subcoder_index;
-# define d(seq) \
- case seq: \
+# define decode_with_match_bit \
match_bit = len & offset; \
subcoder_index = offset + match_bit + symbol; \
rc_bit(probs[subcoder_index], \
offset &= ~match_bit, \
- offset &= match_bit, \
- seq)
+ offset &= match_bit)
- d(SEQ_LITERAL_MATCHED0);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED1);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED2);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED3);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED4);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED5);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED6);
+ decode_with_match_bit;
len <<= 1;
- d(SEQ_LITERAL_MATCHED7);
-# undef d
-#endif
+ decode_with_match_bit;
+# undef decode_match_bit
}
- //update_literal(state);
- // Use a lookup table to update to literal state,
- // since compared to other state updates, this would
- // need two branches.
- static const lzma_lzma_state next_state[] = {
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_MATCH_LIT_LIT,
- STATE_REP_LIT_LIT,
- STATE_SHORTREP_LIT_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT,
- STATE_SHORTREP_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT
- };
state = next_state[state];
- case SEQ_LITERAL_WRITE:
- if (unlikely(dict_put(&dict, symbol))) {
- coder->sequence = SEQ_LITERAL_WRITE;
- goto out;
- }
-
+ // Write decoded literal to dictionary
+ dict_put(&dict, symbol);
continue;
}
- // Instead of a new byte we are going to get a byte range
- // (distance and length) which will be repeated from our
- // output history.
+ ///////////////////
+ // Decode match. //
+ ///////////////////
+
+ // Instead of a new byte we are going to decode a
+ // distance-length pair. The distance represents how far
+ // back in the dictionary to begin copying. The length
+ // represents how many bytes to copy.
rc_update_1(coder->is_match[state][pos_state]);
- case SEQ_IS_REP:
- rc_if_0(coder->is_rep[state], SEQ_IS_REP) {
- // Not a repeated match
+ rc_if_0(coder->is_rep[state]) {
+ ///////////////////
+ // Simple match. //
+ ///////////////////
+
+ // Not a repeated match. In this case,
+ // the length (how many bytes to copy) must be
+ // decoded first. Then, the distance (where to
+ // start copying) is decoded.
+ //
+ // This is also how we know when we are done
+ // decoding. If the distance decodes to UINT32_MAX,
+ // then we know to stop decoding (end of payload
+ // marker).
+
rc_update_0(coder->is_rep[state]);
update_match(state);
@@ -492,45 +493,50 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
rep1 = rep0;
// Decode the length of the match.
- len_decode(len, coder->match_len_decoder,
- pos_state, SEQ_MATCH_LEN);
+ len_decode_fast(len, coder->match_len_decoder,
+ pos_state);
+
+ // Next, decode the distance into rep0.
- // Prepare to decode the highest two bits of the
- // match distance.
+ // The next 6 bits determine how to decode the
+ // rest of the distance.
probs = coder->dist_slot[get_dist_state(len)];
symbol = 1;
-#ifdef HAVE_SMALL
- case SEQ_DIST_SLOT:
- do {
- rc_bit(probs[symbol], , , SEQ_DIST_SLOT);
- } while (symbol < DIST_SLOTS);
-#else
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT0);
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT1);
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT2);
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT3);
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT4);
- rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT5);
-#endif
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+ rc_bit(probs[symbol], , );
+
// Get rid of the highest bit that was needed for
// indexing of the probability array.
symbol -= DIST_SLOTS;
assert(symbol <= 63);
if (symbol < DIST_MODEL_START) {
- // Match distances [0, 3] have only two bits.
+ // If the decoded symbol is < DIST_MODEL_START
+ // then we use its value directly as the
+ // match distance. No other bits are needed.
+ // The only possible distance values
+ // are [0, 3].
rep0 = symbol;
} else {
- // Decode the lowest [1, 29] bits of
- // the match distance.
+ // Use the first two bits of symbol as the
+ // highest bits of the match distance.
+
+ // "limit" represents the number of low bits
+ // to decode.
limit = (symbol >> 1) - 1;
assert(limit >= 1 && limit <= 30);
rep0 = 2 + (symbol & 1);
if (symbol < DIST_MODEL_END) {
- // Prepare to decode the low bits for
- // a distance of [4, 127].
+ // When symbol is > DIST_MODEL_START,
+ // but symbol < DIST_MODEL_END, then
+ // it can decode distances between
+ // [4, 127].
assert(limit <= 5);
rep0 <<= limit;
assert(rep0 <= 96);
@@ -548,52 +554,39 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
- symbol - 1;
symbol = 1;
offset = 0;
- case SEQ_DIST_MODEL:
-#ifdef HAVE_SMALL
- do {
- rc_bit(probs[symbol], ,
- rep0 += 1U << offset,
- SEQ_DIST_MODEL);
- } while (++offset < limit);
-#else
+
switch (limit) {
case 5:
assert(offset == 0);
rc_bit(probs[symbol], ,
- rep0 += 1U,
- SEQ_DIST_MODEL);
+ rep0 += 1U);
++offset;
--limit;
case 4:
rc_bit(probs[symbol], ,
- rep0 += 1U << offset,
- SEQ_DIST_MODEL);
+ rep0 += 1U << offset);
++offset;
--limit;
case 3:
rc_bit(probs[symbol], ,
- rep0 += 1U << offset,
- SEQ_DIST_MODEL);
+ rep0 += 1U << offset);
++offset;
--limit;
case 2:
rc_bit(probs[symbol], ,
- rep0 += 1U << offset,
- SEQ_DIST_MODEL);
+ rep0 += 1U << offset);
++offset;
--limit;
case 1:
// We need "symbol" only for
// indexing the probability
// array, thus we can use
- // rc_bit_last() here to omit
- // the unneeded updating of
- // "symbol".
+ // rc_bit_last() here to
+ // omit the unneeded updating
+ // of "symbol".
rc_bit_last(probs[symbol], ,
- rep0 += 1U << offset,
- SEQ_DIST_MODEL);
+ rep0 += 1U << offset);
}
-#endif
} else {
// The distance is >= 128. Decode the
// lower bits without probabilities
@@ -602,44 +595,39 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
assert(limit >= 6);
limit -= ALIGN_BITS;
assert(limit >= 2);
- case SEQ_DIRECT:
+
// Not worth manual unrolling
do {
- rc_direct(rep0, SEQ_DIRECT);
+ rc_direct(rep0);
} while (--limit > 0);
// Decode the lowest four bits using
// probabilities.
rep0 <<= ALIGN_BITS;
symbol = 1;
-#ifdef HAVE_SMALL
- offset = 0;
- case SEQ_ALIGN:
- do {
- rc_bit(coder->pos_align[
- symbol], ,
- rep0 += 1U << offset,
- SEQ_ALIGN);
- } while (++offset < ALIGN_BITS);
-#else
- case SEQ_ALIGN0:
+
rc_bit(coder->pos_align[symbol], ,
- rep0 += 1, SEQ_ALIGN0);
- case SEQ_ALIGN1:
+ rep0 += 1);
+
rc_bit(coder->pos_align[symbol], ,
- rep0 += 2, SEQ_ALIGN1);
- case SEQ_ALIGN2:
+ rep0 += 2);
+
rc_bit(coder->pos_align[symbol], ,
- rep0 += 4, SEQ_ALIGN2);
- case SEQ_ALIGN3:
- // Like in SEQ_DIST_MODEL, we don't
- // need "symbol" for anything else
- // than indexing the probability array.
- rc_bit_last(coder->pos_align[symbol], ,
- rep0 += 8, SEQ_ALIGN3);
-#endif
+ rep0 += 4);
+
+ // Like when distance [4, 127], we
+ // don't need "symbol" for anything
+ // other than indexing the probability
+ // array.
+ rc_bit_last(
+ coder->pos_align[symbol], ,
+ rep0 += 8);
if (rep0 == UINT32_MAX) {
+ ///////////////////////////
+ // End of payload marker //
+ ///////////////////////////
+
// End of payload marker was
// found. It may only be
// present if
@@ -657,10 +645,9 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
goto out;
}
- case SEQ_EOPM:
// LZMA1 stream with
// end-of-payload marker.
- rc_normalize(SEQ_EOPM);
+ rc_normalize();
ret = rc_is_finished(rc)
? LZMA_STREAM_END
: LZMA_DATA_ERROR;
@@ -678,10 +665,12 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
} else {
rc_update_1(coder->is_rep[state]);
- // Repeated match
- //
- // The match distance is a value that we have had
- // earlier. The latest four match distances are
+ /////////////////////
+ // Repeated match. //
+ /////////////////////
+
+ // The match distance is a value that we have decoded
+ // recently. The latest four match distances are
// available as rep0, rep1, rep2 and rep3. We will
// now decode which of them is the new distance.
//
@@ -692,13 +681,331 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
goto out;
}
- case SEQ_IS_REP0:
- rc_if_0(coder->is_rep0[state], SEQ_IS_REP0) {
+ rc_if_0(coder->is_rep0[state]) {
rc_update_0(coder->is_rep0[state]);
// The distance is rep0.
+ // Decode the next bit to determine if 1 byte
+ // should be copied from rep0 distance or
+ // if the number of bytes needs to be decoded.
+
+ // If the next bit is 0, then it is a
+ // "Short Rep Match" and only 1 bit is copied.
+ // Otherwise, the length of the match is
+ // decoded after the "else" statement.
+ rc_if_0(coder->is_rep0_long[state][pos_state]) {
+ rc_update_0(coder->is_rep0_long[
+ state][pos_state]);
+
+ update_short_rep(state);
+ dict_put(&dict, dict_get(&dict, rep0));
+ continue;
+ }
+
+ // Repeating more than one byte at
+ // distance of rep0.
+ rc_update_1(coder->is_rep0_long[
+ state][pos_state]);
+
+ } else {
+ rc_update_1(coder->is_rep0[state]);
+
+ // The distance is rep1, rep2 or rep3. Once
+ // we find out which one of these three, it
+ // is stored to rep0 and rep1, rep2 and rep3
+ // are updated accordingly. There is no
+ // "Short Rep Match" option, so the length
+ // of the match must always be decoded next.
+ rc_if_0(coder->is_rep1[state]) {
+ // The distance is rep1.
+ rc_update_0(coder->is_rep1[state]);
+
+ const uint32_t distance = rep1;
+ rep1 = rep0;
+ rep0 = distance;
+
+ } else {
+ rc_update_1(coder->is_rep1[state]);
+
+ rc_if_0(coder->is_rep2[state]) {
+ // The distance is rep2.
+ rc_update_0(coder->is_rep2[
+ state]);
+
+ const uint32_t distance = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ rep0 = distance;
+
+ } else {
+ // The distance is rep3.
+ rc_update_1(coder->is_rep2[
+ state]);
+
+ const uint32_t distance = rep3;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ }
+ }
+
+ update_long_rep(state);
+
+ // Decode the length of the repeated match.
+ len_decode_fast(len, coder->rep_len_decoder,
+ pos_state);
+ }
+
+ /////////////////////////////////
+ // Repeat from history buffer. //
+ /////////////////////////////////
+
+ // The length is always between these limits. There is no way
+ // to trigger the algorithm to set len outside this range.
+ assert(len >= MATCH_LEN_MIN);
+ assert(len <= MATCH_LEN_MAX);
+
+ // Repeat len bytes from distance of rep0.
+ if (unlikely(dict_repeat(&dict, rep0, &len))) {
+ coder->sequence = SEQ_COPY;
+ goto out;
+ }
+
+ continue;
+
+slow:
+#endif
+ ///////////////////////////
+ // Resumable Mode (slow) //
+ ///////////////////////////
+
+ // This is very similar to Non-resumable Mode, so most of the
+ // comments are not repeated. The main differences are:
+ // - case labels are used to resume at the correct location.
+ // - Loops are not unrolled.
+ // - Range coder macros take an extra sequence argument
+ // so they can save to coder->sequence the location to
+ // resume in case there is not enough input.
+ case SEQ_NORMALIZE:
+ case SEQ_IS_MATCH:
+ if (unlikely(might_finish_without_eopm
+ && dict.pos == dict.limit)) {
+ // In rare cases there is a useless byte that needs
+ // to be read anyway.
+ rc_normalize_safe(SEQ_NORMALIZE);
+
+ // If the range decoder state is such that we can
+ // be at the end of the LZMA stream, then the
+ // decoding is finished.
+ if (rc_is_finished(rc)) {
+ ret = LZMA_STREAM_END;
+ goto out;
+ }
+
+ // If the caller hasn't allowed EOPM to be present
+ // together with known uncompressed size, then the
+ // LZMA stream is corrupt.
+ if (!coder->allow_eopm) {
+ ret = LZMA_DATA_ERROR;
+ goto out;
+ }
+
+ // Otherwise continue decoding with the expectation
+ // that the next LZMA symbol is EOPM.
+ eopm_is_valid = true;
+ }
+
+ rc_if_0_safe(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
+ /////////////////////
+ // Decode literal. //
+ /////////////////////
+
+ rc_update_0(coder->is_match[state][pos_state]);
+
+ probs = literal_subcoder(coder->literal,
+ literal_context_bits, literal_pos_mask,
+ dict.pos, dict_get(&dict, 0));
+ symbol = 1;
+
+ if (is_literal_state(state)) {
+ // Decode literal without match byte.
+ // The "slow" version does not unroll
+ // the loop.
+ case SEQ_LITERAL:
+ do {
+ rc_bit_safe(probs[symbol], , ,
+ SEQ_LITERAL);
+ } while (symbol < (1 << 8));
+ } else {
+ // Decode literal with match byte.
+ len = (uint32_t)(dict_get(&dict, rep0)) << 1;
+
+ offset = 0x100;
+
+ case SEQ_LITERAL_MATCHED:
+ do {
+ const uint32_t match_bit
+ = len & offset;
+ const uint32_t subcoder_index
+ = offset + match_bit
+ + symbol;
+
+ rc_bit_safe(probs[subcoder_index],
+ offset &= ~match_bit,
+ offset &= match_bit,
+ SEQ_LITERAL_MATCHED);
+
+ // It seems to be faster to do this
+ // here instead of putting it to the
+ // beginning of the loop and then
+ // putting the "case" in the middle
+ // of the loop.
+ len <<= 1;
+
+ } while (symbol < (1 << 8));
+ }
+
+ state = next_state[state];
+
+ case SEQ_LITERAL_WRITE:
+ if (dict_put_safe(&dict, symbol)) {
+ coder->sequence = SEQ_LITERAL_WRITE;
+ goto out;
+ }
+
+ continue;
+ }
+
+ ///////////////////
+ // Decode match. //
+ ///////////////////
+
+ rc_update_1(coder->is_match[state][pos_state]);
+
+ case SEQ_IS_REP:
+ rc_if_0_safe(coder->is_rep[state], SEQ_IS_REP) {
+ ///////////////////
+ // Simple match. //
+ ///////////////////
+
+ rc_update_0(coder->is_rep[state]);
+ update_match(state);
+
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+
+ len_decode(len, coder->match_len_decoder,
+ pos_state, SEQ_MATCH_LEN);
+
+ probs = coder->dist_slot[get_dist_state(len)];
+ symbol = 1;
+
+ case SEQ_DIST_SLOT:
+ do {
+ rc_bit_safe(probs[symbol], , , SEQ_DIST_SLOT);
+ } while (symbol < DIST_SLOTS);
+
+ symbol -= DIST_SLOTS;
+ assert(symbol <= 63);
+
+ if (symbol < DIST_MODEL_START) {
+ rep0 = symbol;
+ } else {
+ limit = (symbol >> 1) - 1;
+ assert(limit >= 1 && limit <= 30);
+ rep0 = 2 + (symbol & 1);
+
+ if (symbol < DIST_MODEL_END) {
+ assert(limit <= 5);
+ rep0 <<= limit;
+ assert(rep0 <= 96);
+ // -1 is fine, because we start
+ // decoding at probs[1], not probs[0].
+ // NOTE: This violates the C standard,
+ // since we are doing pointer
+ // arithmetic past the beginning of
+ // the array.
+ assert((int32_t)(rep0 - symbol - 1)
+ >= -1);
+ assert((int32_t)(rep0 - symbol - 1)
+ <= 82);
+ probs = coder->pos_special + rep0
+ - symbol - 1;
+ symbol = 1;
+ offset = 0;
+ case SEQ_DIST_MODEL:
+ do {
+ rc_bit_safe(probs[symbol], ,
+ rep0 += 1U << offset,
+ SEQ_DIST_MODEL);
+ } while (++offset < limit);
+ } else {
+ assert(symbol >= 14);
+ assert(limit >= 6);
+ limit -= ALIGN_BITS;
+ assert(limit >= 2);
+ case SEQ_DIRECT:
+ do {
+ rc_direct_safe(rep0,
+ SEQ_DIRECT);
+ } while (--limit > 0);
+
+ rep0 <<= ALIGN_BITS;
+ symbol = 1;
+
+ offset = 0;
+ case SEQ_ALIGN:
+ do {
+ rc_bit_safe(coder->pos_align[
+ symbol], ,
+ rep0 += 1U << offset,
+ SEQ_ALIGN);
+ } while (++offset < ALIGN_BITS);
+
+ // End of payload marker
+ if (rep0 == UINT32_MAX) {
+ if (!eopm_is_valid) {
+ ret = LZMA_DATA_ERROR;
+ goto out;
+ }
+
+ case SEQ_EOPM:
+ rc_normalize_safe(SEQ_EOPM);
+ ret = rc_is_finished(rc)
+ ? LZMA_STREAM_END
+ : LZMA_DATA_ERROR;
+ goto out;
+ }
+ }
+ }
+
+ if (unlikely(!dict_is_distance_valid(&dict, rep0))) {
+ ret = LZMA_DATA_ERROR;
+ goto out;
+ }
+
+ } else {
+ /////////////////////
+ // Repeated match. //
+ /////////////////////
+
+ rc_update_1(coder->is_rep[state]);
+
+ if (unlikely(!dict_is_distance_valid(&dict, 0))) {
+ ret = LZMA_DATA_ERROR;
+ goto out;
+ }
+
+ case SEQ_IS_REP0:
+ rc_if_0_safe(coder->is_rep0[state], SEQ_IS_REP0) {
+ rc_update_0(coder->is_rep0[state]);
+
case SEQ_IS_REP0_LONG:
- rc_if_0(coder->is_rep0_long[state][pos_state],
+ rc_if_0_safe(coder->is_rep0_long
+ [state][pos_state],
SEQ_IS_REP0_LONG) {
rc_update_0(coder->is_rep0_long[
state][pos_state]);
@@ -706,8 +1013,9 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
update_short_rep(state);
case SEQ_SHORTREP:
- if (unlikely(dict_put(&dict, dict_get(
- &dict, rep0)))) {
+ if (dict_put_safe(&dict,
+ dict_get(&dict,
+ rep0))) {
coder->sequence = SEQ_SHORTREP;
goto out;
}
@@ -715,8 +1023,6 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
continue;
}
- // Repeating more than one byte at
- // distance of rep0.
rc_update_1(coder->is_rep0_long[
state][pos_state]);
@@ -724,11 +1030,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
rc_update_1(coder->is_rep0[state]);
case SEQ_IS_REP1:
- // The distance is rep1, rep2 or rep3. Once
- // we find out which one of these three, it
- // is stored to rep0 and rep1, rep2 and rep3
- // are updated accordingly.
- rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) {
+ rc_if_0_safe(coder->is_rep1[state], SEQ_IS_REP1) {
rc_update_0(coder->is_rep1[state]);
const uint32_t distance = rep1;
@@ -738,7 +1040,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
} else {
rc_update_1(coder->is_rep1[state]);
case SEQ_IS_REP2:
- rc_if_0(coder->is_rep2[state],
+ rc_if_0_safe(coder->is_rep2[state],
SEQ_IS_REP2) {
rc_update_0(coder->is_rep2[
state]);
@@ -763,7 +1065,6 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
update_long_rep(state);
- // Decode the length of the repeated match.
len_decode(len, coder->rep_len_decoder,
pos_state, SEQ_REP_LEN);
}
@@ -772,13 +1073,10 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// Repeat from history buffer. //
/////////////////////////////////
- // The length is always between these limits. There is no way
- // to trigger the algorithm to set len outside this range.
assert(len >= MATCH_LEN_MIN);
assert(len <= MATCH_LEN_MAX);
case SEQ_COPY:
- // Repeat len bytes from distance of rep0.
if (unlikely(dict_repeat(&dict, rep0, &len))) {
coder->sequence = SEQ_COPY;
goto out;