cregit-Linux how code gets into the kernel

Release 4.12 lib/xz/xz_dec_lzma2.c

Directory: lib/xz
/*
 * LZMA2 decoder
 *
 * Authors: Lasse Collin <lasse.collin@tukaani.org>
 *          Igor Pavlov <http://7-zip.org/>
 *
 * This file has been put into the public domain.
 * You can do whatever you want with this file.
 */

#include "xz_private.h"
#include "xz_lzma2.h"

/*
 * Range decoder initialization eats the first five bytes of each LZMA chunk.
 */

#define RC_INIT_BYTES 5

/*
 * Minimum number of usable input buffer 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 of 20 bytes of input. However,
 * lzma_main() does an extra normalization before returning, thus we
 * need to put 21 here.
 */

#define LZMA_IN_REQUIRED 21

/*
 * Dictionary (history buffer)
 *
 * These are always true:
 *    start <= pos <= full <= end
 *    pos <= limit <= end
 *
 * In multi-call mode, also these are true:
 *    end == size
 *    size <= size_max
 *    allocated <= size
 *
 * Most of these variables are size_t to support single-call mode,
 * in which the dictionary variables address the actual output
 * buffer directly.
 */

struct dictionary {
	/* Beginning of the history buffer */
	
uint8_t *buf;

	/* Old position in buf (before decoding more data) */
	
size_t start;

	/* Position in buf */
	
size_t pos;

	/*
         * How full dictionary is. This is used to detect corrupt input that
         * would read beyond the beginning of the uncompressed stream.
         */
	
size_t full;

	/* Write limit; we don't write to buf[limit] or later bytes. */
	
size_t limit;

	/*
         * End of the dictionary buffer. In multi-call mode, this is
         * the same as the dictionary size. In single-call mode, this
         * indicates the size of the output buffer.
         */
	
size_t end;

	/*
         * Size of the dictionary as specified in Block Header. This is used
         * together with "full" to detect corrupt input that would make us
         * read beyond the beginning of the uncompressed stream.
         */
	
uint32_t size;

	/*
         * Maximum allowed dictionary size in multi-call mode.
         * This is ignored in single-call mode.
         */
	
uint32_t size_max;

	/*
         * Amount of memory currently allocated for the dictionary.
         * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
         * size_max is always the same as the allocated size.)
         */
	
uint32_t allocated;

	/* Operation mode */
	
enum xz_mode mode;
};

/* Range decoder */

struct rc_dec {
	
uint32_t range;
	
uint32_t code;

	/*
         * Number of initializing bytes remaining to be read
         * by rc_read_init().
         */
	
uint32_t init_bytes_left;

	/*
         * Buffer from which we read our input. It can be either
         * temp.buf or the caller-provided input buffer.
         */
	
const uint8_t *in;
	
size_t in_pos;
	
size_t in_limit;
};

/* Probabilities for a length decoder. */

struct lzma_len_dec {
	/* Probability of match length being at least 10 */
	
uint16_t choice;

	/* Probability of match length being at least 18 */
	
uint16_t choice2;

	/* Probabilities for match lengths 2-9 */
	
uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS];

	/* Probabilities for match lengths 10-17 */
	
uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS];

	/* Probabilities for match lengths 18-273 */
	
uint16_t high[LEN_HIGH_SYMBOLS];
};


struct lzma_dec {
	/* Distances of latest four matches */
	
uint32_t rep0;
	
uint32_t rep1;
	
uint32_t rep2;
	
uint32_t rep3;

	/* Types of the most recently seen LZMA symbols */
	
enum lzma_state state;

	/*
         * Length of a match. This is updated so that dict_repeat can
         * be called again to finish repeating the whole match.
         */
	
uint32_t len;

	/*
         * LZMA properties or related bit masks (number of literal
         * context bits, a mask dervied from the number of literal
         * position bits, and a mask dervied from the number
         * position bits)
         */
	
uint32_t lc;
	
uint32_t literal_pos_mask; /* (1 << lp) - 1 */
	
uint32_t pos_mask;         /* (1 << pb) - 1 */

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

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

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

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

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

	/*
         * If 1, the repeated match has length of one byte. Otherwise
         * the length is decoded from rep_len_decoder.
         */
	
uint16_t 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].
         */
	
uint16_t dist_slot[DIST_STATES][DIST_SLOTS];

	/*
         * Probility trees for additional bits for match distance
         * when the distance is in the range [4, 127].
         */
	
uint16_t dist_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.
         */
	
uint16_t dist_align[ALIGN_SIZE];

	/* Length of a normal match */
	
struct lzma_len_dec match_len_dec;

	/* Length of a repeated match */
	
struct lzma_len_dec rep_len_dec;

	/* Probabilities of literals */
	
uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
};


struct lzma2_dec {
	/* Position in xz_dec_lzma2_run(). */
	
enum lzma2_seq {
		
SEQ_CONTROL,
		
SEQ_UNCOMPRESSED_1,
		
SEQ_UNCOMPRESSED_2,
		
SEQ_COMPRESSED_0,
		
SEQ_COMPRESSED_1,
		
SEQ_PROPERTIES,
		
SEQ_LZMA_PREPARE,
		
SEQ_LZMA_RUN,
		
SEQ_COPY
	
} sequence;

	/* Next position after decoding the compressed size of the chunk. */
	
enum lzma2_seq next_sequence;

	/* Uncompressed size of LZMA chunk (2 MiB at maximum) */
	
uint32_t uncompressed;

	/*
         * Compressed size of LZMA chunk or compressed/uncompressed
         * size of uncompressed chunk (64 KiB at maximum)
         */
	
uint32_t compressed;

	/*
         * True if dictionary reset is needed. This is false before
         * the first chunk (LZMA or uncompressed).
         */
	
bool need_dict_reset;

	/*
         * True if new LZMA properties are needed. This is false
         * before the first LZMA chunk.
         */
	
bool need_props;
};


struct xz_dec_lzma2 {
	/*
         * The order below is important on x86 to reduce code size and
         * it shouldn't hurt on other platforms. Everything up to and
         * including lzma.pos_mask are in the first 128 bytes on x86-32,
         * which allows using smaller instructions to access those
         * variables. On x86-64, fewer variables fit into the first 128
         * bytes, but this is still the best order without sacrificing
         * the readability by splitting the structures.
         */
	
struct rc_dec rc;
	
struct dictionary dict;
	
struct lzma2_dec lzma2;
	
struct lzma_dec lzma;

	/*
         * Temporary buffer which holds small number of input bytes between
         * decoder calls. See lzma2_lzma() for details.
         */
	struct {
		
uint32_t size;
		
uint8_t buf[3 * LZMA_IN_REQUIRED];
	
} temp;
};

/**************
 * Dictionary *
 **************/

/*
 * Reset the dictionary state. When in single-call mode, set up the beginning
 * of the dictionary to point to the actual output buffer.
 */

static void dict_reset(struct dictionary *dict, struct xz_buf *b) { if (DEC_IS_SINGLE(dict->mode)) { dict->buf = b->out + b->out_pos; dict->end = b->out_size - b->out_pos; } dict->start = 0; dict->pos = 0; dict->limit = 0; dict->full = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin75100.00%1100.00%
Total75100.00%1100.00%

/* Set dictionary write limit */
static void dict_limit(struct dictionary *dict, size_t out_max) { if (dict->end - dict->pos <= out_max) dict->limit = dict->end; else dict->limit = dict->pos + out_max; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin45100.00%1100.00%
Total45100.00%1100.00%

/* Return true if at least one byte can be written into the dictionary. */
static inline bool dict_has_space(const struct dictionary *dict) { return dict->pos < dict->limit; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin22100.00%1100.00%
Total22100.00%1100.00%

/* * Get a byte from the dictionary at the given distance. The distance is * assumed to valid, or as a special case, zero when the dictionary is * still empty. This special case is needed for single-call decoding to * avoid writing a '\0' to the end of the destination buffer. */
static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) { size_t offset = dict->pos - dist - 1; if (dist >= dict->pos) offset += dict->end; return dict->full > 0 ? dict->buf[offset] : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin57100.00%1100.00%
Total57100.00%1100.00%

/* * Put one byte into the dictionary. It is assumed that there is space for it. */
static inline void dict_put(struct dictionary *dict, uint8_t byte) { dict->buf[dict->pos++] = byte; if (dict->full < dict->pos) dict->full = dict->pos; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin45100.00%1100.00%
Total45100.00%1100.00%

/* * Repeat given number of bytes from the given distance. If the distance is * invalid, false is returned. On success, true is returned and *len is * updated to indicate how many bytes were left to be repeated. */
static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist) { size_t back; uint32_t left; if (dist >= dict->full || dist >= dict->size) return false; left = min_t(size_t, dict->limit - dict->pos, *len); *len -= left; back = dict->pos - dist - 1; if (dist >= dict->pos) back += dict->end; do { dict->buf[dict->pos++] = dict->buf[back++]; if (back == dict->end) back = 0; } while (--left > 0); if (dict->full < dict->pos) dict->full = dict->pos; return true; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin150100.00%1100.00%
Total150100.00%1100.00%

/* Copy uncompressed data as is from input to dictionary and output buffers. */
static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, uint32_t *left) { size_t copy_size; while (*left > 0 && b->in_pos < b->in_size && b->out_pos < b->out_size) { copy_size = min(b->in_size - b->in_pos, b->out_size - b->out_pos); if (copy_size > dict->end - dict->pos) copy_size = dict->end - dict->pos; if (copy_size > *left) copy_size = *left; *left -= copy_size; memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); dict->pos += copy_size; if (dict->full < dict->pos) dict->full = dict->pos; if (DEC_IS_MULTI(dict->mode)) { if (dict->pos == dict->end) dict->pos = 0; memcpy(b->out + b->out_pos, b->in + b->in_pos, copy_size); } dict->start = dict->pos; b->out_pos += copy_size; b->in_pos += copy_size; } }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin221100.00%1100.00%
Total221100.00%1100.00%

/* * Flush pending data from dictionary to b->out. It is assumed that there is * enough space in b->out. This is guaranteed because caller uses dict_limit() * before decoding data into the dictionary. */
static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) { size_t copy_size = dict->pos - dict->start; if (DEC_IS_MULTI(dict->mode)) { if (dict->pos == dict->end) dict->pos = 0; memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size); } dict->start = dict->pos; b->out_pos += copy_size; return copy_size; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin92100.00%1100.00%
Total92100.00%1100.00%

/***************** * Range decoder * *****************/ /* Reset the range decoder. */
static void rc_reset(struct rc_dec *rc) { rc->range = (uint32_t)-1; rc->code = 0; rc->init_bytes_left = RC_INIT_BYTES; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin33100.00%1100.00%
Total33100.00%1100.00%

/* * Read the first five initial bytes into rc->code if they haven't been * read already. (Yes, the first byte gets completely ignored.) */
static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) { while (rc->init_bytes_left > 0) { if (b->in_pos == b->in_size) return false; rc->code = (rc->code << 8) + b->in[b->in_pos++]; --rc->init_bytes_left; } return true; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin69100.00%1100.00%
Total69100.00%1100.00%

/* Return true if there may not be enough input for the next decoding loop. */
static inline bool rc_limit_exceeded(const struct rc_dec *rc) { return rc->in_pos > rc->in_limit; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin22100.00%1100.00%
Total22100.00%1100.00%

/* * Return true if it is possible (from point of view of range decoder) that * we have reached the end of the LZMA chunk. */
static inline bool rc_is_finished(const struct rc_dec *rc) { return rc->code == 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin20100.00%1100.00%
Total20100.00%1100.00%

/* Read the next input byte if needed. */
static __always_inline void rc_normalize(struct rc_dec *rc) { if (rc->range < RC_TOP_VALUE) { rc->range <<= RC_SHIFT_BITS; rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; } }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin50100.00%1100.00%
Total50100.00%1100.00%

/* * Decode one bit. In some versions, this function has been splitted in three * functions so that the compiler is supposed to be able to more easily avoid * an extra branch. In this particular version of the LZMA decoder, this * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 * on x86). Using a non-splitted version results in nicer looking code too. * * NOTE: This must return an int. Do not make it return a bool or the speed * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) */
static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) { uint32_t bound; int bit; rc_normalize(rc); bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; if (rc->code < bound) { rc->range = bound; *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; bit = 0; } else { rc->range -= bound; rc->code -= bound; *prob -= *prob >> RC_MOVE_BITS; bit = 1; } return bit; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin102100.00%1100.00%
Total102100.00%1100.00%

/* Decode a bittree starting from the most significant bit. */
static __always_inline uint32_t rc_bittree(struct rc_dec *rc, uint16_t *probs, uint32_t limit) { uint32_t symbol = 1; do { if (rc_bit(rc, &probs[symbol])) symbol = (symbol << 1) + 1; else symbol <<= 1; } while (symbol < limit); return symbol; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin65100.00%1100.00%
Total65100.00%1100.00%

/* Decode a bittree starting from the least significant bit. */
static __always_inline void rc_bittree_reverse(struct rc_dec *rc, uint16_t *probs, uint32_t *dest, uint32_t limit) { uint32_t symbol = 1; uint32_t i = 0; do { if (rc_bit(rc, &probs[symbol])) { symbol = (symbol << 1) + 1; *dest += 1 << i; } else { symbol <<= 1; } } while (++i < limit); }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin83100.00%1100.00%
Total83100.00%1100.00%

/* Decode direct bits (fixed fifty-fifty probability) */
static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) { uint32_t mask; do { rc_normalize(rc); rc->range >>= 1; rc->code -= rc->range; mask = (uint32_t)0 - (rc->code >> 31); rc->code += rc->range & mask; *dest = (*dest << 1) + (mask + 1); } while (--limit > 0); }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin93100.00%1100.00%
Total93100.00%1100.00%

/******** * LZMA * ********/ /* Get pointer to literal coder probability array. */
static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s) { uint32_t prev_byte = dict_get(&s->dict, 0); uint32_t low = prev_byte >> (8 - s->lzma.lc); uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; return s->lzma.literal[low + high]; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin75100.00%1100.00%
Total75100.00%1100.00%

/* Decode a literal (one 8-bit byte) */
static void lzma_literal(struct xz_dec_lzma2 *s) { uint16_t *probs; uint32_t symbol; uint32_t match_byte; uint32_t match_bit; uint32_t offset; uint32_t i; probs = lzma_literal_probs(s); if (lzma_state_is_literal(s->lzma.state)) { symbol = rc_bittree(&s->rc, probs, 0x100); } else { symbol = 1; match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; offset = 0x100; do { match_bit = match_byte & offset; match_byte <<= 1; i = offset + match_bit + symbol; if (rc_bit(&s->rc, &probs[i])) { symbol = (symbol << 1) + 1; offset &= match_bit; } else { symbol <<= 1; offset &= ~match_bit; } } while (symbol < 0x100); } dict_put(&s->dict, (uint8_t)symbol); lzma_state_literal(&s->lzma.state); }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin188100.00%1100.00%
Total188100.00%1100.00%

/* Decode the length of the match into s->lzma.len. */
static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, uint32_t pos_state) { uint16_t *probs; uint32_t limit; if (!rc_bit(&s->rc, &l->choice)) { probs = l->low[pos_state]; limit = LEN_LOW_SYMBOLS; s->lzma.len = MATCH_LEN_MIN; } else { if (!rc_bit(&s->rc, &l->choice2)) { probs = l->mid[pos_state]; limit = LEN_MID_SYMBOLS; s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; } else { probs = l->high; limit = LEN_HIGH_SYMBOLS; s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; } } s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin154100.00%1100.00%
Total154100.00%1100.00%

/* Decode a match. The distance will be stored in s->lzma.rep0. */
static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { uint16_t *probs; uint32_t dist_slot; uint32_t limit; lzma_state_match(&s->lzma.state); s->lzma.rep3 = s->lzma.rep2; s->lzma.rep2 = s->lzma.rep1; s->lzma.rep1 = s->lzma.rep0; lzma_len(s, &s->lzma.match_len_dec, pos_state); probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; if (dist_slot < DIST_MODEL_START) { s->lzma.rep0 = dist_slot; } else { limit = (dist_slot >> 1) - 1; s->lzma.rep0 = 2 + (dist_slot & 1); if (dist_slot < DIST_MODEL_END) { s->lzma.rep0 <<= limit; probs = s->lzma.dist_special + s->lzma.rep0 - dist_slot - 1; rc_bittree_reverse(&s->rc, probs, &s->lzma.rep0, limit); } else { rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); s->lzma.rep0 <<= ALIGN_BITS; rc_bittree_reverse(&s->rc, s->lzma.dist_align, &s->lzma.rep0, ALIGN_BITS); } } }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin267100.00%1100.00%
Total267100.00%1100.00%

/* * Decode a repeated match. The distance is one of the four most recently * seen matches. The distance will be stored in s->lzma.rep0. */
static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { uint32_t tmp; if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ s->lzma.state][pos_state])) { lzma_state_short_rep(&s->lzma.state); s->lzma.len = 1; return; } } else { if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { tmp = s->lzma.rep1; } else { if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { tmp = s->lzma.rep2; } else { tmp = s->lzma.rep3; s->lzma.rep3 = s->lzma.rep2; } s->lzma.rep2 = s->lzma.rep1; } s->lzma.rep1 = s->lzma.rep0; s->lzma.rep0 = tmp; } lzma_state_long_rep(&s->lzma.state); lzma_len(s, &s->lzma.rep_len_dec, pos_state); }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin248100.00%1100.00%
Total248100.00%1100.00%

/* LZMA decoder core */
static bool lzma_main(struct xz_dec_lzma2 *s) { uint32_t pos_state; /* * If the dictionary was reached during the previous call, try to * finish the possibly pending repeat in the dictionary. */ if (dict_has_space(&s->dict) && s->lzma.len > 0) dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); /* * Decode more LZMA symbols. One iteration may consume up to * LZMA_IN_REQUIRED - 1 bytes. */ while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { pos_state = s->dict.pos & s->lzma.pos_mask; if (!rc_bit(&s->rc, &s->lzma.is_match[ s->lzma.state][pos_state])) { lzma_literal(s); } else { if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) lzma_rep_match(s, pos_state); else lzma_match(s, pos_state); if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) return false; } } /* * Having the range decoder always normalized when we are outside * this function makes it easier to correctly handle end of the chunk. */ rc_normalize(&s->rc); return true; }

Contributors

PersonTokensPropCommitsCommitProp
Lasse Collin206100.00%1100.00%
Total206100.00%1100.00%

/* * Reset the LZMA decoder and range decoder state. Dictionary is nore reset * here, because LZMA state may be reset without resetting the dictionary. */
static void lzma_reset(struct xz_dec_lzma2 *s) { uint16_t *probs; size_t i; s->lzma.state = STATE_LIT_LIT; s->lzma.rep0 = 0; s->lzma.rep1 = 0; s->lzma.rep2 = 0; s->lzma.rep3 = 0; /* * All probabilities are initialized to the same value. This hack * makes the code smaller by avoiding a separate loop for each * probability array. * * This could be optimized so that only that part of