aboutsummaryrefslogblamecommitdiff
path: root/src/liblzma/lzma/lzma_decoder.c
blob: 0abed02b81546ba434c433f742540d315140a27c (plain) (tree)
1
2
3
4
5
6
7
8
9

                                



                                                                               


                            
                       
  

                                                                               
                       

                         

                          





                                                              

                                                                      

                                                             
 
 
                                             


                                                                           
                                                
      
                      
                                                   



                                           
                  

                                         
                                                             



                                                                   
                          




                                                                  

                   


                       
                                                                  

                                   

           
 


                                                                       
      
                     
                              
                                         


                                                                    
                  
                                         
                                       
                                                  


                                                                             
                          
                                                  
                                                                
                                                         

                                                                               



                   

                                                                








                                                         
                


                           
 
                                                    
                                                                     


















                                                                             
                                                       

                                                         


                                                                            
                                                       
 
                                                                             
                                              
                                                                 
 

                                                                         
                                          
 

                                              
 

                                            
 


                           
 

                              
 

                                                       
 



                                                                
 
                                            
                                      
                              
 
                                                                     


                                       




                                                                          







                                                       

                                    

                                  



                                      
                               
                           
                          





                                 


                                    




















                                                                           
                     

 
               
                                                         

                                                        
 

                                                       



                            





                                                                 







                                                                    



                                           
                        
                                                          







                                      

                                                  







                                                                       
                                                          






                                                                          



                                                                        
                                                          


                                                                          






                                                                               
                                                                           

                                                 
 

















                                                                               






                                                                             
                  
 


                                               
 





                                                                           
                                  
 







                                                                      
 
                                                                  
                                                                       
 

                                                                        
                                                                
                                                                           
                                                                    
 
                                                      

                                                             
                                                                     
                                                      
                                

                                                              
                                                                  

                                                                       
                         
 

                                                              


                                 







                                                                        
 
                                                               
 














                                                                           
                                                          

                                            






                                                                       



                                                                      
 

                                                                      
                                                                      
 
                                                        

                                             
                                                        




                                                                              

                                              




                                                                            



                                                                  
                                                              



                                                                             


                                                           
 












                                                                              
                                                   
 


                                                                        








                                                                            




                                                                              
                                        
                                                                             



                                                                           
 

                                                            
 
                                                               



                                                                            



















                                                                              
                                 
                         
 



                                                                             


                         
                                                          
 





                                                                             

                                                                          






                                                                          
 
                                                        
                                                                   

                                                        











































































































































                                                                                
                                                                           
                                                                    


                                                      

                                                             








                                                                      

                                                              



























                                                                             














































































                                                                              

                                                                    

                                                            

                                                   

                                            





                                                                          
                                                                   



                                                                      
 
                                                                 











                                                                               
                  
     
      





                                                                              

                                                                         





























                                                                             
                              

                                                                   


                                                                           
 

                                                                
                          


                                                                       


                                                                               
 
                                                 

                                 


                                                                   
                                
                                                                   
 
                         
                                                                                  
                                                                           
 


                                                                       
 
                                        

                                                                           
                                                                           







                                                                               
 
                                                



                                                                               
                                                            


                                                                
                                         
                                 

                         
                                               
 

                                                                

                 



                                                 

                                             
 
                      



                                                               

         

                     
 


                                          
 
                                          
 





                             







                                                                           
                                                           

                                                                  


                                                                         
                                                                   



                                                                          

         
                                     


                                                                              
                                               


                   



           

                                                                      
 
                                              
                                                     
                                       

 
 
           
                                                    
 
                                              
                                               
 

                                                                   
 
                                                                         
                                                  
 
                                          
                                                               
 
                                                  
                                                                          

                




                                     
                                                  

                        
                            


                                               


                                                                 

                 



                                             

         

                                                                   
 
                                                                      
                                                 
 
                                                    

                                          
                                                          



                                                    

                                                                               
                                                                      
                                              
                                                                      
                                              
 
                                                                    
                                              
                                                                    
                                              

         














                                                                    
                                                                              
                                                                              

                                
                                                                              






                                                                  
 

                                                                         


                                                                 
 



                       



                                                                       
                                                                       
                                                                              
 


                                       























                                                                              
                                                 
                                                             

                                               
                                                                      





                       
                                                                              







                                                                          


 
           
                                                                 




                                                                



                                             
 
                                                         
 


               
                                                       

                                                     

                                                                   






                                               

                                  
                                                           



               
                                                                       


                                                        
                                          











                                                                           
                                             
 

                                  






                                  
                                  
 
// SPDX-License-Identifier: 0BSD

///////////////////////////////////////////////////////////////////////////////
//
/// \file       lzma_decoder.c
/// \brief      LZMA decoder
///
//  Authors:    Igor Pavlov
//              Lasse Collin
//              Jia Tan
//
///////////////////////////////////////////////////////////////////////////////

#include "lz_decoder.h"
#include "lzma_common.h"
#include "lzma_decoder.h"
#include "range_decoder.h"

// The macros unroll loops with switch statements.
// Silence warnings about missing fall-through comments.
#if TUKLIB_GNUC_REQ(7, 0)
#	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.
#define LZMA_IN_REQUIRED 20


// Macros for (somewhat) size-optimized code.
// This is used to decode the match length (how many bytes must be repeated
// from the dictionary). This version is used in the Resumable mode and
// does not unroll any loops.
#define len_decode(target, ld, pos_state, seq) \
do { \
case seq ## _CHOICE: \
	rc_if_0_safe(ld.choice, seq ## _CHOICE) { \
		rc_update_0(ld.choice); \
		probs = ld.low[pos_state];\
		limit = LEN_LOW_SYMBOLS; \
		target = MATCH_LEN_MIN; \
	} else { \
		rc_update_1(ld.choice); \
case seq ## _CHOICE2: \
		rc_if_0_safe(ld.choice2, seq ## _CHOICE2) { \
			rc_update_0(ld.choice2); \
			probs = ld.mid[pos_state]; \
			limit = LEN_MID_SYMBOLS; \
			target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
		} else { \
			rc_update_1(ld.choice2); \
			probs = ld.high; \
			limit = LEN_HIGH_SYMBOLS; \
			target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS \
					+ LEN_MID_SYMBOLS; \
		} \
	} \
	symbol = 1; \
case seq ## _BITTREE: \
	do { \
		rc_bit_safe(probs[symbol], , , seq ## _BITTREE); \
	} while (symbol < limit); \
	target += symbol - limit; \
} while (0)


// This is the faster version of the match length decoder that does not
// worry about being resumable. It unrolls the bittree decoding loop.
#define len_decode_fast(target, ld, pos_state) \
do { \
	symbol = 1; \
	rc_if_0(ld.choice) { \
		rc_update_0(ld.choice); \
		rc_bittree3(ld.low[pos_state], \
				-LEN_LOW_SYMBOLS + MATCH_LEN_MIN); \
		target = symbol; \
	} else { \
		rc_update_1(ld.choice); \
		rc_if_0(ld.choice2) { \
			rc_update_0(ld.choice2); \
			rc_bittree3(ld.mid[pos_state], -LEN_MID_SYMBOLS \
					+ MATCH_LEN_MIN + LEN_LOW_SYMBOLS); \
			target = symbol; \
		} else { \
			rc_update_1(ld.choice2); \
			rc_bittree8(ld.high, -LEN_HIGH_SYMBOLS \
					+ MATCH_LEN_MIN \
					+ LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS); \
			target = symbol; \
		} \
	} \
} while (0)


/// Length decoder probabilities; see comments in lzma_common.h.
typedef struct {
	probability choice;
	probability choice2;
	probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
	probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
	probability high[LEN_HIGH_SYMBOLS];
} lzma_length_decoder;


typedef struct {
	///////////////////
	// Probabilities //
	///////////////////

	/// Literals; see comments in lzma_common.h.
	probability literal[LITERAL_CODERS_MAX * LITERAL_CODER_SIZE];

	/// If 1, it's a match. Otherwise it's a single 8-bit literal.
	probability is_match[STATES][POS_STATES_MAX];

	/// If 1, it's a repeated match. The distance is one of rep0 .. rep3.
	probability is_rep[STATES];

	/// If 0, distance of a repeated match is rep0.
	/// Otherwise check is_rep1.
	probability is_rep0[STATES];

	/// If 0, distance of a repeated match is rep1.
	/// Otherwise check is_rep2.
	probability is_rep1[STATES];

	/// If 0, distance of a repeated match is rep2. Otherwise it is rep3.
	probability is_rep2[STATES];

	/// If 1, the repeated match has length of one byte. Otherwise
	/// the length is decoded from rep_len_decoder.
	probability is_rep0_long[STATES][POS_STATES_MAX];

	/// Probability tree for the highest two bits of the match distance.
	/// There is a separate probability tree for match lengths of
	/// 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
	probability dist_slot[DIST_STATES][DIST_SLOTS];

	/// Probability trees for additional bits for match distance when the
	/// distance is in the range [4, 127].
	probability pos_special[FULL_DISTANCES - DIST_MODEL_END];

	/// Probability tree for the lowest four bits of a match distance
	/// that is equal to or greater than 128.
	probability pos_align[ALIGN_SIZE];

	/// Length of a normal match
	lzma_length_decoder match_len_decoder;

	/// Length of a repeated match
	lzma_length_decoder rep_len_decoder;

	///////////////////
	// Decoder state //
	///////////////////

	// Range coder
	lzma_range_decoder rc;

	// Types of the most recently seen LZMA symbols
	lzma_lzma_state state;

	uint32_t rep0;      ///< Distance of the latest match
	uint32_t rep1;      ///< Distance of second latest match
	uint32_t rep2;      ///< Distance of third latest match
	uint32_t rep3;      ///< Distance of fourth latest match

	uint32_t pos_mask; // (1U << pb) - 1
	uint32_t literal_context_bits;
	uint32_t literal_mask;

	/// Uncompressed size as bytes, or LZMA_VLI_UNKNOWN if end of
	/// payload marker is expected.
	lzma_vli uncompressed_size;

	/// True if end of payload marker (EOPM) is allowed even when
	/// uncompressed_size is known; false if EOPM must not be present.
	/// This is ignored if uncompressed_size == LZMA_VLI_UNKNOWN.
	bool allow_eopm;

	////////////////////////////////
	// State of incomplete symbol //
	////////////////////////////////

	/// Position where to continue the decoder loop
	enum {
		SEQ_NORMALIZE,
		SEQ_IS_MATCH,
		SEQ_LITERAL,
		SEQ_LITERAL_MATCHED,
		SEQ_LITERAL_WRITE,
		SEQ_IS_REP,
		SEQ_MATCH_LEN_CHOICE,
		SEQ_MATCH_LEN_CHOICE2,
		SEQ_MATCH_LEN_BITTREE,
		SEQ_DIST_SLOT,
		SEQ_DIST_MODEL,
		SEQ_DIRECT,
		SEQ_ALIGN,
		SEQ_EOPM,
		SEQ_IS_REP0,
		SEQ_SHORTREP,
		SEQ_IS_REP0_LONG,
		SEQ_IS_REP1,
		SEQ_IS_REP2,
		SEQ_REP_LEN_CHOICE,
		SEQ_REP_LEN_CHOICE2,
		SEQ_REP_LEN_BITTREE,
		SEQ_COPY,
	} sequence;

	/// Base of the current probability tree
	probability *probs;

	/// Symbol being decoded. This is also used as an index variable in
	/// bittree decoders: probs[symbol]
	uint32_t symbol;

	/// Used as a loop termination condition on bittree decoders and
	/// direct bits decoder.
	uint32_t limit;

	/// Matched literal decoder: 0x100 or 0 to help avoiding branches.
	/// Bittree reverse decoders: Offset of the next bit: 1 << offset
	uint32_t offset;

	/// If decoding a literal: match byte.
	/// If decoding a match: length of the match.
	uint32_t len;
} lzma_lzma1_decoder;


static lzma_ret
lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
		const uint8_t *restrict in,
		size_t *restrict in_pos, size_t in_size)
{
	lzma_lzma1_decoder *restrict coder = coder_ptr;

	////////////////////
	// Initialization //
	////////////////////

	{
		const lzma_ret ret = rc_read_init(
				&coder->rc, in, in_pos, in_size);
		if (ret != LZMA_STREAM_END)
			return ret;
	}

	///////////////
	// Variables //
	///////////////

	// Making local copies of often-used variables improves both
	// speed and readability.

	lzma_dict dict = *dictptr;

	const size_t dict_start = dict.pos;

	// Range decoder
	rc_to_local(coder->rc, *in_pos, LZMA_IN_REQUIRED);

	// State
	uint32_t state = coder->state;
	uint32_t rep0 = coder->rep0;
	uint32_t rep1 = coder->rep1;
	uint32_t rep2 = coder->rep2;
	uint32_t rep3 = coder->rep3;

	const uint32_t pos_mask = coder->pos_mask;

	// These variables are actually needed only if we last time ran
	// out of input in the middle of the decoder loop.
	probability *probs = coder->probs;
	uint32_t symbol = coder->symbol;
	uint32_t limit = coder->limit;
	uint32_t offset = coder->offset;
	uint32_t len = coder->len;

	const uint32_t literal_mask = coder->literal_mask;
	const uint32_t literal_context_bits = coder->literal_context_bits;

	// Temporary variables
	uint32_t pos_state = dict.pos & pos_mask;

	lzma_ret ret = LZMA_OK;

	// This is true when the next LZMA symbol is allowed to be EOPM.
	// That is, if this is false, then EOPM is considered
	// an invalid symbol and we will return LZMA_DATA_ERROR.
	//
	// EOPM is always required (not just allowed) when
	// the uncompressed size isn't known. When uncompressed size
	// is known, eopm_is_valid may be set to true later.
	bool eopm_is_valid = coder->uncompressed_size == LZMA_VLI_UNKNOWN;

	// If uncompressed size is known and there is enough output space
	// to decode all the data, limit the available buffer space so that
	// the main loop won't try to decode past the end of the stream.
	bool might_finish_without_eopm = false;
	if (coder->uncompressed_size != LZMA_VLI_UNKNOWN
			&& coder->uncompressed_size <= dict.limit - dict.pos) {
		dict.limit = dict.pos + (size_t)(coder->uncompressed_size);
		might_finish_without_eopm = true;
	}

	// 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
		// since we already calculated it when setting up the local
		// variables.
		pos_state = dict.pos & pos_mask;

#ifndef HAVE_SMALL

		///////////////////////////////
		// Non-resumable Mode (fast) //
		///////////////////////////////

		// Go to Resumable mode (1) if there is not enough input to
		// safely decode any possible LZMA symbol or (2) if the
		// dictionary is full, which may need special checks that
		// are only done in the Resumable mode.
		if (unlikely(!rc_is_fast_allowed()
				|| dict.pos == dict.limit))
			goto slow;

		// 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. //
			/////////////////////

			// Update the RC that we have decoded a 0.
			rc_update_0(coder->is_match[state][pos_state]);

			// Get the correct probability array from lp and
			// lc params.
			probs = literal_subcoder(coder->literal,
					literal_context_bits, literal_mask,
					dict.pos, dict_get0(&dict));

			if (is_literal_state(state)) {
				update_literal_normal(state);

				// Decode literal without match byte.
				rc_bittree8(probs, 0);
			} else {
				update_literal_matched(state);

				// Decode literal with match byte.
				rc_matched_literal(probs,
						dict_get(&dict, rep0));
			}

			// Write decoded literal to dictionary
			dict_put(&dict, symbol);
			continue;
		}

		///////////////////
		// 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]);

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

			// The latest three match distances are kept in
			// memory in case there are repeated matches.
			rep3 = rep2;
			rep2 = rep1;
			rep1 = rep0;

			// Decode the length of the match.
			len_decode_fast(len, coder->match_len_decoder,
					pos_state);

			// Next, decode the distance into rep0.

			// The next 6 bits determine how to decode the
			// rest of the distance.
			probs = coder->dist_slot[get_dist_state(len)];

			rc_bittree6(probs, -DIST_SLOTS);
			assert(symbol <= 63);

			if (symbol < DIST_MODEL_START) {
				// 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 {
				// 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) {
					// 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);

					// -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 = 1;

					// Variable number (1-5) of bits
					// from a reverse bittree. This
					// isn't worth manual unrolling.
					//
					// NOTE: Making one or many of the
					// variables (probs, symbol, offset,
					// or limit) local here (instead of
					// using those declared outside the
					// main loop) can affect code size
					// and performance which isn't a
					// surprise but it's not so clear
					// what is the best.
					do {
						rc_bit_add_if_1(probs,
								rep0, offset);
						offset <<= 1;
					} while (--limit > 0);
				} else {
					// The distance is >= 128. Decode the
					// lower bits without probabilities
					// except the lowest four bits.
					assert(symbol >= 14);
					assert(limit >= 6);

					limit -= ALIGN_BITS;
					assert(limit >= 2);

					rc_direct(rep0, limit);

					// Decode the lowest four bits using
					// probabilities.
					rep0 <<= ALIGN_BITS;
					rc_bittree_rev4(coder->pos_align);
					rep0 += symbol;

					// If the end of payload marker (EOPM)
					// is detected, jump to the safe code.
					// The EOPM handling isn't speed
					// critical at all.
					//
					// A final normalization is needed
					// after the EOPM (there can be a
					// dummy byte to read in some cases).
					// If the normalization was done here
					// in the fast code, it would need to
					// be taken into account in the value
					// of LZMA_IN_REQUIRED. Using the
					// safe code allows keeping
					// LZMA_IN_REQUIRED as 20 instead of
					// 21.
					if (rep0 == UINT32_MAX)
						goto eopm;
				}
			}

			// Validate the distance we just decoded.
			if (unlikely(!dict_is_distance_valid(&dict, rep0))) {
				ret = LZMA_DATA_ERROR;
				goto out;
			}

		} else {
			rc_update_1(coder->is_rep[state]);

			/////////////////////
			// 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.
			//
			// There cannot be a match if we haven't produced
			// any output, so check that first.
			if (unlikely(!dict_is_distance_valid(&dict, 0))) {
				ret = LZMA_DATA_ERROR;
				goto out;
			}

			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_mask,
					dict.pos, dict_get0(&dict));
			symbol = 1;

			if (is_literal_state(state)) {
				update_literal_normal(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 {
				update_literal_matched(state);

				// 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));
			}

	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:
					rc_direct_safe(rep0, limit,
							SEQ_DIRECT);

					rep0 <<= ALIGN_BITS;
					symbol = 0;
					offset = 1;
	case SEQ_ALIGN:
					do {
						rc_bit_last_safe(
							coder->pos_align[
								offset
								+ symbol],
							,
							symbol += offset,
							SEQ_ALIGN);
						offset <<= 1;
					} while (offset < ALIGN_SIZE);

					rep0 += symbol;

					if (rep0 == UINT32_MAX) {
						// End of payload marker was
						// found. It may only be
						// present if
						//   - uncompressed size is
						//     unknown or
						//   - after known uncompressed
						//     size amount of bytes has
						//     been decompressed and
						//     caller has indicated
						//     that EOPM might be used
						//     (it's not allowed in
						//     LZMA2).
#ifndef HAVE_SMALL
eopm:
#endif
						if (!eopm_is_valid) {
							ret = LZMA_DATA_ERROR;
							goto out;
						}

	case SEQ_EOPM:
						// LZMA1 stream with
						// end-of-payload marker.
						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_safe(coder->is_rep0_long
						[state][pos_state],
						SEQ_IS_REP0_LONG) {
					rc_update_0(coder->is_rep0_long[
							state][pos_state]);

					update_short_rep(state);

	case SEQ_SHORTREP:
					if (dict_put_safe(&dict,
							dict_get(&dict,
							rep0))) {
						coder->sequence = SEQ_SHORTREP;
						goto out;
					}

					continue;
				}

				rc_update_1(coder->is_rep0_long[
						state][pos_state]);

			} else {
				rc_update_1(coder->is_rep0[state]);

	case 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;
					rep1 = rep0;
					rep0 = distance;

				} else {
					rc_update_1(coder->is_rep1[state]);
	case SEQ_IS_REP2:
					rc_if_0_safe(coder->is_rep2[state],
							SEQ_IS_REP2) {
						rc_update_0(coder->is_rep2[
								state]);

						const uint32_t distance = rep2;
						rep2 = rep1;
						rep1 = rep0;
						rep0 = distance;

					} else {
						rc_update_1(coder->is_rep2[
								state]);

						const uint32_t distance = rep3;
						rep3 = rep2;
						rep2 = rep1;
						rep1 = rep0;
						rep0 = distance;
					}
				}
			}

			update_long_rep(state);

			len_decode(len, coder->rep_len_decoder,
					pos_state, SEQ_REP_LEN);
		}

		/////////////////////////////////
		// Repeat from history buffer. //
		/////////////////////////////////

		assert(len >= MATCH_LEN_MIN);
		assert(len <= MATCH_LEN_MAX);

	case SEQ_COPY:
		if (unlikely(dict_repeat(&dict, rep0, &len))) {
			coder->sequence = SEQ_COPY;
			goto out;
		}
	}

out:
	// Save state

	// NOTE: Must not copy dict.limit.
	dictptr->pos = dict.pos;
	dictptr->full = dict.full;

	rc_from_local(coder->rc, *in_pos);

	coder->state = state;
	coder->rep0 = rep0;
	coder->rep1 = rep1;
	coder->rep2 = rep2;
	coder->rep3 = rep3;

	coder->probs = probs;
	coder->symbol = symbol;
	coder->limit = limit;
	coder->offset = offset;
	coder->len = len;

	// Update the remaining amount of uncompressed data if uncompressed
	// size was known.
	if (coder->uncompressed_size != LZMA_VLI_UNKNOWN) {
		coder->uncompressed_size -= dict.pos - dict_start;

		// If we have gotten all the output but the decoder wants
		// to write more output, the file is corrupt. There are
		// three SEQ values where output is produced.
		if (coder->uncompressed_size == 0 && ret == LZMA_OK
				&& (coder->sequence == SEQ_LITERAL_WRITE
					|| coder->sequence == SEQ_SHORTREP
					|| coder->sequence == SEQ_COPY))
			ret = LZMA_DATA_ERROR;
	}

	if (ret == LZMA_STREAM_END) {
		// Reset the range decoder so that it is ready to reinitialize
		// for a new LZMA2 chunk.
		rc_reset(coder->rc);
		coder->sequence = SEQ_IS_MATCH;
	}

	return ret;
}


static void
lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size,
		bool allow_eopm)
{
	lzma_lzma1_decoder *coder = coder_ptr;
	coder->uncompressed_size = uncompressed_size;
	coder->allow_eopm = allow_eopm;
}


static void
lzma_decoder_reset(void *coder_ptr, const void *opt)
{
	lzma_lzma1_decoder *coder = coder_ptr;
	const lzma_options_lzma *options = opt;

	// NOTE: We assume that lc/lp/pb are valid since they were
	// successfully decoded with lzma_lzma_decode_properties().

	// Calculate pos_mask. We don't need pos_bits as is for anything.
	coder->pos_mask = (1U << options->pb) - 1;

	// Initialize the literal decoder.
	literal_init(coder->literal, options->lc, options->lp);

	coder->literal_context_bits = options->lc;
	coder->literal_mask = literal_mask_calc(options->lc, options->lp);

	// State
	coder->state = STATE_LIT_LIT;
	coder->rep0 = 0;
	coder->rep1 = 0;
	coder->rep2 = 0;
	coder->rep3 = 0;
	coder->pos_mask = (1U << options->pb) - 1;

	// Range decoder
	rc_reset(coder->rc);

	// Bit and bittree decoders
	for (uint32_t i = 0; i < STATES; ++i) {
		for (uint32_t j = 0; j <= coder->pos_mask; ++j) {
			bit_reset(coder->is_match[i][j]);
			bit_reset(coder->is_rep0_long[i][j]);
		}

		bit_reset(coder->is_rep[i]);
		bit_reset(coder->is_rep0[i]);
		bit_reset(coder->is_rep1[i]);
		bit_reset(coder->is_rep2[i]);
	}

	for (uint32_t i = 0; i < DIST_STATES; ++i)
		bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);

	for (uint32_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
		bit_reset(coder->pos_special[i]);

	bittree_reset(coder->pos_align, ALIGN_BITS);

	// Len decoders (also bit/bittree)
	const uint32_t num_pos_states = 1U << options->pb;
	bit_reset(coder->match_len_decoder.choice);
	bit_reset(coder->match_len_decoder.choice2);
	bit_reset(coder->rep_len_decoder.choice);
	bit_reset(coder->rep_len_decoder.choice2);

	for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
		bittree_reset(coder->match_len_decoder.low[pos_state],
				LEN_LOW_BITS);
		bittree_reset(coder->match_len_decoder.mid[pos_state],
				LEN_MID_BITS);

		bittree_reset(coder->rep_len_decoder.low[pos_state],
				LEN_LOW_BITS);
		bittree_reset(coder->rep_len_decoder.mid[pos_state],
				LEN_MID_BITS);
	}

	bittree_reset(coder->match_len_decoder.high, LEN_HIGH_BITS);
	bittree_reset(coder->rep_len_decoder.high, LEN_HIGH_BITS);

	coder->sequence = SEQ_IS_MATCH;
	coder->probs = NULL;
	coder->symbol = 0;
	coder->limit = 0;
	coder->offset = 0;
	coder->len = 0;

	return;
}


extern lzma_ret
lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator,
		const lzma_options_lzma *options, lzma_lz_options *lz_options)
{
	if (lz->coder == NULL) {
		lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator);
		if (lz->coder == NULL)
			return LZMA_MEM_ERROR;

		lz->code = &lzma_decode;
		lz->reset = &lzma_decoder_reset;
		lz->set_uncompressed = &lzma_decoder_uncompressed;
	}

	// All dictionary sizes are OK here. LZ decoder will take care of
	// the special cases.
	lz_options->dict_size = options->dict_size;
	lz_options->preset_dict = options->preset_dict;
	lz_options->preset_dict_size = options->preset_dict_size;

	return LZMA_OK;
}


/// Allocate and initialize LZMA decoder. This is used only via LZ
/// initialization (lzma_lzma_decoder_init() passes function pointer to
/// the LZ initialization).
static lzma_ret
lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
		lzma_vli id, const void *options, lzma_lz_options *lz_options)
{
	if (!is_lclppb_valid(options))
		return LZMA_PROG_ERROR;

	lzma_vli uncomp_size = LZMA_VLI_UNKNOWN;
	bool allow_eopm = true;

	if (id == LZMA_FILTER_LZMA1EXT) {
		const lzma_options_lzma *opt = options;

		// Only one flag is supported.
		if (opt->ext_flags & ~LZMA_LZMA1EXT_ALLOW_EOPM)
			return LZMA_OPTIONS_ERROR;

		// FIXME? Using lzma_vli instead of uint64_t is weird because
		// this has nothing to do with .xz headers and variable-length
		// integer encoding. On the other hand, using LZMA_VLI_UNKNOWN
		// instead of UINT64_MAX is clearer when unknown size is
		// meant. A problem with using lzma_vli is that now we
		// allow > LZMA_VLI_MAX which is fine in this file but
		// it's still confusing. Note that alone_decoder.c also
		// allows > LZMA_VLI_MAX when setting uncompressed size.
		uncomp_size = opt->ext_size_low
				+ ((uint64_t)(opt->ext_size_high) << 32);
		allow_eopm = (opt->ext_flags & LZMA_LZMA1EXT_ALLOW_EOPM) != 0
				|| uncomp_size == LZMA_VLI_UNKNOWN;
	}

	return_if_error(lzma_lzma_decoder_create(
			lz, allocator, options, lz_options));

	lzma_decoder_reset(lz->coder, options);
	lzma_decoder_uncompressed(lz->coder, uncomp_size, allow_eopm);

	return LZMA_OK;
}


extern lzma_ret
lzma_lzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
		const lzma_filter_info *filters)
{
	// LZMA can only be the last filter in the chain. This is enforced
	// by the raw_decoder initialization.
	assert(filters[1].init == NULL);

	return lzma_lz_decoder_init(next, allocator, filters,
			&lzma_decoder_init);
}


extern bool
lzma_lzma_lclppb_decode(lzma_options_lzma *options, uint8_t byte)
{
	if (byte > (4 * 5 + 4) * 9 + 8)
		return true;

	// See the file format specification to understand this.
	options->pb = byte / (9 * 5);
	byte -= options->pb * 9 * 5;
	options->lp = byte / 9;
	options->lc = byte - options->lp * 9;

	return options->lc + options->lp > LZMA_LCLP_MAX;
}


extern uint64_t
lzma_lzma_decoder_memusage_nocheck(const void *options)
{
	const lzma_options_lzma *const opt = options;
	return sizeof(lzma_lzma1_decoder)
			+ lzma_lz_decoder_memusage(opt->dict_size);
}


extern uint64_t
lzma_lzma_decoder_memusage(const void *options)
{
	if (!is_lclppb_valid(options))
		return UINT64_MAX;

	return lzma_lzma_decoder_memusage_nocheck(options);
}


extern lzma_ret
lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
		const uint8_t *props, size_t props_size)
{
	if (props_size != 5)
		return LZMA_OPTIONS_ERROR;

	lzma_options_lzma *opt
			= lzma_alloc(sizeof(lzma_options_lzma), allocator);
	if (opt == NULL)
		return LZMA_MEM_ERROR;

	if (lzma_lzma_lclppb_decode(opt, props[0]))
		goto error;

	// All dictionary sizes are accepted, including zero. LZ decoder
	// will automatically use a dictionary at least a few KiB even if
	// a smaller dictionary is requested.
	opt->dict_size = read32le(props + 1);

	opt->preset_dict = NULL;
	opt->preset_dict_size = 0;

	*options = opt;

	return LZMA_OK;

error:
	lzma_free(opt, allocator);
	return LZMA_OPTIONS_ERROR;
}