163dab8eeSAdrian Chadd /*
263dab8eeSAdrian Chadd * .xz Stream decoder
363dab8eeSAdrian Chadd *
463dab8eeSAdrian Chadd * Author: Lasse Collin <lasse.collin@tukaani.org>
563dab8eeSAdrian Chadd *
663dab8eeSAdrian Chadd * This file has been put into the public domain.
763dab8eeSAdrian Chadd * You can do whatever you want with this file.
863dab8eeSAdrian Chadd */
963dab8eeSAdrian Chadd
1063dab8eeSAdrian Chadd #include "xz_private.h"
1163dab8eeSAdrian Chadd #include "xz_stream.h"
1263dab8eeSAdrian Chadd
13f0bd5302SXin LI #ifdef XZ_USE_CRC64
14f0bd5302SXin LI # define IS_CRC64(check_type) ((check_type) == XZ_CHECK_CRC64)
15f0bd5302SXin LI #else
16f0bd5302SXin LI # define IS_CRC64(check_type) false
17f0bd5302SXin LI #endif
18f0bd5302SXin LI
1963dab8eeSAdrian Chadd /* Hash used to validate the Index field */
2063dab8eeSAdrian Chadd struct xz_dec_hash {
2163dab8eeSAdrian Chadd vli_type unpadded;
2263dab8eeSAdrian Chadd vli_type uncompressed;
2363dab8eeSAdrian Chadd uint32_t crc32;
2463dab8eeSAdrian Chadd };
2563dab8eeSAdrian Chadd
2663dab8eeSAdrian Chadd struct xz_dec {
2763dab8eeSAdrian Chadd /* Position in dec_main() */
2863dab8eeSAdrian Chadd enum {
2963dab8eeSAdrian Chadd SEQ_STREAM_HEADER,
3063dab8eeSAdrian Chadd SEQ_BLOCK_START,
3163dab8eeSAdrian Chadd SEQ_BLOCK_HEADER,
3263dab8eeSAdrian Chadd SEQ_BLOCK_UNCOMPRESS,
3363dab8eeSAdrian Chadd SEQ_BLOCK_PADDING,
3463dab8eeSAdrian Chadd SEQ_BLOCK_CHECK,
3563dab8eeSAdrian Chadd SEQ_INDEX,
3663dab8eeSAdrian Chadd SEQ_INDEX_PADDING,
3763dab8eeSAdrian Chadd SEQ_INDEX_CRC32,
38*cd3a777bSXin LI SEQ_STREAM_FOOTER,
39*cd3a777bSXin LI SEQ_STREAM_PADDING
4063dab8eeSAdrian Chadd } sequence;
4163dab8eeSAdrian Chadd
4263dab8eeSAdrian Chadd /* Position in variable-length integers and Check fields */
4363dab8eeSAdrian Chadd uint32_t pos;
4463dab8eeSAdrian Chadd
4563dab8eeSAdrian Chadd /* Variable-length integer decoded by dec_vli() */
4663dab8eeSAdrian Chadd vli_type vli;
4763dab8eeSAdrian Chadd
4863dab8eeSAdrian Chadd /* Saved in_pos and out_pos */
4963dab8eeSAdrian Chadd size_t in_start;
5063dab8eeSAdrian Chadd size_t out_start;
5163dab8eeSAdrian Chadd
52f0bd5302SXin LI #ifdef XZ_USE_CRC64
53f0bd5302SXin LI /* CRC32 or CRC64 value in Block or CRC32 value in Index */
54f0bd5302SXin LI uint64_t crc;
55f0bd5302SXin LI #else
5663dab8eeSAdrian Chadd /* CRC32 value in Block or Index */
57f0bd5302SXin LI uint32_t crc;
58f0bd5302SXin LI #endif
5963dab8eeSAdrian Chadd
6063dab8eeSAdrian Chadd /* Type of the integrity check calculated from uncompressed data */
6163dab8eeSAdrian Chadd enum xz_check check_type;
6263dab8eeSAdrian Chadd
6363dab8eeSAdrian Chadd /* Operation mode */
6463dab8eeSAdrian Chadd enum xz_mode mode;
6563dab8eeSAdrian Chadd
6663dab8eeSAdrian Chadd /*
6763dab8eeSAdrian Chadd * True if the next call to xz_dec_run() is allowed to return
6863dab8eeSAdrian Chadd * XZ_BUF_ERROR.
6963dab8eeSAdrian Chadd */
7063dab8eeSAdrian Chadd bool allow_buf_error;
7163dab8eeSAdrian Chadd
7263dab8eeSAdrian Chadd /* Information stored in Block Header */
7363dab8eeSAdrian Chadd struct {
7463dab8eeSAdrian Chadd /*
7563dab8eeSAdrian Chadd * Value stored in the Compressed Size field, or
7663dab8eeSAdrian Chadd * VLI_UNKNOWN if Compressed Size is not present.
7763dab8eeSAdrian Chadd */
7863dab8eeSAdrian Chadd vli_type compressed;
7963dab8eeSAdrian Chadd
8063dab8eeSAdrian Chadd /*
8163dab8eeSAdrian Chadd * Value stored in the Uncompressed Size field, or
8263dab8eeSAdrian Chadd * VLI_UNKNOWN if Uncompressed Size is not present.
8363dab8eeSAdrian Chadd */
8463dab8eeSAdrian Chadd vli_type uncompressed;
8563dab8eeSAdrian Chadd
8663dab8eeSAdrian Chadd /* Size of the Block Header field */
8763dab8eeSAdrian Chadd uint32_t size;
8863dab8eeSAdrian Chadd } block_header;
8963dab8eeSAdrian Chadd
9063dab8eeSAdrian Chadd /* Information collected when decoding Blocks */
9163dab8eeSAdrian Chadd struct {
9263dab8eeSAdrian Chadd /* Observed compressed size of the current Block */
9363dab8eeSAdrian Chadd vli_type compressed;
9463dab8eeSAdrian Chadd
9563dab8eeSAdrian Chadd /* Observed uncompressed size of the current Block */
9663dab8eeSAdrian Chadd vli_type uncompressed;
9763dab8eeSAdrian Chadd
9863dab8eeSAdrian Chadd /* Number of Blocks decoded so far */
9963dab8eeSAdrian Chadd vli_type count;
10063dab8eeSAdrian Chadd
10163dab8eeSAdrian Chadd /*
10263dab8eeSAdrian Chadd * Hash calculated from the Block sizes. This is used to
10363dab8eeSAdrian Chadd * validate the Index field.
10463dab8eeSAdrian Chadd */
10563dab8eeSAdrian Chadd struct xz_dec_hash hash;
10663dab8eeSAdrian Chadd } block;
10763dab8eeSAdrian Chadd
10863dab8eeSAdrian Chadd /* Variables needed when verifying the Index field */
10963dab8eeSAdrian Chadd struct {
11063dab8eeSAdrian Chadd /* Position in dec_index() */
11163dab8eeSAdrian Chadd enum {
11263dab8eeSAdrian Chadd SEQ_INDEX_COUNT,
11363dab8eeSAdrian Chadd SEQ_INDEX_UNPADDED,
11463dab8eeSAdrian Chadd SEQ_INDEX_UNCOMPRESSED
11563dab8eeSAdrian Chadd } sequence;
11663dab8eeSAdrian Chadd
11763dab8eeSAdrian Chadd /* Size of the Index in bytes */
11863dab8eeSAdrian Chadd vli_type size;
11963dab8eeSAdrian Chadd
12063dab8eeSAdrian Chadd /* Number of Records (matches block.count in valid files) */
12163dab8eeSAdrian Chadd vli_type count;
12263dab8eeSAdrian Chadd
12363dab8eeSAdrian Chadd /*
12463dab8eeSAdrian Chadd * Hash calculated from the Records (matches block.hash in
12563dab8eeSAdrian Chadd * valid files).
12663dab8eeSAdrian Chadd */
12763dab8eeSAdrian Chadd struct xz_dec_hash hash;
12863dab8eeSAdrian Chadd } index;
12963dab8eeSAdrian Chadd
13063dab8eeSAdrian Chadd /*
13163dab8eeSAdrian Chadd * Temporary buffer needed to hold Stream Header, Block Header,
13263dab8eeSAdrian Chadd * and Stream Footer. The Block Header is the biggest (1 KiB)
13363dab8eeSAdrian Chadd * so we reserve space according to that. buf[] has to be aligned
13463dab8eeSAdrian Chadd * to a multiple of four bytes; the size_t variables before it
13563dab8eeSAdrian Chadd * should guarantee this.
13663dab8eeSAdrian Chadd */
13763dab8eeSAdrian Chadd struct {
13863dab8eeSAdrian Chadd size_t pos;
13963dab8eeSAdrian Chadd size_t size;
14063dab8eeSAdrian Chadd uint8_t buf[1024];
14163dab8eeSAdrian Chadd } temp;
14263dab8eeSAdrian Chadd
14363dab8eeSAdrian Chadd struct xz_dec_lzma2 *lzma2;
14463dab8eeSAdrian Chadd
14563dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
14663dab8eeSAdrian Chadd struct xz_dec_bcj *bcj;
14763dab8eeSAdrian Chadd bool bcj_active;
14863dab8eeSAdrian Chadd #endif
14963dab8eeSAdrian Chadd };
15063dab8eeSAdrian Chadd
15163dab8eeSAdrian Chadd #ifdef XZ_DEC_ANY_CHECK
15263dab8eeSAdrian Chadd /* Sizes of the Check field with different Check IDs */
15363dab8eeSAdrian Chadd static const uint8_t check_sizes[16] = {
15463dab8eeSAdrian Chadd 0,
15563dab8eeSAdrian Chadd 4, 4, 4,
15663dab8eeSAdrian Chadd 8, 8, 8,
15763dab8eeSAdrian Chadd 16, 16, 16,
15863dab8eeSAdrian Chadd 32, 32, 32,
15963dab8eeSAdrian Chadd 64, 64, 64
16063dab8eeSAdrian Chadd };
16163dab8eeSAdrian Chadd #endif
16263dab8eeSAdrian Chadd
16363dab8eeSAdrian Chadd /*
16463dab8eeSAdrian Chadd * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
16563dab8eeSAdrian Chadd * must have set s->temp.pos to indicate how much data we are supposed
16663dab8eeSAdrian Chadd * to copy into s->temp.buf. Return true once s->temp.pos has reached
16763dab8eeSAdrian Chadd * s->temp.size.
16863dab8eeSAdrian Chadd */
fill_temp(struct xz_dec * s,struct xz_buf * b)16963dab8eeSAdrian Chadd static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
17063dab8eeSAdrian Chadd {
17163dab8eeSAdrian Chadd size_t copy_size = min_t(size_t,
17263dab8eeSAdrian Chadd b->in_size - b->in_pos, s->temp.size - s->temp.pos);
17363dab8eeSAdrian Chadd
17463dab8eeSAdrian Chadd memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
17563dab8eeSAdrian Chadd b->in_pos += copy_size;
17663dab8eeSAdrian Chadd s->temp.pos += copy_size;
17763dab8eeSAdrian Chadd
17863dab8eeSAdrian Chadd if (s->temp.pos == s->temp.size) {
17963dab8eeSAdrian Chadd s->temp.pos = 0;
18063dab8eeSAdrian Chadd return true;
18163dab8eeSAdrian Chadd }
18263dab8eeSAdrian Chadd
18363dab8eeSAdrian Chadd return false;
18463dab8eeSAdrian Chadd }
18563dab8eeSAdrian Chadd
18663dab8eeSAdrian Chadd /* Decode a variable-length integer (little-endian base-128 encoding) */
dec_vli(struct xz_dec * s,const uint8_t * in,size_t * in_pos,size_t in_size)18763dab8eeSAdrian Chadd static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in,
18863dab8eeSAdrian Chadd size_t *in_pos, size_t in_size)
18963dab8eeSAdrian Chadd {
19063dab8eeSAdrian Chadd uint8_t byte;
19163dab8eeSAdrian Chadd
19263dab8eeSAdrian Chadd if (s->pos == 0)
19363dab8eeSAdrian Chadd s->vli = 0;
19463dab8eeSAdrian Chadd
19563dab8eeSAdrian Chadd while (*in_pos < in_size) {
19663dab8eeSAdrian Chadd byte = in[*in_pos];
19763dab8eeSAdrian Chadd ++*in_pos;
19863dab8eeSAdrian Chadd
19963dab8eeSAdrian Chadd s->vli |= (vli_type)(byte & 0x7F) << s->pos;
20063dab8eeSAdrian Chadd
20163dab8eeSAdrian Chadd if ((byte & 0x80) == 0) {
20263dab8eeSAdrian Chadd /* Don't allow non-minimal encodings. */
20363dab8eeSAdrian Chadd if (byte == 0 && s->pos != 0)
20463dab8eeSAdrian Chadd return XZ_DATA_ERROR;
20563dab8eeSAdrian Chadd
20663dab8eeSAdrian Chadd s->pos = 0;
20763dab8eeSAdrian Chadd return XZ_STREAM_END;
20863dab8eeSAdrian Chadd }
20963dab8eeSAdrian Chadd
21063dab8eeSAdrian Chadd s->pos += 7;
21163dab8eeSAdrian Chadd if (s->pos == 7 * VLI_BYTES_MAX)
21263dab8eeSAdrian Chadd return XZ_DATA_ERROR;
21363dab8eeSAdrian Chadd }
21463dab8eeSAdrian Chadd
21563dab8eeSAdrian Chadd return XZ_OK;
21663dab8eeSAdrian Chadd }
21763dab8eeSAdrian Chadd
21863dab8eeSAdrian Chadd /*
21963dab8eeSAdrian Chadd * Decode the Compressed Data field from a Block. Update and validate
22063dab8eeSAdrian Chadd * the observed compressed and uncompressed sizes of the Block so that
22163dab8eeSAdrian Chadd * they don't exceed the values possibly stored in the Block Header
22263dab8eeSAdrian Chadd * (validation assumes that no integer overflow occurs, since vli_type
223f0bd5302SXin LI * is normally uint64_t). Update the CRC32 or CRC64 value if presence of
224f0bd5302SXin LI * the CRC32 or CRC64 field was indicated in Stream Header.
22563dab8eeSAdrian Chadd *
22663dab8eeSAdrian Chadd * Once the decoding is finished, validate that the observed sizes match
22763dab8eeSAdrian Chadd * the sizes possibly stored in the Block Header. Update the hash and
22863dab8eeSAdrian Chadd * Block count, which are later used to validate the Index field.
22963dab8eeSAdrian Chadd */
dec_block(struct xz_dec * s,struct xz_buf * b)23063dab8eeSAdrian Chadd static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
23163dab8eeSAdrian Chadd {
23263dab8eeSAdrian Chadd enum xz_ret ret;
23363dab8eeSAdrian Chadd
23463dab8eeSAdrian Chadd s->in_start = b->in_pos;
23563dab8eeSAdrian Chadd s->out_start = b->out_pos;
23663dab8eeSAdrian Chadd
23763dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
23863dab8eeSAdrian Chadd if (s->bcj_active)
23963dab8eeSAdrian Chadd ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
24063dab8eeSAdrian Chadd else
24163dab8eeSAdrian Chadd #endif
24263dab8eeSAdrian Chadd ret = xz_dec_lzma2_run(s->lzma2, b);
24363dab8eeSAdrian Chadd
24463dab8eeSAdrian Chadd s->block.compressed += b->in_pos - s->in_start;
24563dab8eeSAdrian Chadd s->block.uncompressed += b->out_pos - s->out_start;
24663dab8eeSAdrian Chadd
24763dab8eeSAdrian Chadd /*
24863dab8eeSAdrian Chadd * There is no need to separately check for VLI_UNKNOWN, since
24963dab8eeSAdrian Chadd * the observed sizes are always smaller than VLI_UNKNOWN.
25063dab8eeSAdrian Chadd */
25163dab8eeSAdrian Chadd if (s->block.compressed > s->block_header.compressed
25263dab8eeSAdrian Chadd || s->block.uncompressed
25363dab8eeSAdrian Chadd > s->block_header.uncompressed)
25463dab8eeSAdrian Chadd return XZ_DATA_ERROR;
25563dab8eeSAdrian Chadd
25663dab8eeSAdrian Chadd if (s->check_type == XZ_CHECK_CRC32)
257f0bd5302SXin LI s->crc = xz_crc32(b->out + s->out_start,
258f0bd5302SXin LI b->out_pos - s->out_start, s->crc);
259f0bd5302SXin LI #ifdef XZ_USE_CRC64
260f0bd5302SXin LI else if (s->check_type == XZ_CHECK_CRC64)
261f0bd5302SXin LI s->crc = xz_crc64(b->out + s->out_start,
262f0bd5302SXin LI b->out_pos - s->out_start, s->crc);
263f0bd5302SXin LI #endif
26463dab8eeSAdrian Chadd
26563dab8eeSAdrian Chadd if (ret == XZ_STREAM_END) {
26663dab8eeSAdrian Chadd if (s->block_header.compressed != VLI_UNKNOWN
26763dab8eeSAdrian Chadd && s->block_header.compressed
26863dab8eeSAdrian Chadd != s->block.compressed)
26963dab8eeSAdrian Chadd return XZ_DATA_ERROR;
27063dab8eeSAdrian Chadd
27163dab8eeSAdrian Chadd if (s->block_header.uncompressed != VLI_UNKNOWN
27263dab8eeSAdrian Chadd && s->block_header.uncompressed
27363dab8eeSAdrian Chadd != s->block.uncompressed)
27463dab8eeSAdrian Chadd return XZ_DATA_ERROR;
27563dab8eeSAdrian Chadd
27663dab8eeSAdrian Chadd s->block.hash.unpadded += s->block_header.size
27763dab8eeSAdrian Chadd + s->block.compressed;
27863dab8eeSAdrian Chadd
27963dab8eeSAdrian Chadd #ifdef XZ_DEC_ANY_CHECK
28063dab8eeSAdrian Chadd s->block.hash.unpadded += check_sizes[s->check_type];
28163dab8eeSAdrian Chadd #else
28263dab8eeSAdrian Chadd if (s->check_type == XZ_CHECK_CRC32)
28363dab8eeSAdrian Chadd s->block.hash.unpadded += 4;
284f0bd5302SXin LI else if (IS_CRC64(s->check_type))
285f0bd5302SXin LI s->block.hash.unpadded += 8;
28663dab8eeSAdrian Chadd #endif
28763dab8eeSAdrian Chadd
28863dab8eeSAdrian Chadd s->block.hash.uncompressed += s->block.uncompressed;
28963dab8eeSAdrian Chadd s->block.hash.crc32 = xz_crc32(
29063dab8eeSAdrian Chadd (const uint8_t *)&s->block.hash,
29163dab8eeSAdrian Chadd sizeof(s->block.hash), s->block.hash.crc32);
29263dab8eeSAdrian Chadd
29363dab8eeSAdrian Chadd ++s->block.count;
29463dab8eeSAdrian Chadd }
29563dab8eeSAdrian Chadd
29663dab8eeSAdrian Chadd return ret;
29763dab8eeSAdrian Chadd }
29863dab8eeSAdrian Chadd
29963dab8eeSAdrian Chadd /* Update the Index size and the CRC32 value. */
index_update(struct xz_dec * s,const struct xz_buf * b)30063dab8eeSAdrian Chadd static void index_update(struct xz_dec *s, const struct xz_buf *b)
30163dab8eeSAdrian Chadd {
30263dab8eeSAdrian Chadd size_t in_used = b->in_pos - s->in_start;
30363dab8eeSAdrian Chadd s->index.size += in_used;
304f0bd5302SXin LI s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc);
30563dab8eeSAdrian Chadd }
30663dab8eeSAdrian Chadd
30763dab8eeSAdrian Chadd /*
30863dab8eeSAdrian Chadd * Decode the Number of Records, Unpadded Size, and Uncompressed Size
30963dab8eeSAdrian Chadd * fields from the Index field. That is, Index Padding and CRC32 are not
31063dab8eeSAdrian Chadd * decoded by this function.
31163dab8eeSAdrian Chadd *
31263dab8eeSAdrian Chadd * This can return XZ_OK (more input needed), XZ_STREAM_END (everything
31363dab8eeSAdrian Chadd * successfully decoded), or XZ_DATA_ERROR (input is corrupt).
31463dab8eeSAdrian Chadd */
dec_index(struct xz_dec * s,struct xz_buf * b)31563dab8eeSAdrian Chadd static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
31663dab8eeSAdrian Chadd {
31763dab8eeSAdrian Chadd enum xz_ret ret;
31863dab8eeSAdrian Chadd
31963dab8eeSAdrian Chadd do {
32063dab8eeSAdrian Chadd ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
32163dab8eeSAdrian Chadd if (ret != XZ_STREAM_END) {
32263dab8eeSAdrian Chadd index_update(s, b);
32363dab8eeSAdrian Chadd return ret;
32463dab8eeSAdrian Chadd }
32563dab8eeSAdrian Chadd
32663dab8eeSAdrian Chadd switch (s->index.sequence) {
32763dab8eeSAdrian Chadd case SEQ_INDEX_COUNT:
32863dab8eeSAdrian Chadd s->index.count = s->vli;
32963dab8eeSAdrian Chadd
33063dab8eeSAdrian Chadd /*
33163dab8eeSAdrian Chadd * Validate that the Number of Records field
33263dab8eeSAdrian Chadd * indicates the same number of Records as
33363dab8eeSAdrian Chadd * there were Blocks in the Stream.
33463dab8eeSAdrian Chadd */
33563dab8eeSAdrian Chadd if (s->index.count != s->block.count)
33663dab8eeSAdrian Chadd return XZ_DATA_ERROR;
33763dab8eeSAdrian Chadd
33863dab8eeSAdrian Chadd s->index.sequence = SEQ_INDEX_UNPADDED;
33963dab8eeSAdrian Chadd break;
34063dab8eeSAdrian Chadd
34163dab8eeSAdrian Chadd case SEQ_INDEX_UNPADDED:
34263dab8eeSAdrian Chadd s->index.hash.unpadded += s->vli;
34363dab8eeSAdrian Chadd s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
34463dab8eeSAdrian Chadd break;
34563dab8eeSAdrian Chadd
34663dab8eeSAdrian Chadd case SEQ_INDEX_UNCOMPRESSED:
34763dab8eeSAdrian Chadd s->index.hash.uncompressed += s->vli;
34863dab8eeSAdrian Chadd s->index.hash.crc32 = xz_crc32(
34963dab8eeSAdrian Chadd (const uint8_t *)&s->index.hash,
35063dab8eeSAdrian Chadd sizeof(s->index.hash),
35163dab8eeSAdrian Chadd s->index.hash.crc32);
35263dab8eeSAdrian Chadd --s->index.count;
35363dab8eeSAdrian Chadd s->index.sequence = SEQ_INDEX_UNPADDED;
35463dab8eeSAdrian Chadd break;
35563dab8eeSAdrian Chadd }
35663dab8eeSAdrian Chadd } while (s->index.count > 0);
35763dab8eeSAdrian Chadd
35863dab8eeSAdrian Chadd return XZ_STREAM_END;
35963dab8eeSAdrian Chadd }
36063dab8eeSAdrian Chadd
36163dab8eeSAdrian Chadd /*
362f0bd5302SXin LI * Validate that the next four or eight input bytes match the value
363f0bd5302SXin LI * of s->crc. s->pos must be zero when starting to validate the first byte.
364f0bd5302SXin LI * The "bits" argument allows using the same code for both CRC32 and CRC64.
36563dab8eeSAdrian Chadd */
crc_validate(struct xz_dec * s,struct xz_buf * b,uint32_t bits)366f0bd5302SXin LI static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b,
367f0bd5302SXin LI uint32_t bits)
36863dab8eeSAdrian Chadd {
36963dab8eeSAdrian Chadd do {
37063dab8eeSAdrian Chadd if (b->in_pos == b->in_size)
37163dab8eeSAdrian Chadd return XZ_OK;
37263dab8eeSAdrian Chadd
373f0bd5302SXin LI if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++])
37463dab8eeSAdrian Chadd return XZ_DATA_ERROR;
37563dab8eeSAdrian Chadd
37663dab8eeSAdrian Chadd s->pos += 8;
37763dab8eeSAdrian Chadd
378f0bd5302SXin LI } while (s->pos < bits);
37963dab8eeSAdrian Chadd
380f0bd5302SXin LI s->crc = 0;
38163dab8eeSAdrian Chadd s->pos = 0;
38263dab8eeSAdrian Chadd
38363dab8eeSAdrian Chadd return XZ_STREAM_END;
38463dab8eeSAdrian Chadd }
38563dab8eeSAdrian Chadd
38663dab8eeSAdrian Chadd #ifdef XZ_DEC_ANY_CHECK
38763dab8eeSAdrian Chadd /*
38863dab8eeSAdrian Chadd * Skip over the Check field when the Check ID is not supported.
38963dab8eeSAdrian Chadd * Returns true once the whole Check field has been skipped over.
39063dab8eeSAdrian Chadd */
check_skip(struct xz_dec * s,struct xz_buf * b)39163dab8eeSAdrian Chadd static bool check_skip(struct xz_dec *s, struct xz_buf *b)
39263dab8eeSAdrian Chadd {
39363dab8eeSAdrian Chadd while (s->pos < check_sizes[s->check_type]) {
39463dab8eeSAdrian Chadd if (b->in_pos == b->in_size)
39563dab8eeSAdrian Chadd return false;
39663dab8eeSAdrian Chadd
39763dab8eeSAdrian Chadd ++b->in_pos;
39863dab8eeSAdrian Chadd ++s->pos;
39963dab8eeSAdrian Chadd }
40063dab8eeSAdrian Chadd
40163dab8eeSAdrian Chadd s->pos = 0;
40263dab8eeSAdrian Chadd
40363dab8eeSAdrian Chadd return true;
40463dab8eeSAdrian Chadd }
40563dab8eeSAdrian Chadd #endif
40663dab8eeSAdrian Chadd
40763dab8eeSAdrian Chadd /* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
dec_stream_header(struct xz_dec * s)40863dab8eeSAdrian Chadd static enum xz_ret dec_stream_header(struct xz_dec *s)
40963dab8eeSAdrian Chadd {
41063dab8eeSAdrian Chadd if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
41163dab8eeSAdrian Chadd return XZ_FORMAT_ERROR;
41263dab8eeSAdrian Chadd
41363dab8eeSAdrian Chadd if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0)
41463dab8eeSAdrian Chadd != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
41563dab8eeSAdrian Chadd return XZ_DATA_ERROR;
41663dab8eeSAdrian Chadd
41763dab8eeSAdrian Chadd if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
41863dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
41963dab8eeSAdrian Chadd
42063dab8eeSAdrian Chadd /*
421f0bd5302SXin LI * Of integrity checks, we support none (Check ID = 0),
422f0bd5302SXin LI * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4).
423f0bd5302SXin LI * However, if XZ_DEC_ANY_CHECK is defined, we will accept other
424f0bd5302SXin LI * check types too, but then the check won't be verified and
425f0bd5302SXin LI * a warning (XZ_UNSUPPORTED_CHECK) will be given.
42663dab8eeSAdrian Chadd */
427*cd3a777bSXin LI if (s->temp.buf[HEADER_MAGIC_SIZE + 1] > XZ_CHECK_MAX)
428*cd3a777bSXin LI return XZ_OPTIONS_ERROR;
429*cd3a777bSXin LI
43063dab8eeSAdrian Chadd s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
43163dab8eeSAdrian Chadd
43263dab8eeSAdrian Chadd #ifdef XZ_DEC_ANY_CHECK
433f0bd5302SXin LI if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
43463dab8eeSAdrian Chadd return XZ_UNSUPPORTED_CHECK;
43563dab8eeSAdrian Chadd #else
436f0bd5302SXin LI if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type))
43763dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
43863dab8eeSAdrian Chadd #endif
43963dab8eeSAdrian Chadd
44063dab8eeSAdrian Chadd return XZ_OK;
44163dab8eeSAdrian Chadd }
44263dab8eeSAdrian Chadd
44363dab8eeSAdrian Chadd /* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
dec_stream_footer(struct xz_dec * s)44463dab8eeSAdrian Chadd static enum xz_ret dec_stream_footer(struct xz_dec *s)
44563dab8eeSAdrian Chadd {
44663dab8eeSAdrian Chadd if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
44763dab8eeSAdrian Chadd return XZ_DATA_ERROR;
44863dab8eeSAdrian Chadd
44963dab8eeSAdrian Chadd if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
45063dab8eeSAdrian Chadd return XZ_DATA_ERROR;
45163dab8eeSAdrian Chadd
45263dab8eeSAdrian Chadd /*
45363dab8eeSAdrian Chadd * Validate Backward Size. Note that we never added the size of the
45463dab8eeSAdrian Chadd * Index CRC32 field to s->index.size, thus we use s->index.size / 4
45563dab8eeSAdrian Chadd * instead of s->index.size / 4 - 1.
45663dab8eeSAdrian Chadd */
45763dab8eeSAdrian Chadd if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
45863dab8eeSAdrian Chadd return XZ_DATA_ERROR;
45963dab8eeSAdrian Chadd
46063dab8eeSAdrian Chadd if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
46163dab8eeSAdrian Chadd return XZ_DATA_ERROR;
46263dab8eeSAdrian Chadd
46363dab8eeSAdrian Chadd /*
46463dab8eeSAdrian Chadd * Use XZ_STREAM_END instead of XZ_OK to be more convenient
46563dab8eeSAdrian Chadd * for the caller.
46663dab8eeSAdrian Chadd */
46763dab8eeSAdrian Chadd return XZ_STREAM_END;
46863dab8eeSAdrian Chadd }
46963dab8eeSAdrian Chadd
47063dab8eeSAdrian Chadd /* Decode the Block Header and initialize the filter chain. */
dec_block_header(struct xz_dec * s)47163dab8eeSAdrian Chadd static enum xz_ret dec_block_header(struct xz_dec *s)
47263dab8eeSAdrian Chadd {
47363dab8eeSAdrian Chadd enum xz_ret ret;
47463dab8eeSAdrian Chadd
47563dab8eeSAdrian Chadd /*
47663dab8eeSAdrian Chadd * Validate the CRC32. We know that the temp buffer is at least
47763dab8eeSAdrian Chadd * eight bytes so this is safe.
47863dab8eeSAdrian Chadd */
47963dab8eeSAdrian Chadd s->temp.size -= 4;
48063dab8eeSAdrian Chadd if (xz_crc32(s->temp.buf, s->temp.size, 0)
48163dab8eeSAdrian Chadd != get_le32(s->temp.buf + s->temp.size))
48263dab8eeSAdrian Chadd return XZ_DATA_ERROR;
48363dab8eeSAdrian Chadd
48463dab8eeSAdrian Chadd s->temp.pos = 2;
48563dab8eeSAdrian Chadd
48663dab8eeSAdrian Chadd /*
48763dab8eeSAdrian Chadd * Catch unsupported Block Flags. We support only one or two filters
48863dab8eeSAdrian Chadd * in the chain, so we catch that with the same test.
48963dab8eeSAdrian Chadd */
49063dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
49163dab8eeSAdrian Chadd if (s->temp.buf[1] & 0x3E)
49263dab8eeSAdrian Chadd #else
49363dab8eeSAdrian Chadd if (s->temp.buf[1] & 0x3F)
49463dab8eeSAdrian Chadd #endif
49563dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
49663dab8eeSAdrian Chadd
49763dab8eeSAdrian Chadd /* Compressed Size */
49863dab8eeSAdrian Chadd if (s->temp.buf[1] & 0x40) {
49963dab8eeSAdrian Chadd if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
50063dab8eeSAdrian Chadd != XZ_STREAM_END)
50163dab8eeSAdrian Chadd return XZ_DATA_ERROR;
50263dab8eeSAdrian Chadd
50363dab8eeSAdrian Chadd s->block_header.compressed = s->vli;
50463dab8eeSAdrian Chadd } else {
50563dab8eeSAdrian Chadd s->block_header.compressed = VLI_UNKNOWN;
50663dab8eeSAdrian Chadd }
50763dab8eeSAdrian Chadd
50863dab8eeSAdrian Chadd /* Uncompressed Size */
50963dab8eeSAdrian Chadd if (s->temp.buf[1] & 0x80) {
51063dab8eeSAdrian Chadd if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
51163dab8eeSAdrian Chadd != XZ_STREAM_END)
51263dab8eeSAdrian Chadd return XZ_DATA_ERROR;
51363dab8eeSAdrian Chadd
51463dab8eeSAdrian Chadd s->block_header.uncompressed = s->vli;
51563dab8eeSAdrian Chadd } else {
51663dab8eeSAdrian Chadd s->block_header.uncompressed = VLI_UNKNOWN;
51763dab8eeSAdrian Chadd }
51863dab8eeSAdrian Chadd
51963dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
52063dab8eeSAdrian Chadd /* If there are two filters, the first one must be a BCJ filter. */
52163dab8eeSAdrian Chadd s->bcj_active = s->temp.buf[1] & 0x01;
52263dab8eeSAdrian Chadd if (s->bcj_active) {
52363dab8eeSAdrian Chadd if (s->temp.size - s->temp.pos < 2)
52463dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
52563dab8eeSAdrian Chadd
52663dab8eeSAdrian Chadd ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
52763dab8eeSAdrian Chadd if (ret != XZ_OK)
52863dab8eeSAdrian Chadd return ret;
52963dab8eeSAdrian Chadd
53063dab8eeSAdrian Chadd /*
53163dab8eeSAdrian Chadd * We don't support custom start offset,
53263dab8eeSAdrian Chadd * so Size of Properties must be zero.
53363dab8eeSAdrian Chadd */
53463dab8eeSAdrian Chadd if (s->temp.buf[s->temp.pos++] != 0x00)
53563dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
53663dab8eeSAdrian Chadd }
53763dab8eeSAdrian Chadd #endif
53863dab8eeSAdrian Chadd
53963dab8eeSAdrian Chadd /* Valid Filter Flags always take at least two bytes. */
54063dab8eeSAdrian Chadd if (s->temp.size - s->temp.pos < 2)
54163dab8eeSAdrian Chadd return XZ_DATA_ERROR;
54263dab8eeSAdrian Chadd
54363dab8eeSAdrian Chadd /* Filter ID = LZMA2 */
54463dab8eeSAdrian Chadd if (s->temp.buf[s->temp.pos++] != 0x21)
54563dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
54663dab8eeSAdrian Chadd
54763dab8eeSAdrian Chadd /* Size of Properties = 1-byte Filter Properties */
54863dab8eeSAdrian Chadd if (s->temp.buf[s->temp.pos++] != 0x01)
54963dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
55063dab8eeSAdrian Chadd
55163dab8eeSAdrian Chadd /* Filter Properties contains LZMA2 dictionary size. */
55263dab8eeSAdrian Chadd if (s->temp.size - s->temp.pos < 1)
55363dab8eeSAdrian Chadd return XZ_DATA_ERROR;
55463dab8eeSAdrian Chadd
55563dab8eeSAdrian Chadd ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
55663dab8eeSAdrian Chadd if (ret != XZ_OK)
55763dab8eeSAdrian Chadd return ret;
55863dab8eeSAdrian Chadd
55963dab8eeSAdrian Chadd /* The rest must be Header Padding. */
56063dab8eeSAdrian Chadd while (s->temp.pos < s->temp.size)
56163dab8eeSAdrian Chadd if (s->temp.buf[s->temp.pos++] != 0x00)
56263dab8eeSAdrian Chadd return XZ_OPTIONS_ERROR;
56363dab8eeSAdrian Chadd
56463dab8eeSAdrian Chadd s->temp.pos = 0;
56563dab8eeSAdrian Chadd s->block.compressed = 0;
56663dab8eeSAdrian Chadd s->block.uncompressed = 0;
56763dab8eeSAdrian Chadd
56863dab8eeSAdrian Chadd return XZ_OK;
56963dab8eeSAdrian Chadd }
57063dab8eeSAdrian Chadd
dec_main(struct xz_dec * s,struct xz_buf * b)57163dab8eeSAdrian Chadd static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
57263dab8eeSAdrian Chadd {
57363dab8eeSAdrian Chadd enum xz_ret ret;
57463dab8eeSAdrian Chadd
57563dab8eeSAdrian Chadd /*
57663dab8eeSAdrian Chadd * Store the start position for the case when we are in the middle
57763dab8eeSAdrian Chadd * of the Index field.
57863dab8eeSAdrian Chadd */
57963dab8eeSAdrian Chadd s->in_start = b->in_pos;
58063dab8eeSAdrian Chadd
58163dab8eeSAdrian Chadd while (true) {
58263dab8eeSAdrian Chadd switch (s->sequence) {
58363dab8eeSAdrian Chadd case SEQ_STREAM_HEADER:
58463dab8eeSAdrian Chadd /*
58563dab8eeSAdrian Chadd * Stream Header is copied to s->temp, and then
58663dab8eeSAdrian Chadd * decoded from there. This way if the caller
58763dab8eeSAdrian Chadd * gives us only little input at a time, we can
58863dab8eeSAdrian Chadd * still keep the Stream Header decoding code
58963dab8eeSAdrian Chadd * simple. Similar approach is used in many places
59063dab8eeSAdrian Chadd * in this file.
59163dab8eeSAdrian Chadd */
59263dab8eeSAdrian Chadd if (!fill_temp(s, b))
59363dab8eeSAdrian Chadd return XZ_OK;
59463dab8eeSAdrian Chadd
59563dab8eeSAdrian Chadd /*
59663dab8eeSAdrian Chadd * If dec_stream_header() returns
59763dab8eeSAdrian Chadd * XZ_UNSUPPORTED_CHECK, it is still possible
59863dab8eeSAdrian Chadd * to continue decoding if working in multi-call
59963dab8eeSAdrian Chadd * mode. Thus, update s->sequence before calling
60063dab8eeSAdrian Chadd * dec_stream_header().
60163dab8eeSAdrian Chadd */
60263dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_START;
60363dab8eeSAdrian Chadd
60463dab8eeSAdrian Chadd ret = dec_stream_header(s);
60563dab8eeSAdrian Chadd if (ret != XZ_OK)
60663dab8eeSAdrian Chadd return ret;
60763dab8eeSAdrian Chadd
608*cd3a777bSXin LI /* Fall through */
609*cd3a777bSXin LI
61063dab8eeSAdrian Chadd case SEQ_BLOCK_START:
61163dab8eeSAdrian Chadd /* We need one byte of input to continue. */
61263dab8eeSAdrian Chadd if (b->in_pos == b->in_size)
61363dab8eeSAdrian Chadd return XZ_OK;
61463dab8eeSAdrian Chadd
61563dab8eeSAdrian Chadd /* See if this is the beginning of the Index field. */
61663dab8eeSAdrian Chadd if (b->in[b->in_pos] == 0) {
61763dab8eeSAdrian Chadd s->in_start = b->in_pos++;
61863dab8eeSAdrian Chadd s->sequence = SEQ_INDEX;
61963dab8eeSAdrian Chadd break;
62063dab8eeSAdrian Chadd }
62163dab8eeSAdrian Chadd
62263dab8eeSAdrian Chadd /*
62363dab8eeSAdrian Chadd * Calculate the size of the Block Header and
62463dab8eeSAdrian Chadd * prepare to decode it.
62563dab8eeSAdrian Chadd */
62663dab8eeSAdrian Chadd s->block_header.size
62763dab8eeSAdrian Chadd = ((uint32_t)b->in[b->in_pos] + 1) * 4;
62863dab8eeSAdrian Chadd
62963dab8eeSAdrian Chadd s->temp.size = s->block_header.size;
63063dab8eeSAdrian Chadd s->temp.pos = 0;
63163dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_HEADER;
63263dab8eeSAdrian Chadd
633*cd3a777bSXin LI /* Fall through */
634*cd3a777bSXin LI
63563dab8eeSAdrian Chadd case SEQ_BLOCK_HEADER:
63663dab8eeSAdrian Chadd if (!fill_temp(s, b))
63763dab8eeSAdrian Chadd return XZ_OK;
63863dab8eeSAdrian Chadd
63963dab8eeSAdrian Chadd ret = dec_block_header(s);
64063dab8eeSAdrian Chadd if (ret != XZ_OK)
64163dab8eeSAdrian Chadd return ret;
64263dab8eeSAdrian Chadd
64363dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_UNCOMPRESS;
64463dab8eeSAdrian Chadd
645*cd3a777bSXin LI /* Fall through */
646*cd3a777bSXin LI
64763dab8eeSAdrian Chadd case SEQ_BLOCK_UNCOMPRESS:
64863dab8eeSAdrian Chadd ret = dec_block(s, b);
64963dab8eeSAdrian Chadd if (ret != XZ_STREAM_END)
65063dab8eeSAdrian Chadd return ret;
65163dab8eeSAdrian Chadd
65263dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_PADDING;
65363dab8eeSAdrian Chadd
654*cd3a777bSXin LI /* Fall through */
655*cd3a777bSXin LI
65663dab8eeSAdrian Chadd case SEQ_BLOCK_PADDING:
65763dab8eeSAdrian Chadd /*
65863dab8eeSAdrian Chadd * Size of Compressed Data + Block Padding
65963dab8eeSAdrian Chadd * must be a multiple of four. We don't need
66063dab8eeSAdrian Chadd * s->block.compressed for anything else
66163dab8eeSAdrian Chadd * anymore, so we use it here to test the size
66263dab8eeSAdrian Chadd * of the Block Padding field.
66363dab8eeSAdrian Chadd */
66463dab8eeSAdrian Chadd while (s->block.compressed & 3) {
66563dab8eeSAdrian Chadd if (b->in_pos == b->in_size)
66663dab8eeSAdrian Chadd return XZ_OK;
66763dab8eeSAdrian Chadd
66863dab8eeSAdrian Chadd if (b->in[b->in_pos++] != 0)
66963dab8eeSAdrian Chadd return XZ_DATA_ERROR;
67063dab8eeSAdrian Chadd
67163dab8eeSAdrian Chadd ++s->block.compressed;
67263dab8eeSAdrian Chadd }
67363dab8eeSAdrian Chadd
67463dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_CHECK;
67563dab8eeSAdrian Chadd
676*cd3a777bSXin LI /* Fall through */
677*cd3a777bSXin LI
67863dab8eeSAdrian Chadd case SEQ_BLOCK_CHECK:
67963dab8eeSAdrian Chadd if (s->check_type == XZ_CHECK_CRC32) {
680f0bd5302SXin LI ret = crc_validate(s, b, 32);
681f0bd5302SXin LI if (ret != XZ_STREAM_END)
682f0bd5302SXin LI return ret;
683f0bd5302SXin LI }
684f0bd5302SXin LI else if (IS_CRC64(s->check_type)) {
685f0bd5302SXin LI ret = crc_validate(s, b, 64);
68663dab8eeSAdrian Chadd if (ret != XZ_STREAM_END)
68763dab8eeSAdrian Chadd return ret;
68863dab8eeSAdrian Chadd }
68963dab8eeSAdrian Chadd #ifdef XZ_DEC_ANY_CHECK
69063dab8eeSAdrian Chadd else if (!check_skip(s, b)) {
69163dab8eeSAdrian Chadd return XZ_OK;
69263dab8eeSAdrian Chadd }
69363dab8eeSAdrian Chadd #endif
69463dab8eeSAdrian Chadd
69563dab8eeSAdrian Chadd s->sequence = SEQ_BLOCK_START;
69663dab8eeSAdrian Chadd break;
69763dab8eeSAdrian Chadd
69863dab8eeSAdrian Chadd case SEQ_INDEX:
69963dab8eeSAdrian Chadd ret = dec_index(s, b);
70063dab8eeSAdrian Chadd if (ret != XZ_STREAM_END)
70163dab8eeSAdrian Chadd return ret;
70263dab8eeSAdrian Chadd
70363dab8eeSAdrian Chadd s->sequence = SEQ_INDEX_PADDING;
70463dab8eeSAdrian Chadd
705*cd3a777bSXin LI /* Fall through */
706*cd3a777bSXin LI
70763dab8eeSAdrian Chadd case SEQ_INDEX_PADDING:
70863dab8eeSAdrian Chadd while ((s->index.size + (b->in_pos - s->in_start))
70963dab8eeSAdrian Chadd & 3) {
71063dab8eeSAdrian Chadd if (b->in_pos == b->in_size) {
71163dab8eeSAdrian Chadd index_update(s, b);
71263dab8eeSAdrian Chadd return XZ_OK;
71363dab8eeSAdrian Chadd }
71463dab8eeSAdrian Chadd
71563dab8eeSAdrian Chadd if (b->in[b->in_pos++] != 0)
71663dab8eeSAdrian Chadd return XZ_DATA_ERROR;
71763dab8eeSAdrian Chadd }
71863dab8eeSAdrian Chadd
71963dab8eeSAdrian Chadd /* Finish the CRC32 value and Index size. */
72063dab8eeSAdrian Chadd index_update(s, b);
72163dab8eeSAdrian Chadd
72263dab8eeSAdrian Chadd /* Compare the hashes to validate the Index field. */
72363dab8eeSAdrian Chadd if (!memeq(&s->block.hash, &s->index.hash,
72463dab8eeSAdrian Chadd sizeof(s->block.hash)))
72563dab8eeSAdrian Chadd return XZ_DATA_ERROR;
72663dab8eeSAdrian Chadd
72763dab8eeSAdrian Chadd s->sequence = SEQ_INDEX_CRC32;
72863dab8eeSAdrian Chadd
729*cd3a777bSXin LI /* Fall through */
730*cd3a777bSXin LI
73163dab8eeSAdrian Chadd case SEQ_INDEX_CRC32:
732f0bd5302SXin LI ret = crc_validate(s, b, 32);
73363dab8eeSAdrian Chadd if (ret != XZ_STREAM_END)
73463dab8eeSAdrian Chadd return ret;
73563dab8eeSAdrian Chadd
73663dab8eeSAdrian Chadd s->temp.size = STREAM_HEADER_SIZE;
73763dab8eeSAdrian Chadd s->sequence = SEQ_STREAM_FOOTER;
73863dab8eeSAdrian Chadd
739*cd3a777bSXin LI /* Fall through */
740*cd3a777bSXin LI
74163dab8eeSAdrian Chadd case SEQ_STREAM_FOOTER:
74263dab8eeSAdrian Chadd if (!fill_temp(s, b))
74363dab8eeSAdrian Chadd return XZ_OK;
74463dab8eeSAdrian Chadd
74563dab8eeSAdrian Chadd return dec_stream_footer(s);
746*cd3a777bSXin LI
747*cd3a777bSXin LI case SEQ_STREAM_PADDING:
748*cd3a777bSXin LI /* Never reached, only silencing a warning */
749*cd3a777bSXin LI break;
75063dab8eeSAdrian Chadd }
75163dab8eeSAdrian Chadd }
75263dab8eeSAdrian Chadd
75363dab8eeSAdrian Chadd /* Never reached */
75463dab8eeSAdrian Chadd }
75563dab8eeSAdrian Chadd
75663dab8eeSAdrian Chadd /*
75763dab8eeSAdrian Chadd * xz_dec_run() is a wrapper for dec_main() to handle some special cases in
75863dab8eeSAdrian Chadd * multi-call and single-call decoding.
75963dab8eeSAdrian Chadd *
76063dab8eeSAdrian Chadd * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
76163dab8eeSAdrian Chadd * are not going to make any progress anymore. This is to prevent the caller
76263dab8eeSAdrian Chadd * from calling us infinitely when the input file is truncated or otherwise
76363dab8eeSAdrian Chadd * corrupt. Since zlib-style API allows that the caller fills the input buffer
76463dab8eeSAdrian Chadd * only when the decoder doesn't produce any new output, we have to be careful
76563dab8eeSAdrian Chadd * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
76663dab8eeSAdrian Chadd * after the second consecutive call to xz_dec_run() that makes no progress.
76763dab8eeSAdrian Chadd *
76863dab8eeSAdrian Chadd * In single-call mode, if we couldn't decode everything and no error
76963dab8eeSAdrian Chadd * occurred, either the input is truncated or the output buffer is too small.
77063dab8eeSAdrian Chadd * Since we know that the last input byte never produces any output, we know
77163dab8eeSAdrian Chadd * that if all the input was consumed and decoding wasn't finished, the file
77263dab8eeSAdrian Chadd * must be corrupt. Otherwise the output buffer has to be too small or the
77363dab8eeSAdrian Chadd * file is corrupt in a way that decoding it produces too big output.
77463dab8eeSAdrian Chadd *
77563dab8eeSAdrian Chadd * If single-call decoding fails, we reset b->in_pos and b->out_pos back to
77663dab8eeSAdrian Chadd * their original values. This is because with some filter chains there won't
77763dab8eeSAdrian Chadd * be any valid uncompressed data in the output buffer unless the decoding
77863dab8eeSAdrian Chadd * actually succeeds (that's the price to pay of using the output buffer as
77963dab8eeSAdrian Chadd * the workspace).
78063dab8eeSAdrian Chadd */
xz_dec_run(struct xz_dec * s,struct xz_buf * b)78163dab8eeSAdrian Chadd XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
78263dab8eeSAdrian Chadd {
78363dab8eeSAdrian Chadd size_t in_start;
78463dab8eeSAdrian Chadd size_t out_start;
78563dab8eeSAdrian Chadd enum xz_ret ret;
78663dab8eeSAdrian Chadd
78763dab8eeSAdrian Chadd if (DEC_IS_SINGLE(s->mode))
78863dab8eeSAdrian Chadd xz_dec_reset(s);
78963dab8eeSAdrian Chadd
79063dab8eeSAdrian Chadd in_start = b->in_pos;
79163dab8eeSAdrian Chadd out_start = b->out_pos;
79263dab8eeSAdrian Chadd ret = dec_main(s, b);
79363dab8eeSAdrian Chadd
79463dab8eeSAdrian Chadd if (DEC_IS_SINGLE(s->mode)) {
79563dab8eeSAdrian Chadd if (ret == XZ_OK)
79663dab8eeSAdrian Chadd ret = b->in_pos == b->in_size
79763dab8eeSAdrian Chadd ? XZ_DATA_ERROR : XZ_BUF_ERROR;
79863dab8eeSAdrian Chadd
79963dab8eeSAdrian Chadd if (ret != XZ_STREAM_END) {
80063dab8eeSAdrian Chadd b->in_pos = in_start;
80163dab8eeSAdrian Chadd b->out_pos = out_start;
80263dab8eeSAdrian Chadd }
80363dab8eeSAdrian Chadd
80463dab8eeSAdrian Chadd } else if (ret == XZ_OK && in_start == b->in_pos
80563dab8eeSAdrian Chadd && out_start == b->out_pos) {
80663dab8eeSAdrian Chadd if (s->allow_buf_error)
80763dab8eeSAdrian Chadd ret = XZ_BUF_ERROR;
80863dab8eeSAdrian Chadd
80963dab8eeSAdrian Chadd s->allow_buf_error = true;
81063dab8eeSAdrian Chadd } else {
81163dab8eeSAdrian Chadd s->allow_buf_error = false;
81263dab8eeSAdrian Chadd }
81363dab8eeSAdrian Chadd
81463dab8eeSAdrian Chadd return ret;
81563dab8eeSAdrian Chadd }
81663dab8eeSAdrian Chadd
817*cd3a777bSXin LI #ifdef XZ_DEC_CONCATENATED
xz_dec_catrun(struct xz_dec * s,struct xz_buf * b,int finish)818*cd3a777bSXin LI XZ_EXTERN enum xz_ret xz_dec_catrun(struct xz_dec *s, struct xz_buf *b,
819*cd3a777bSXin LI int finish)
820*cd3a777bSXin LI {
821*cd3a777bSXin LI enum xz_ret ret;
822*cd3a777bSXin LI
823*cd3a777bSXin LI if (DEC_IS_SINGLE(s->mode)) {
824*cd3a777bSXin LI xz_dec_reset(s);
825*cd3a777bSXin LI finish = true;
826*cd3a777bSXin LI }
827*cd3a777bSXin LI
828*cd3a777bSXin LI while (true) {
829*cd3a777bSXin LI if (s->sequence == SEQ_STREAM_PADDING) {
830*cd3a777bSXin LI /*
831*cd3a777bSXin LI * Skip Stream Padding. Its size must be a multiple
832*cd3a777bSXin LI * of four bytes which is tracked with s->pos.
833*cd3a777bSXin LI */
834*cd3a777bSXin LI while (true) {
835*cd3a777bSXin LI if (b->in_pos == b->in_size) {
836*cd3a777bSXin LI /*
837*cd3a777bSXin LI * Note that if we are repeatedly
838*cd3a777bSXin LI * given no input and finish is false,
839*cd3a777bSXin LI * we will keep returning XZ_OK even
840*cd3a777bSXin LI * though no progress is being made.
841*cd3a777bSXin LI * The lack of XZ_BUF_ERROR support
842*cd3a777bSXin LI * isn't a problem here because a
843*cd3a777bSXin LI * reasonable caller will eventually
844*cd3a777bSXin LI * provide more input or set finish
845*cd3a777bSXin LI * to true.
846*cd3a777bSXin LI */
847*cd3a777bSXin LI if (!finish)
848*cd3a777bSXin LI return XZ_OK;
849*cd3a777bSXin LI
850*cd3a777bSXin LI if (s->pos != 0)
851*cd3a777bSXin LI return XZ_DATA_ERROR;
852*cd3a777bSXin LI
853*cd3a777bSXin LI return XZ_STREAM_END;
854*cd3a777bSXin LI }
855*cd3a777bSXin LI
856*cd3a777bSXin LI if (b->in[b->in_pos] != 0x00) {
857*cd3a777bSXin LI if (s->pos != 0)
858*cd3a777bSXin LI return XZ_DATA_ERROR;
859*cd3a777bSXin LI
860*cd3a777bSXin LI break;
861*cd3a777bSXin LI }
862*cd3a777bSXin LI
863*cd3a777bSXin LI ++b->in_pos;
864*cd3a777bSXin LI s->pos = (s->pos + 1) & 3;
865*cd3a777bSXin LI }
866*cd3a777bSXin LI
867*cd3a777bSXin LI /*
868*cd3a777bSXin LI * More input remains. It should be a new Stream.
869*cd3a777bSXin LI *
870*cd3a777bSXin LI * In single-call mode xz_dec_run() will always call
871*cd3a777bSXin LI * xz_dec_reset(). Thus, we need to do it here only
872*cd3a777bSXin LI * in multi-call mode.
873*cd3a777bSXin LI */
874*cd3a777bSXin LI if (DEC_IS_MULTI(s->mode))
875*cd3a777bSXin LI xz_dec_reset(s);
876*cd3a777bSXin LI }
877*cd3a777bSXin LI
878*cd3a777bSXin LI ret = xz_dec_run(s, b);
879*cd3a777bSXin LI
880*cd3a777bSXin LI if (ret != XZ_STREAM_END)
881*cd3a777bSXin LI break;
882*cd3a777bSXin LI
883*cd3a777bSXin LI s->sequence = SEQ_STREAM_PADDING;
884*cd3a777bSXin LI }
885*cd3a777bSXin LI
886*cd3a777bSXin LI return ret;
887*cd3a777bSXin LI }
888*cd3a777bSXin LI #endif
889*cd3a777bSXin LI
xz_dec_init(enum xz_mode mode,uint32_t dict_max)89063dab8eeSAdrian Chadd XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max)
89163dab8eeSAdrian Chadd {
89263dab8eeSAdrian Chadd struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
89363dab8eeSAdrian Chadd if (s == NULL)
89463dab8eeSAdrian Chadd return NULL;
89563dab8eeSAdrian Chadd
89663dab8eeSAdrian Chadd s->mode = mode;
89763dab8eeSAdrian Chadd
89863dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
89963dab8eeSAdrian Chadd s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
90063dab8eeSAdrian Chadd if (s->bcj == NULL)
90163dab8eeSAdrian Chadd goto error_bcj;
90263dab8eeSAdrian Chadd #endif
90363dab8eeSAdrian Chadd
90463dab8eeSAdrian Chadd s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
90563dab8eeSAdrian Chadd if (s->lzma2 == NULL)
90663dab8eeSAdrian Chadd goto error_lzma2;
90763dab8eeSAdrian Chadd
90863dab8eeSAdrian Chadd xz_dec_reset(s);
90963dab8eeSAdrian Chadd return s;
91063dab8eeSAdrian Chadd
91163dab8eeSAdrian Chadd error_lzma2:
91263dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
91363dab8eeSAdrian Chadd xz_dec_bcj_end(s->bcj);
91463dab8eeSAdrian Chadd error_bcj:
91563dab8eeSAdrian Chadd #endif
91663dab8eeSAdrian Chadd kfree(s);
91763dab8eeSAdrian Chadd return NULL;
91863dab8eeSAdrian Chadd }
91963dab8eeSAdrian Chadd
xz_dec_reset(struct xz_dec * s)92063dab8eeSAdrian Chadd XZ_EXTERN void xz_dec_reset(struct xz_dec *s)
92163dab8eeSAdrian Chadd {
92263dab8eeSAdrian Chadd s->sequence = SEQ_STREAM_HEADER;
92363dab8eeSAdrian Chadd s->allow_buf_error = false;
92463dab8eeSAdrian Chadd s->pos = 0;
925f0bd5302SXin LI s->crc = 0;
92663dab8eeSAdrian Chadd memzero(&s->block, sizeof(s->block));
92763dab8eeSAdrian Chadd memzero(&s->index, sizeof(s->index));
92863dab8eeSAdrian Chadd s->temp.pos = 0;
92963dab8eeSAdrian Chadd s->temp.size = STREAM_HEADER_SIZE;
93063dab8eeSAdrian Chadd }
93163dab8eeSAdrian Chadd
xz_dec_end(struct xz_dec * s)93263dab8eeSAdrian Chadd XZ_EXTERN void xz_dec_end(struct xz_dec *s)
93363dab8eeSAdrian Chadd {
93463dab8eeSAdrian Chadd if (s != NULL) {
93563dab8eeSAdrian Chadd xz_dec_lzma2_end(s->lzma2);
93663dab8eeSAdrian Chadd #ifdef XZ_DEC_BCJ
93763dab8eeSAdrian Chadd xz_dec_bcj_end(s->bcj);
93863dab8eeSAdrian Chadd #endif
93963dab8eeSAdrian Chadd kfree(s);
94063dab8eeSAdrian Chadd }
94163dab8eeSAdrian Chadd }
942