xref: /freebsd/contrib/xz/src/liblzma/common/stream_decoder.c (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
2*3b35e7eeSXin LI 
381ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
481ad8388SMartin Matuska //
581ad8388SMartin Matuska /// \file       stream_decoder.c
681ad8388SMartin Matuska /// \brief      Decodes .xz Streams
781ad8388SMartin Matuska //
881ad8388SMartin Matuska //  Author:     Lasse Collin
981ad8388SMartin Matuska //
1081ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1181ad8388SMartin Matuska 
1281ad8388SMartin Matuska #include "stream_decoder.h"
1381ad8388SMartin Matuska #include "block_decoder.h"
14047153b4SXin LI #include "index.h"
1581ad8388SMartin Matuska 
1681ad8388SMartin Matuska 
171456f0f9SXin LI typedef struct {
1881ad8388SMartin Matuska 	enum {
1981ad8388SMartin Matuska 		SEQ_STREAM_HEADER,
2081ad8388SMartin Matuska 		SEQ_BLOCK_HEADER,
219e6bbe47SXin LI 		SEQ_BLOCK_INIT,
229e6bbe47SXin LI 		SEQ_BLOCK_RUN,
2381ad8388SMartin Matuska 		SEQ_INDEX,
2481ad8388SMartin Matuska 		SEQ_STREAM_FOOTER,
2581ad8388SMartin Matuska 		SEQ_STREAM_PADDING,
2681ad8388SMartin Matuska 	} sequence;
2781ad8388SMartin Matuska 
289e6bbe47SXin LI 	/// Block decoder
2981ad8388SMartin Matuska 	lzma_next_coder block_decoder;
3081ad8388SMartin Matuska 
3181ad8388SMartin Matuska 	/// Block options decoded by the Block Header decoder and used by
3281ad8388SMartin Matuska 	/// the Block decoder.
3381ad8388SMartin Matuska 	lzma_block block_options;
3481ad8388SMartin Matuska 
3581ad8388SMartin Matuska 	/// Stream Flags from Stream Header
3681ad8388SMartin Matuska 	lzma_stream_flags stream_flags;
3781ad8388SMartin Matuska 
3881ad8388SMartin Matuska 	/// Index is hashed so that it can be compared to the sizes of Blocks
3981ad8388SMartin Matuska 	/// with O(1) memory usage.
4081ad8388SMartin Matuska 	lzma_index_hash *index_hash;
4181ad8388SMartin Matuska 
4281ad8388SMartin Matuska 	/// Memory usage limit
4381ad8388SMartin Matuska 	uint64_t memlimit;
4481ad8388SMartin Matuska 
4581ad8388SMartin Matuska 	/// Amount of memory actually needed (only an estimate)
4681ad8388SMartin Matuska 	uint64_t memusage;
4781ad8388SMartin Matuska 
4881ad8388SMartin Matuska 	/// If true, LZMA_NO_CHECK is returned if the Stream has
4981ad8388SMartin Matuska 	/// no integrity check.
5081ad8388SMartin Matuska 	bool tell_no_check;
5181ad8388SMartin Matuska 
5281ad8388SMartin Matuska 	/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
5381ad8388SMartin Matuska 	/// an integrity check that isn't supported by this liblzma build.
5481ad8388SMartin Matuska 	bool tell_unsupported_check;
5581ad8388SMartin Matuska 
5681ad8388SMartin Matuska 	/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
5781ad8388SMartin Matuska 	bool tell_any_check;
5881ad8388SMartin Matuska 
5953200025SRui Paulo 	/// If true, we will tell the Block decoder to skip calculating
6053200025SRui Paulo 	/// and verifying the integrity check.
6153200025SRui Paulo 	bool ignore_check;
6253200025SRui Paulo 
6381ad8388SMartin Matuska 	/// If true, we will decode concatenated Streams that possibly have
6481ad8388SMartin Matuska 	/// Stream Padding between or after them. LZMA_STREAM_END is returned
659e6bbe47SXin LI 	/// once the application isn't giving us any new input (LZMA_FINISH),
669e6bbe47SXin LI 	/// and we aren't in the middle of a Stream, and possible
679e6bbe47SXin LI 	/// Stream Padding is a multiple of four bytes.
6881ad8388SMartin Matuska 	bool concatenated;
6981ad8388SMartin Matuska 
7081ad8388SMartin Matuska 	/// When decoding concatenated Streams, this is true as long as we
7181ad8388SMartin Matuska 	/// are decoding the first Stream. This is needed to avoid misleading
7281ad8388SMartin Matuska 	/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
7381ad8388SMartin Matuska 	/// bytes.
7481ad8388SMartin Matuska 	bool first_stream;
7581ad8388SMartin Matuska 
7681ad8388SMartin Matuska 	/// Write position in buffer[] and position in Stream Padding
7781ad8388SMartin Matuska 	size_t pos;
7881ad8388SMartin Matuska 
7981ad8388SMartin Matuska 	/// Buffer to hold Stream Header, Block Header, and Stream Footer.
8081ad8388SMartin Matuska 	/// Block Header has biggest maximum size.
8181ad8388SMartin Matuska 	uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
821456f0f9SXin LI } lzma_stream_coder;
8381ad8388SMartin Matuska 
8481ad8388SMartin Matuska 
8581ad8388SMartin Matuska static lzma_ret
861456f0f9SXin LI stream_decoder_reset(lzma_stream_coder *coder, const lzma_allocator *allocator)
8781ad8388SMartin Matuska {
8881ad8388SMartin Matuska 	// Initialize the Index hash used to verify the Index.
8981ad8388SMartin Matuska 	coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
9081ad8388SMartin Matuska 	if (coder->index_hash == NULL)
9181ad8388SMartin Matuska 		return LZMA_MEM_ERROR;
9281ad8388SMartin Matuska 
9381ad8388SMartin Matuska 	// Reset the rest of the variables.
9481ad8388SMartin Matuska 	coder->sequence = SEQ_STREAM_HEADER;
9581ad8388SMartin Matuska 	coder->pos = 0;
9681ad8388SMartin Matuska 
9781ad8388SMartin Matuska 	return LZMA_OK;
9881ad8388SMartin Matuska }
9981ad8388SMartin Matuska 
10081ad8388SMartin Matuska 
10181ad8388SMartin Matuska static lzma_ret
1021456f0f9SXin LI stream_decode(void *coder_ptr, const lzma_allocator *allocator,
10381ad8388SMartin Matuska 		const uint8_t *restrict in, size_t *restrict in_pos,
10481ad8388SMartin Matuska 		size_t in_size, uint8_t *restrict out,
10581ad8388SMartin Matuska 		size_t *restrict out_pos, size_t out_size, lzma_action action)
10681ad8388SMartin Matuska {
1071456f0f9SXin LI 	lzma_stream_coder *coder = coder_ptr;
1081456f0f9SXin LI 
10981ad8388SMartin Matuska 	// When decoding the actual Block, it may be able to produce more
11081ad8388SMartin Matuska 	// output even if we don't give it any new input.
11181ad8388SMartin Matuska 	while (true)
11281ad8388SMartin Matuska 	switch (coder->sequence) {
11381ad8388SMartin Matuska 	case SEQ_STREAM_HEADER: {
11481ad8388SMartin Matuska 		// Copy the Stream Header to the internal buffer.
11581ad8388SMartin Matuska 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
11681ad8388SMartin Matuska 				LZMA_STREAM_HEADER_SIZE);
11781ad8388SMartin Matuska 
11881ad8388SMartin Matuska 		// Return if we didn't get the whole Stream Header yet.
11981ad8388SMartin Matuska 		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
12081ad8388SMartin Matuska 			return LZMA_OK;
12181ad8388SMartin Matuska 
12281ad8388SMartin Matuska 		coder->pos = 0;
12381ad8388SMartin Matuska 
12481ad8388SMartin Matuska 		// Decode the Stream Header.
12581ad8388SMartin Matuska 		const lzma_ret ret = lzma_stream_header_decode(
12681ad8388SMartin Matuska 				&coder->stream_flags, coder->buffer);
12781ad8388SMartin Matuska 		if (ret != LZMA_OK)
12881ad8388SMartin Matuska 			return ret == LZMA_FORMAT_ERROR && !coder->first_stream
12981ad8388SMartin Matuska 					? LZMA_DATA_ERROR : ret;
13081ad8388SMartin Matuska 
13181ad8388SMartin Matuska 		// If we are decoding concatenated Streams, and the later
13281ad8388SMartin Matuska 		// Streams have invalid Header Magic Bytes, we give
13381ad8388SMartin Matuska 		// LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
13481ad8388SMartin Matuska 		coder->first_stream = false;
13581ad8388SMartin Matuska 
13681ad8388SMartin Matuska 		// Copy the type of the Check so that Block Header and Block
13781ad8388SMartin Matuska 		// decoders see it.
13881ad8388SMartin Matuska 		coder->block_options.check = coder->stream_flags.check;
13981ad8388SMartin Matuska 
14081ad8388SMartin Matuska 		// Even if we return LZMA_*_CHECK below, we want
14181ad8388SMartin Matuska 		// to continue from Block Header decoding.
14281ad8388SMartin Matuska 		coder->sequence = SEQ_BLOCK_HEADER;
14381ad8388SMartin Matuska 
14481ad8388SMartin Matuska 		// Detect if there's no integrity check or if it is
14581ad8388SMartin Matuska 		// unsupported if those were requested by the application.
14681ad8388SMartin Matuska 		if (coder->tell_no_check && coder->stream_flags.check
14781ad8388SMartin Matuska 				== LZMA_CHECK_NONE)
14881ad8388SMartin Matuska 			return LZMA_NO_CHECK;
14981ad8388SMartin Matuska 
15081ad8388SMartin Matuska 		if (coder->tell_unsupported_check
15181ad8388SMartin Matuska 				&& !lzma_check_is_supported(
15281ad8388SMartin Matuska 					coder->stream_flags.check))
15381ad8388SMartin Matuska 			return LZMA_UNSUPPORTED_CHECK;
15481ad8388SMartin Matuska 
15581ad8388SMartin Matuska 		if (coder->tell_any_check)
15681ad8388SMartin Matuska 			return LZMA_GET_CHECK;
15781ad8388SMartin Matuska 	}
15881ad8388SMartin Matuska 
15981ad8388SMartin Matuska 	// Fall through
16081ad8388SMartin Matuska 
16181ad8388SMartin Matuska 	case SEQ_BLOCK_HEADER: {
16281ad8388SMartin Matuska 		if (*in_pos >= in_size)
16381ad8388SMartin Matuska 			return LZMA_OK;
16481ad8388SMartin Matuska 
16581ad8388SMartin Matuska 		if (coder->pos == 0) {
16681ad8388SMartin Matuska 			// Detect if it's Index.
167047153b4SXin LI 			if (in[*in_pos] == INDEX_INDICATOR) {
16881ad8388SMartin Matuska 				coder->sequence = SEQ_INDEX;
16981ad8388SMartin Matuska 				break;
17081ad8388SMartin Matuska 			}
17181ad8388SMartin Matuska 
17281ad8388SMartin Matuska 			// Calculate the size of the Block Header. Note that
17381ad8388SMartin Matuska 			// Block Header decoder wants to see this byte too
17481ad8388SMartin Matuska 			// so don't advance *in_pos.
17581ad8388SMartin Matuska 			coder->block_options.header_size
17681ad8388SMartin Matuska 					= lzma_block_header_size_decode(
17781ad8388SMartin Matuska 						in[*in_pos]);
17881ad8388SMartin Matuska 		}
17981ad8388SMartin Matuska 
18081ad8388SMartin Matuska 		// Copy the Block Header to the internal buffer.
18181ad8388SMartin Matuska 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
18281ad8388SMartin Matuska 				coder->block_options.header_size);
18381ad8388SMartin Matuska 
18481ad8388SMartin Matuska 		// Return if we didn't get the whole Block Header yet.
18581ad8388SMartin Matuska 		if (coder->pos < coder->block_options.header_size)
18681ad8388SMartin Matuska 			return LZMA_OK;
18781ad8388SMartin Matuska 
18881ad8388SMartin Matuska 		coder->pos = 0;
1899e6bbe47SXin LI 		coder->sequence = SEQ_BLOCK_INIT;
1909e6bbe47SXin LI 	}
1919e6bbe47SXin LI 
1929e6bbe47SXin LI 	// Fall through
1939e6bbe47SXin LI 
1949e6bbe47SXin LI 	case SEQ_BLOCK_INIT: {
1959e6bbe47SXin LI 		// Checking memusage and doing the initialization needs
1969e6bbe47SXin LI 		// its own sequence point because we need to be able to
1979e6bbe47SXin LI 		// retry if we return LZMA_MEMLIMIT_ERROR.
19881ad8388SMartin Matuska 
19953200025SRui Paulo 		// Version 1 is needed to support the .ignore_check option.
20053200025SRui Paulo 		coder->block_options.version = 1;
20181ad8388SMartin Matuska 
20281ad8388SMartin Matuska 		// Set up a buffer to hold the filter chain. Block Header
20381ad8388SMartin Matuska 		// decoder will initialize all members of this array so
20481ad8388SMartin Matuska 		// we don't need to do it here.
20581ad8388SMartin Matuska 		lzma_filter filters[LZMA_FILTERS_MAX + 1];
20681ad8388SMartin Matuska 		coder->block_options.filters = filters;
20781ad8388SMartin Matuska 
20881ad8388SMartin Matuska 		// Decode the Block Header.
20981ad8388SMartin Matuska 		return_if_error(lzma_block_header_decode(&coder->block_options,
21081ad8388SMartin Matuska 				allocator, coder->buffer));
21181ad8388SMartin Matuska 
21253200025SRui Paulo 		// If LZMA_IGNORE_CHECK was used, this flag needs to be set.
21353200025SRui Paulo 		// It has to be set after lzma_block_header_decode() because
21453200025SRui Paulo 		// it always resets this to false.
21553200025SRui Paulo 		coder->block_options.ignore_check = coder->ignore_check;
21653200025SRui Paulo 
21781ad8388SMartin Matuska 		// Check the memory usage limit.
21881ad8388SMartin Matuska 		const uint64_t memusage = lzma_raw_decoder_memusage(filters);
21981ad8388SMartin Matuska 		lzma_ret ret;
22081ad8388SMartin Matuska 
22181ad8388SMartin Matuska 		if (memusage == UINT64_MAX) {
22281ad8388SMartin Matuska 			// One or more unknown Filter IDs.
22381ad8388SMartin Matuska 			ret = LZMA_OPTIONS_ERROR;
22481ad8388SMartin Matuska 		} else {
22581ad8388SMartin Matuska 			// Now we can set coder->memusage since we know that
22681ad8388SMartin Matuska 			// the filter chain is valid. We don't want
22781ad8388SMartin Matuska 			// lzma_memusage() to return UINT64_MAX in case of
22881ad8388SMartin Matuska 			// invalid filter chain.
22981ad8388SMartin Matuska 			coder->memusage = memusage;
23081ad8388SMartin Matuska 
23181ad8388SMartin Matuska 			if (memusage > coder->memlimit) {
23281ad8388SMartin Matuska 				// The chain would need too much memory.
23381ad8388SMartin Matuska 				ret = LZMA_MEMLIMIT_ERROR;
23481ad8388SMartin Matuska 			} else {
23581ad8388SMartin Matuska 				// Memory usage is OK.
23681ad8388SMartin Matuska 				// Initialize the Block decoder.
23781ad8388SMartin Matuska 				ret = lzma_block_decoder_init(
23881ad8388SMartin Matuska 						&coder->block_decoder,
23981ad8388SMartin Matuska 						allocator,
24081ad8388SMartin Matuska 						&coder->block_options);
24181ad8388SMartin Matuska 			}
24281ad8388SMartin Matuska 		}
24381ad8388SMartin Matuska 
24481ad8388SMartin Matuska 		// Free the allocated filter options since they are needed
24581ad8388SMartin Matuska 		// only to initialize the Block decoder.
24673ed8e77SXin LI 		lzma_filters_free(filters, allocator);
24781ad8388SMartin Matuska 		coder->block_options.filters = NULL;
24881ad8388SMartin Matuska 
2499e6bbe47SXin LI 		// Check if memory usage calculation and Block decoder
25081ad8388SMartin Matuska 		// initialization succeeded.
25181ad8388SMartin Matuska 		if (ret != LZMA_OK)
25281ad8388SMartin Matuska 			return ret;
25381ad8388SMartin Matuska 
2549e6bbe47SXin LI 		coder->sequence = SEQ_BLOCK_RUN;
25581ad8388SMartin Matuska 	}
25681ad8388SMartin Matuska 
25781ad8388SMartin Matuska 	// Fall through
25881ad8388SMartin Matuska 
2599e6bbe47SXin LI 	case SEQ_BLOCK_RUN: {
26081ad8388SMartin Matuska 		const lzma_ret ret = coder->block_decoder.code(
26181ad8388SMartin Matuska 				coder->block_decoder.coder, allocator,
26281ad8388SMartin Matuska 				in, in_pos, in_size, out, out_pos, out_size,
26381ad8388SMartin Matuska 				action);
26481ad8388SMartin Matuska 
26581ad8388SMartin Matuska 		if (ret != LZMA_STREAM_END)
26681ad8388SMartin Matuska 			return ret;
26781ad8388SMartin Matuska 
26881ad8388SMartin Matuska 		// Block decoded successfully. Add the new size pair to
26981ad8388SMartin Matuska 		// the Index hash.
27081ad8388SMartin Matuska 		return_if_error(lzma_index_hash_append(coder->index_hash,
27181ad8388SMartin Matuska 				lzma_block_unpadded_size(
27281ad8388SMartin Matuska 					&coder->block_options),
27381ad8388SMartin Matuska 				coder->block_options.uncompressed_size));
27481ad8388SMartin Matuska 
27581ad8388SMartin Matuska 		coder->sequence = SEQ_BLOCK_HEADER;
27681ad8388SMartin Matuska 		break;
27781ad8388SMartin Matuska 	}
27881ad8388SMartin Matuska 
27981ad8388SMartin Matuska 	case SEQ_INDEX: {
28081ad8388SMartin Matuska 		// If we don't have any input, don't call
28181ad8388SMartin Matuska 		// lzma_index_hash_decode() since it would return
28281ad8388SMartin Matuska 		// LZMA_BUF_ERROR, which we must not do here.
28381ad8388SMartin Matuska 		if (*in_pos >= in_size)
28481ad8388SMartin Matuska 			return LZMA_OK;
28581ad8388SMartin Matuska 
28681ad8388SMartin Matuska 		// Decode the Index and compare it to the hash calculated
28781ad8388SMartin Matuska 		// from the sizes of the Blocks (if any).
28881ad8388SMartin Matuska 		const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
28981ad8388SMartin Matuska 				in, in_pos, in_size);
29081ad8388SMartin Matuska 		if (ret != LZMA_STREAM_END)
29181ad8388SMartin Matuska 			return ret;
29281ad8388SMartin Matuska 
29381ad8388SMartin Matuska 		coder->sequence = SEQ_STREAM_FOOTER;
29481ad8388SMartin Matuska 	}
29581ad8388SMartin Matuska 
29681ad8388SMartin Matuska 	// Fall through
29781ad8388SMartin Matuska 
29881ad8388SMartin Matuska 	case SEQ_STREAM_FOOTER: {
29981ad8388SMartin Matuska 		// Copy the Stream Footer to the internal buffer.
30081ad8388SMartin Matuska 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
30181ad8388SMartin Matuska 				LZMA_STREAM_HEADER_SIZE);
30281ad8388SMartin Matuska 
30381ad8388SMartin Matuska 		// Return if we didn't get the whole Stream Footer yet.
30481ad8388SMartin Matuska 		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
30581ad8388SMartin Matuska 			return LZMA_OK;
30681ad8388SMartin Matuska 
30781ad8388SMartin Matuska 		coder->pos = 0;
30881ad8388SMartin Matuska 
30981ad8388SMartin Matuska 		// Decode the Stream Footer. The decoder gives
31081ad8388SMartin Matuska 		// LZMA_FORMAT_ERROR if the magic bytes don't match,
31181ad8388SMartin Matuska 		// so convert that return code to LZMA_DATA_ERROR.
31281ad8388SMartin Matuska 		lzma_stream_flags footer_flags;
31381ad8388SMartin Matuska 		const lzma_ret ret = lzma_stream_footer_decode(
31481ad8388SMartin Matuska 				&footer_flags, coder->buffer);
31581ad8388SMartin Matuska 		if (ret != LZMA_OK)
31681ad8388SMartin Matuska 			return ret == LZMA_FORMAT_ERROR
31781ad8388SMartin Matuska 					? LZMA_DATA_ERROR : ret;
31881ad8388SMartin Matuska 
31981ad8388SMartin Matuska 		// Check that Index Size stored in the Stream Footer matches
32081ad8388SMartin Matuska 		// the real size of the Index field.
32181ad8388SMartin Matuska 		if (lzma_index_hash_size(coder->index_hash)
32281ad8388SMartin Matuska 				!= footer_flags.backward_size)
32381ad8388SMartin Matuska 			return LZMA_DATA_ERROR;
32481ad8388SMartin Matuska 
32581ad8388SMartin Matuska 		// Compare that the Stream Flags fields are identical in
32681ad8388SMartin Matuska 		// both Stream Header and Stream Footer.
32781ad8388SMartin Matuska 		return_if_error(lzma_stream_flags_compare(
32881ad8388SMartin Matuska 				&coder->stream_flags, &footer_flags));
32981ad8388SMartin Matuska 
33081ad8388SMartin Matuska 		if (!coder->concatenated)
33181ad8388SMartin Matuska 			return LZMA_STREAM_END;
33281ad8388SMartin Matuska 
33381ad8388SMartin Matuska 		coder->sequence = SEQ_STREAM_PADDING;
33481ad8388SMartin Matuska 	}
33581ad8388SMartin Matuska 
33681ad8388SMartin Matuska 	// Fall through
33781ad8388SMartin Matuska 
33881ad8388SMartin Matuska 	case SEQ_STREAM_PADDING:
33981ad8388SMartin Matuska 		assert(coder->concatenated);
34081ad8388SMartin Matuska 
34181ad8388SMartin Matuska 		// Skip over possible Stream Padding.
34281ad8388SMartin Matuska 		while (true) {
34381ad8388SMartin Matuska 			if (*in_pos >= in_size) {
34481ad8388SMartin Matuska 				// Unless LZMA_FINISH was used, we cannot
34581ad8388SMartin Matuska 				// know if there's more input coming later.
34681ad8388SMartin Matuska 				if (action != LZMA_FINISH)
34781ad8388SMartin Matuska 					return LZMA_OK;
34881ad8388SMartin Matuska 
34981ad8388SMartin Matuska 				// Stream Padding must be a multiple of
35081ad8388SMartin Matuska 				// four bytes.
35181ad8388SMartin Matuska 				return coder->pos == 0
35281ad8388SMartin Matuska 						? LZMA_STREAM_END
35381ad8388SMartin Matuska 						: LZMA_DATA_ERROR;
35481ad8388SMartin Matuska 			}
35581ad8388SMartin Matuska 
35681ad8388SMartin Matuska 			// If the byte is not zero, it probably indicates
35781ad8388SMartin Matuska 			// beginning of a new Stream (or the file is corrupt).
35881ad8388SMartin Matuska 			if (in[*in_pos] != 0x00)
35981ad8388SMartin Matuska 				break;
36081ad8388SMartin Matuska 
36181ad8388SMartin Matuska 			++*in_pos;
36281ad8388SMartin Matuska 			coder->pos = (coder->pos + 1) & 3;
36381ad8388SMartin Matuska 		}
36481ad8388SMartin Matuska 
36581ad8388SMartin Matuska 		// Stream Padding must be a multiple of four bytes (empty
36681ad8388SMartin Matuska 		// Stream Padding is OK).
36781ad8388SMartin Matuska 		if (coder->pos != 0) {
36881ad8388SMartin Matuska 			++*in_pos;
36981ad8388SMartin Matuska 			return LZMA_DATA_ERROR;
37081ad8388SMartin Matuska 		}
37181ad8388SMartin Matuska 
37281ad8388SMartin Matuska 		// Prepare to decode the next Stream.
37381ad8388SMartin Matuska 		return_if_error(stream_decoder_reset(coder, allocator));
37481ad8388SMartin Matuska 		break;
37581ad8388SMartin Matuska 
37681ad8388SMartin Matuska 	default:
37781ad8388SMartin Matuska 		assert(0);
37881ad8388SMartin Matuska 		return LZMA_PROG_ERROR;
37981ad8388SMartin Matuska 	}
38081ad8388SMartin Matuska 
38181ad8388SMartin Matuska 	// Never reached
38281ad8388SMartin Matuska }
38381ad8388SMartin Matuska 
38481ad8388SMartin Matuska 
38581ad8388SMartin Matuska static void
3861456f0f9SXin LI stream_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
38781ad8388SMartin Matuska {
3881456f0f9SXin LI 	lzma_stream_coder *coder = coder_ptr;
38981ad8388SMartin Matuska 	lzma_next_end(&coder->block_decoder, allocator);
39081ad8388SMartin Matuska 	lzma_index_hash_end(coder->index_hash, allocator);
39181ad8388SMartin Matuska 	lzma_free(coder, allocator);
39281ad8388SMartin Matuska 	return;
39381ad8388SMartin Matuska }
39481ad8388SMartin Matuska 
39581ad8388SMartin Matuska 
39681ad8388SMartin Matuska static lzma_check
3971456f0f9SXin LI stream_decoder_get_check(const void *coder_ptr)
39881ad8388SMartin Matuska {
3991456f0f9SXin LI 	const lzma_stream_coder *coder = coder_ptr;
40081ad8388SMartin Matuska 	return coder->stream_flags.check;
40181ad8388SMartin Matuska }
40281ad8388SMartin Matuska 
40381ad8388SMartin Matuska 
40481ad8388SMartin Matuska static lzma_ret
4051456f0f9SXin LI stream_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
40681ad8388SMartin Matuska 		uint64_t *old_memlimit, uint64_t new_memlimit)
40781ad8388SMartin Matuska {
4081456f0f9SXin LI 	lzma_stream_coder *coder = coder_ptr;
4091456f0f9SXin LI 
41081ad8388SMartin Matuska 	*memusage = coder->memusage;
41181ad8388SMartin Matuska 	*old_memlimit = coder->memlimit;
41281ad8388SMartin Matuska 
41381ad8388SMartin Matuska 	if (new_memlimit != 0) {
41481ad8388SMartin Matuska 		if (new_memlimit < coder->memusage)
41581ad8388SMartin Matuska 			return LZMA_MEMLIMIT_ERROR;
41681ad8388SMartin Matuska 
41781ad8388SMartin Matuska 		coder->memlimit = new_memlimit;
41881ad8388SMartin Matuska 	}
41981ad8388SMartin Matuska 
42081ad8388SMartin Matuska 	return LZMA_OK;
42181ad8388SMartin Matuska }
42281ad8388SMartin Matuska 
42381ad8388SMartin Matuska 
42481ad8388SMartin Matuska extern lzma_ret
42553200025SRui Paulo lzma_stream_decoder_init(
42653200025SRui Paulo 		lzma_next_coder *next, const lzma_allocator *allocator,
42781ad8388SMartin Matuska 		uint64_t memlimit, uint32_t flags)
42881ad8388SMartin Matuska {
42981ad8388SMartin Matuska 	lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
43081ad8388SMartin Matuska 
43181ad8388SMartin Matuska 	if (flags & ~LZMA_SUPPORTED_FLAGS)
43281ad8388SMartin Matuska 		return LZMA_OPTIONS_ERROR;
43381ad8388SMartin Matuska 
4341456f0f9SXin LI 	lzma_stream_coder *coder = next->coder;
4351456f0f9SXin LI 	if (coder == NULL) {
4361456f0f9SXin LI 		coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
4371456f0f9SXin LI 		if (coder == NULL)
43881ad8388SMartin Matuska 			return LZMA_MEM_ERROR;
43981ad8388SMartin Matuska 
4401456f0f9SXin LI 		next->coder = coder;
44181ad8388SMartin Matuska 		next->code = &stream_decode;
44281ad8388SMartin Matuska 		next->end = &stream_decoder_end;
44381ad8388SMartin Matuska 		next->get_check = &stream_decoder_get_check;
44481ad8388SMartin Matuska 		next->memconfig = &stream_decoder_memconfig;
44581ad8388SMartin Matuska 
4461456f0f9SXin LI 		coder->block_decoder = LZMA_NEXT_CODER_INIT;
4471456f0f9SXin LI 		coder->index_hash = NULL;
44881ad8388SMartin Matuska 	}
44981ad8388SMartin Matuska 
450b71a5db3SXin LI 	coder->memlimit = my_max(1, memlimit);
4511456f0f9SXin LI 	coder->memusage = LZMA_MEMUSAGE_BASE;
4521456f0f9SXin LI 	coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
4531456f0f9SXin LI 	coder->tell_unsupported_check
45481ad8388SMartin Matuska 			= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
4551456f0f9SXin LI 	coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
4561456f0f9SXin LI 	coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
4571456f0f9SXin LI 	coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
4581456f0f9SXin LI 	coder->first_stream = true;
45981ad8388SMartin Matuska 
4601456f0f9SXin LI 	return stream_decoder_reset(coder, allocator);
46181ad8388SMartin Matuska }
46281ad8388SMartin Matuska 
46381ad8388SMartin Matuska 
46481ad8388SMartin Matuska extern LZMA_API(lzma_ret)
46581ad8388SMartin Matuska lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
46681ad8388SMartin Matuska {
46781ad8388SMartin Matuska 	lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
46881ad8388SMartin Matuska 
46981ad8388SMartin Matuska 	strm->internal->supported_actions[LZMA_RUN] = true;
47081ad8388SMartin Matuska 	strm->internal->supported_actions[LZMA_FINISH] = true;
47181ad8388SMartin Matuska 
47281ad8388SMartin Matuska 	return LZMA_OK;
47381ad8388SMartin Matuska }
474