xref: /freebsd/contrib/xz/src/liblzma/common/file_info.c (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
2*3b35e7eeSXin LI 
373ed8e77SXin LI ///////////////////////////////////////////////////////////////////////////////
473ed8e77SXin LI //
573ed8e77SXin LI /// \file       file_info.c
673ed8e77SXin LI /// \brief      Decode .xz file information into a lzma_index structure
773ed8e77SXin LI //
873ed8e77SXin LI //  Author:     Lasse Collin
973ed8e77SXin LI //
1073ed8e77SXin LI ///////////////////////////////////////////////////////////////////////////////
1173ed8e77SXin LI 
1273ed8e77SXin LI #include "index_decoder.h"
1373ed8e77SXin LI 
1473ed8e77SXin LI 
1573ed8e77SXin LI typedef struct {
1673ed8e77SXin LI 	enum {
1773ed8e77SXin LI 		SEQ_MAGIC_BYTES,
1873ed8e77SXin LI 		SEQ_PADDING_SEEK,
1973ed8e77SXin LI 		SEQ_PADDING_DECODE,
2073ed8e77SXin LI 		SEQ_FOOTER,
2173ed8e77SXin LI 		SEQ_INDEX_INIT,
2273ed8e77SXin LI 		SEQ_INDEX_DECODE,
2373ed8e77SXin LI 		SEQ_HEADER_DECODE,
2473ed8e77SXin LI 		SEQ_HEADER_COMPARE,
2573ed8e77SXin LI 	} sequence;
2673ed8e77SXin LI 
2773ed8e77SXin LI 	/// Absolute position of in[*in_pos] in the file. All code that
2873ed8e77SXin LI 	/// modifies *in_pos also updates this. seek_to_pos() needs this
2973ed8e77SXin LI 	/// to determine if we need to request the application to seek for
3073ed8e77SXin LI 	/// us or if we can do the seeking internally by adjusting *in_pos.
3173ed8e77SXin LI 	uint64_t file_cur_pos;
3273ed8e77SXin LI 
3373ed8e77SXin LI 	/// This refers to absolute positions of interesting parts of the
3473ed8e77SXin LI 	/// input file. Sometimes it points to the *beginning* of a specific
3573ed8e77SXin LI 	/// field and sometimes to the *end* of a field. The current target
3673ed8e77SXin LI 	/// position at each moment is explained in the comments.
3773ed8e77SXin LI 	uint64_t file_target_pos;
3873ed8e77SXin LI 
3973ed8e77SXin LI 	/// Size of the .xz file (from the application).
4073ed8e77SXin LI 	uint64_t file_size;
4173ed8e77SXin LI 
4273ed8e77SXin LI 	/// Index decoder
4373ed8e77SXin LI 	lzma_next_coder index_decoder;
4473ed8e77SXin LI 
4573ed8e77SXin LI 	/// Number of bytes remaining in the Index field that is currently
4673ed8e77SXin LI 	/// being decoded.
4773ed8e77SXin LI 	lzma_vli index_remaining;
4873ed8e77SXin LI 
4973ed8e77SXin LI 	/// The Index decoder will store the decoded Index in this pointer.
5073ed8e77SXin LI 	lzma_index *this_index;
5173ed8e77SXin LI 
5273ed8e77SXin LI 	/// Amount of Stream Padding in the current Stream.
5373ed8e77SXin LI 	lzma_vli stream_padding;
5473ed8e77SXin LI 
5573ed8e77SXin LI 	/// The final combined index is collected here.
5673ed8e77SXin LI 	lzma_index *combined_index;
5773ed8e77SXin LI 
5873ed8e77SXin LI 	/// Pointer from the application where to store the index information
5973ed8e77SXin LI 	/// after successful decoding.
6073ed8e77SXin LI 	lzma_index **dest_index;
6173ed8e77SXin LI 
6273ed8e77SXin LI 	/// Pointer to lzma_stream.seek_pos to be used when returning
6373ed8e77SXin LI 	/// LZMA_SEEK_NEEDED. This is set by seek_to_pos() when needed.
6473ed8e77SXin LI 	uint64_t *external_seek_pos;
6573ed8e77SXin LI 
6673ed8e77SXin LI 	/// Memory usage limit
6773ed8e77SXin LI 	uint64_t memlimit;
6873ed8e77SXin LI 
6973ed8e77SXin LI 	/// Stream Flags from the very beginning of the file.
7073ed8e77SXin LI 	lzma_stream_flags first_header_flags;
7173ed8e77SXin LI 
7273ed8e77SXin LI 	/// Stream Flags from Stream Header of the current Stream.
7373ed8e77SXin LI 	lzma_stream_flags header_flags;
7473ed8e77SXin LI 
7573ed8e77SXin LI 	/// Stream Flags from Stream Footer of the current Stream.
7673ed8e77SXin LI 	lzma_stream_flags footer_flags;
7773ed8e77SXin LI 
7873ed8e77SXin LI 	size_t temp_pos;
7973ed8e77SXin LI 	size_t temp_size;
8073ed8e77SXin LI 	uint8_t temp[8192];
8173ed8e77SXin LI 
8273ed8e77SXin LI } lzma_file_info_coder;
8373ed8e77SXin LI 
8473ed8e77SXin LI 
8573ed8e77SXin LI /// Copies data from in[*in_pos] into coder->temp until
8673ed8e77SXin LI /// coder->temp_pos == coder->temp_size. This also keeps coder->file_cur_pos
8773ed8e77SXin LI /// in sync with *in_pos. Returns true if more input is needed.
8873ed8e77SXin LI static bool
8973ed8e77SXin LI fill_temp(lzma_file_info_coder *coder, const uint8_t *restrict in,
9073ed8e77SXin LI 		size_t *restrict in_pos, size_t in_size)
9173ed8e77SXin LI {
9273ed8e77SXin LI 	coder->file_cur_pos += lzma_bufcpy(in, in_pos, in_size,
9373ed8e77SXin LI 			coder->temp, &coder->temp_pos, coder->temp_size);
9473ed8e77SXin LI 	return coder->temp_pos < coder->temp_size;
9573ed8e77SXin LI }
9673ed8e77SXin LI 
9773ed8e77SXin LI 
9873ed8e77SXin LI /// Seeks to the absolute file position specified by target_pos.
9973ed8e77SXin LI /// This tries to do the seeking by only modifying *in_pos, if possible.
10073ed8e77SXin LI /// The main benefit of this is that if one passes the whole file at once
10173ed8e77SXin LI /// to lzma_code(), the decoder will never need to return LZMA_SEEK_NEEDED
10273ed8e77SXin LI /// as all the seeking can be done by adjusting *in_pos in this function.
10373ed8e77SXin LI ///
10473ed8e77SXin LI /// Returns true if an external seek is needed and the caller must return
10573ed8e77SXin LI /// LZMA_SEEK_NEEDED.
10673ed8e77SXin LI static bool
10773ed8e77SXin LI seek_to_pos(lzma_file_info_coder *coder, uint64_t target_pos,
10873ed8e77SXin LI 		size_t in_start, size_t *in_pos, size_t in_size)
10973ed8e77SXin LI {
11073ed8e77SXin LI 	// The input buffer doesn't extend beyond the end of the file.
11173ed8e77SXin LI 	// This has been checked by file_info_decode() already.
11273ed8e77SXin LI 	assert(coder->file_size - coder->file_cur_pos >= in_size - *in_pos);
11373ed8e77SXin LI 
11473ed8e77SXin LI 	const uint64_t pos_min = coder->file_cur_pos - (*in_pos - in_start);
11573ed8e77SXin LI 	const uint64_t pos_max = coder->file_cur_pos + (in_size - *in_pos);
11673ed8e77SXin LI 
11773ed8e77SXin LI 	bool external_seek_needed;
11873ed8e77SXin LI 
11973ed8e77SXin LI 	if (target_pos >= pos_min && target_pos <= pos_max) {
12073ed8e77SXin LI 		// The requested position is available in the current input
12173ed8e77SXin LI 		// buffer or right after it. That is, in a corner case we
12273ed8e77SXin LI 		// end up setting *in_pos == in_size and thus will immediately
12373ed8e77SXin LI 		// need new input bytes from the application.
12473ed8e77SXin LI 		*in_pos += (size_t)(target_pos - coder->file_cur_pos);
12573ed8e77SXin LI 		external_seek_needed = false;
12673ed8e77SXin LI 	} else {
12773ed8e77SXin LI 		// Ask the application to seek the input file.
12873ed8e77SXin LI 		*coder->external_seek_pos = target_pos;
12973ed8e77SXin LI 		external_seek_needed = true;
13073ed8e77SXin LI 
13173ed8e77SXin LI 		// Mark the whole input buffer as used. This way
13273ed8e77SXin LI 		// lzma_stream.total_in will have a better estimate
13373ed8e77SXin LI 		// of the amount of data read. It still won't be perfect
13473ed8e77SXin LI 		// as the value will depend on the input buffer size that
13573ed8e77SXin LI 		// the application uses, but it should be good enough for
13673ed8e77SXin LI 		// those few who want an estimate.
13773ed8e77SXin LI 		*in_pos = in_size;
13873ed8e77SXin LI 	}
13973ed8e77SXin LI 
14073ed8e77SXin LI 	// After seeking (internal or external) the current position
14173ed8e77SXin LI 	// will match the requested target position.
14273ed8e77SXin LI 	coder->file_cur_pos = target_pos;
14373ed8e77SXin LI 
14473ed8e77SXin LI 	return external_seek_needed;
14573ed8e77SXin LI }
14673ed8e77SXin LI 
14773ed8e77SXin LI 
14873ed8e77SXin LI /// The caller sets coder->file_target_pos so that it points to the *end*
14973ed8e77SXin LI /// of the desired file position. This function then determines how far
15073ed8e77SXin LI /// backwards from that position we can seek. After seeking fill_temp()
15173ed8e77SXin LI /// can be used to read data into coder->temp. When fill_temp() has finished,
15273ed8e77SXin LI /// coder->temp[coder->temp_size] will match coder->file_target_pos.
15373ed8e77SXin LI ///
15473ed8e77SXin LI /// This also validates that coder->target_file_pos is sane in sense that
15573ed8e77SXin LI /// we aren't trying to seek too far backwards (too close or beyond the
15673ed8e77SXin LI /// beginning of the file).
15773ed8e77SXin LI static lzma_ret
15873ed8e77SXin LI reverse_seek(lzma_file_info_coder *coder,
15973ed8e77SXin LI 		size_t in_start, size_t *in_pos, size_t in_size)
16073ed8e77SXin LI {
16173ed8e77SXin LI 	// Check that there is enough data before the target position
16273ed8e77SXin LI 	// to contain at least Stream Header and Stream Footer. If there
16373ed8e77SXin LI 	// isn't, the file cannot be valid.
16473ed8e77SXin LI 	if (coder->file_target_pos < 2 * LZMA_STREAM_HEADER_SIZE)
16573ed8e77SXin LI 		return LZMA_DATA_ERROR;
16673ed8e77SXin LI 
16773ed8e77SXin LI 	coder->temp_pos = 0;
16873ed8e77SXin LI 
16973ed8e77SXin LI 	// The Stream Header at the very beginning of the file gets handled
17073ed8e77SXin LI 	// specially in SEQ_MAGIC_BYTES and thus we will never need to seek
17173ed8e77SXin LI 	// there. By not seeking to the first LZMA_STREAM_HEADER_SIZE bytes
17273ed8e77SXin LI 	// we avoid a useless external seek after SEQ_MAGIC_BYTES if the
17373ed8e77SXin LI 	// application uses an extremely small input buffer and the input
17473ed8e77SXin LI 	// file is very small.
17573ed8e77SXin LI 	if (coder->file_target_pos - LZMA_STREAM_HEADER_SIZE
17673ed8e77SXin LI 			< sizeof(coder->temp))
17773ed8e77SXin LI 		coder->temp_size = (size_t)(coder->file_target_pos
17873ed8e77SXin LI 				- LZMA_STREAM_HEADER_SIZE);
17973ed8e77SXin LI 	else
18073ed8e77SXin LI 		coder->temp_size = sizeof(coder->temp);
18173ed8e77SXin LI 
18273ed8e77SXin LI 	// The above if-statements guarantee this. This is important because
18373ed8e77SXin LI 	// the Stream Header/Footer decoders assume that there's at least
18473ed8e77SXin LI 	// LZMA_STREAM_HEADER_SIZE bytes in coder->temp.
18573ed8e77SXin LI 	assert(coder->temp_size >= LZMA_STREAM_HEADER_SIZE);
18673ed8e77SXin LI 
18773ed8e77SXin LI 	if (seek_to_pos(coder, coder->file_target_pos - coder->temp_size,
18873ed8e77SXin LI 			in_start, in_pos, in_size))
18973ed8e77SXin LI 		return LZMA_SEEK_NEEDED;
19073ed8e77SXin LI 
19173ed8e77SXin LI 	return LZMA_OK;
19273ed8e77SXin LI }
19373ed8e77SXin LI 
19473ed8e77SXin LI 
19573ed8e77SXin LI /// Gets the number of zero-bytes at the end of the buffer.
19673ed8e77SXin LI static size_t
19773ed8e77SXin LI get_padding_size(const uint8_t *buf, size_t buf_size)
19873ed8e77SXin LI {
19973ed8e77SXin LI 	size_t padding = 0;
20073ed8e77SXin LI 	while (buf_size > 0 && buf[--buf_size] == 0x00)
20173ed8e77SXin LI 		++padding;
20273ed8e77SXin LI 
20373ed8e77SXin LI 	return padding;
20473ed8e77SXin LI }
20573ed8e77SXin LI 
20673ed8e77SXin LI 
20773ed8e77SXin LI /// With the Stream Header at the very beginning of the file, LZMA_FORMAT_ERROR
20873ed8e77SXin LI /// is used to tell the application that Magic Bytes didn't match. In other
20973ed8e77SXin LI /// Stream Header/Footer fields (in the middle/end of the file) it could be
21073ed8e77SXin LI /// a bit confusing to return LZMA_FORMAT_ERROR as we already know that there
21173ed8e77SXin LI /// is a valid Stream Header at the beginning of the file. For those cases
21273ed8e77SXin LI /// this function is used to convert LZMA_FORMAT_ERROR to LZMA_DATA_ERROR.
21373ed8e77SXin LI static lzma_ret
21473ed8e77SXin LI hide_format_error(lzma_ret ret)
21573ed8e77SXin LI {
21673ed8e77SXin LI 	if (ret == LZMA_FORMAT_ERROR)
21773ed8e77SXin LI 		ret = LZMA_DATA_ERROR;
21873ed8e77SXin LI 
21973ed8e77SXin LI 	return ret;
22073ed8e77SXin LI }
22173ed8e77SXin LI 
22273ed8e77SXin LI 
22373ed8e77SXin LI /// Calls the Index decoder and updates coder->index_remaining.
22473ed8e77SXin LI /// This is a separate function because the input can be either directly
22573ed8e77SXin LI /// from the application or from coder->temp.
22673ed8e77SXin LI static lzma_ret
22773ed8e77SXin LI decode_index(lzma_file_info_coder *coder, const lzma_allocator *allocator,
22873ed8e77SXin LI 		const uint8_t *restrict in, size_t *restrict in_pos,
22973ed8e77SXin LI 		size_t in_size, bool update_file_cur_pos)
23073ed8e77SXin LI {
23173ed8e77SXin LI 	const size_t in_start = *in_pos;
23273ed8e77SXin LI 
23373ed8e77SXin LI 	const lzma_ret ret = coder->index_decoder.code(
23473ed8e77SXin LI 			coder->index_decoder.coder,
23573ed8e77SXin LI 			allocator, in, in_pos, in_size,
23673ed8e77SXin LI 			NULL, NULL, 0, LZMA_RUN);
23773ed8e77SXin LI 
23873ed8e77SXin LI 	coder->index_remaining -= *in_pos - in_start;
23973ed8e77SXin LI 
24073ed8e77SXin LI 	if (update_file_cur_pos)
24173ed8e77SXin LI 		coder->file_cur_pos += *in_pos - in_start;
24273ed8e77SXin LI 
24373ed8e77SXin LI 	return ret;
24473ed8e77SXin LI }
24573ed8e77SXin LI 
24673ed8e77SXin LI 
24773ed8e77SXin LI static lzma_ret
24873ed8e77SXin LI file_info_decode(void *coder_ptr, const lzma_allocator *allocator,
24973ed8e77SXin LI 		const uint8_t *restrict in, size_t *restrict in_pos,
25073ed8e77SXin LI 		size_t in_size,
25173ed8e77SXin LI 		uint8_t *restrict out lzma_attribute((__unused__)),
25273ed8e77SXin LI 		size_t *restrict out_pos lzma_attribute((__unused__)),
25373ed8e77SXin LI 		size_t out_size lzma_attribute((__unused__)),
25473ed8e77SXin LI 		lzma_action action lzma_attribute((__unused__)))
25573ed8e77SXin LI {
25673ed8e77SXin LI 	lzma_file_info_coder *coder = coder_ptr;
25773ed8e77SXin LI 	const size_t in_start = *in_pos;
25873ed8e77SXin LI 
25973ed8e77SXin LI 	// If the caller provides input past the end of the file, trim
26073ed8e77SXin LI 	// the extra bytes from the buffer so that we won't read too far.
26173ed8e77SXin LI 	assert(coder->file_size >= coder->file_cur_pos);
26273ed8e77SXin LI 	if (coder->file_size - coder->file_cur_pos < in_size - in_start)
26373ed8e77SXin LI 		in_size = in_start
26473ed8e77SXin LI 			+ (size_t)(coder->file_size - coder->file_cur_pos);
26573ed8e77SXin LI 
26673ed8e77SXin LI 	while (true)
26773ed8e77SXin LI 	switch (coder->sequence) {
26873ed8e77SXin LI 	case SEQ_MAGIC_BYTES:
26973ed8e77SXin LI 		// Decode the Stream Header at the beginning of the file
27073ed8e77SXin LI 		// first to check if the Magic Bytes match. The flags
27173ed8e77SXin LI 		// are stored in coder->first_header_flags so that we
27273ed8e77SXin LI 		// don't need to seek to it again.
27373ed8e77SXin LI 		//
27473ed8e77SXin LI 		// Check that the file is big enough to contain at least
27573ed8e77SXin LI 		// Stream Header.
27673ed8e77SXin LI 		if (coder->file_size < LZMA_STREAM_HEADER_SIZE)
27773ed8e77SXin LI 			return LZMA_FORMAT_ERROR;
27873ed8e77SXin LI 
27973ed8e77SXin LI 		// Read the Stream Header field into coder->temp.
28073ed8e77SXin LI 		if (fill_temp(coder, in, in_pos, in_size))
28173ed8e77SXin LI 			return LZMA_OK;
28273ed8e77SXin LI 
28373ed8e77SXin LI 		// This is the only Stream Header/Footer decoding where we
28473ed8e77SXin LI 		// want to return LZMA_FORMAT_ERROR if the Magic Bytes don't
28573ed8e77SXin LI 		// match. Elsewhere it will be converted to LZMA_DATA_ERROR.
28673ed8e77SXin LI 		return_if_error(lzma_stream_header_decode(
28773ed8e77SXin LI 				&coder->first_header_flags, coder->temp));
28873ed8e77SXin LI 
28973ed8e77SXin LI 		// Now that we know that the Magic Bytes match, check the
29073ed8e77SXin LI 		// file size. It's better to do this here after checking the
29173ed8e77SXin LI 		// Magic Bytes since this way we can give LZMA_FORMAT_ERROR
29273ed8e77SXin LI 		// instead of LZMA_DATA_ERROR when the Magic Bytes don't
29373ed8e77SXin LI 		// match in a file that is too big or isn't a multiple of
29473ed8e77SXin LI 		// four bytes.
29573ed8e77SXin LI 		if (coder->file_size > LZMA_VLI_MAX || (coder->file_size & 3))
29673ed8e77SXin LI 			return LZMA_DATA_ERROR;
29773ed8e77SXin LI 
29873ed8e77SXin LI 		// Start looking for Stream Padding and Stream Footer
29973ed8e77SXin LI 		// at the end of the file.
30073ed8e77SXin LI 		coder->file_target_pos = coder->file_size;
30173ed8e77SXin LI 
30273ed8e77SXin LI 	// Fall through
30373ed8e77SXin LI 
30473ed8e77SXin LI 	case SEQ_PADDING_SEEK:
30573ed8e77SXin LI 		coder->sequence = SEQ_PADDING_DECODE;
30673ed8e77SXin LI 		return_if_error(reverse_seek(
30773ed8e77SXin LI 				coder, in_start, in_pos, in_size));
30873ed8e77SXin LI 
30973ed8e77SXin LI 	// Fall through
31073ed8e77SXin LI 
31173ed8e77SXin LI 	case SEQ_PADDING_DECODE: {
31273ed8e77SXin LI 		// Copy to coder->temp first. This keeps the code simpler if
31373ed8e77SXin LI 		// the application only provides input a few bytes at a time.
31473ed8e77SXin LI 		if (fill_temp(coder, in, in_pos, in_size))
31573ed8e77SXin LI 			return LZMA_OK;
31673ed8e77SXin LI 
31773ed8e77SXin LI 		// Scan the buffer backwards to get the size of the
31873ed8e77SXin LI 		// Stream Padding field (if any).
31973ed8e77SXin LI 		const size_t new_padding = get_padding_size(
32073ed8e77SXin LI 				coder->temp, coder->temp_size);
32173ed8e77SXin LI 		coder->stream_padding += new_padding;
32273ed8e77SXin LI 
32373ed8e77SXin LI 		// Set the target position to the beginning of Stream Padding
32473ed8e77SXin LI 		// that has been observed so far. If all Stream Padding has
32573ed8e77SXin LI 		// been seen, then the target position will be at the end
32673ed8e77SXin LI 		// of the Stream Footer field.
32773ed8e77SXin LI 		coder->file_target_pos -= new_padding;
32873ed8e77SXin LI 
32973ed8e77SXin LI 		if (new_padding == coder->temp_size) {
33073ed8e77SXin LI 			// The whole buffer was padding. Seek backwards in
33173ed8e77SXin LI 			// the file to get more input.
33273ed8e77SXin LI 			coder->sequence = SEQ_PADDING_SEEK;
33373ed8e77SXin LI 			break;
33473ed8e77SXin LI 		}
33573ed8e77SXin LI 
33673ed8e77SXin LI 		// Size of Stream Padding must be a multiple of 4 bytes.
33773ed8e77SXin LI 		if (coder->stream_padding & 3)
33873ed8e77SXin LI 			return LZMA_DATA_ERROR;
33973ed8e77SXin LI 
34073ed8e77SXin LI 		coder->sequence = SEQ_FOOTER;
34173ed8e77SXin LI 
34273ed8e77SXin LI 		// Calculate the amount of non-padding data in coder->temp.
34373ed8e77SXin LI 		coder->temp_size -= new_padding;
34473ed8e77SXin LI 		coder->temp_pos = coder->temp_size;
34573ed8e77SXin LI 
34673ed8e77SXin LI 		// We can avoid an external seek if the whole Stream Footer
34773ed8e77SXin LI 		// is already in coder->temp. In that case SEQ_FOOTER won't
34873ed8e77SXin LI 		// read more input and will find the Stream Footer from
34973ed8e77SXin LI 		// coder->temp[coder->temp_size - LZMA_STREAM_HEADER_SIZE].
35073ed8e77SXin LI 		//
35173ed8e77SXin LI 		// Otherwise we will need to seek. The seeking is done so
3521f3ced26SXin LI 		// that Stream Footer will be at the end of coder->temp.
35373ed8e77SXin LI 		// This way it's likely that we also get a complete Index
35473ed8e77SXin LI 		// field into coder->temp without needing a separate seek
35573ed8e77SXin LI 		// for that (unless the Index field is big).
35673ed8e77SXin LI 		if (coder->temp_size < LZMA_STREAM_HEADER_SIZE)
35773ed8e77SXin LI 			return_if_error(reverse_seek(
35873ed8e77SXin LI 					coder, in_start, in_pos, in_size));
35973ed8e77SXin LI 	}
36073ed8e77SXin LI 
36173ed8e77SXin LI 	// Fall through
36273ed8e77SXin LI 
36373ed8e77SXin LI 	case SEQ_FOOTER:
36473ed8e77SXin LI 		// Copy the Stream Footer field into coder->temp.
36573ed8e77SXin LI 		// If Stream Footer was already available in coder->temp
36673ed8e77SXin LI 		// in SEQ_PADDING_DECODE, then this does nothing.
36773ed8e77SXin LI 		if (fill_temp(coder, in, in_pos, in_size))
36873ed8e77SXin LI 			return LZMA_OK;
36973ed8e77SXin LI 
37073ed8e77SXin LI 		// Make coder->file_target_pos and coder->temp_size point
37173ed8e77SXin LI 		// to the beginning of Stream Footer and thus to the end
37273ed8e77SXin LI 		// of the Index field. coder->temp_pos will be updated
37373ed8e77SXin LI 		// a bit later.
37473ed8e77SXin LI 		coder->file_target_pos -= LZMA_STREAM_HEADER_SIZE;
37573ed8e77SXin LI 		coder->temp_size -= LZMA_STREAM_HEADER_SIZE;
37673ed8e77SXin LI 
37773ed8e77SXin LI 		// Decode Stream Footer.
37873ed8e77SXin LI 		return_if_error(hide_format_error(lzma_stream_footer_decode(
37973ed8e77SXin LI 				&coder->footer_flags,
38073ed8e77SXin LI 				coder->temp + coder->temp_size)));
38173ed8e77SXin LI 
38273ed8e77SXin LI 		// Check that we won't seek past the beginning of the file.
38373ed8e77SXin LI 		//
38473ed8e77SXin LI 		// LZMA_STREAM_HEADER_SIZE is added because there must be
38573ed8e77SXin LI 		// space for Stream Header too even though we won't seek
38673ed8e77SXin LI 		// there before decoding the Index field.
38773ed8e77SXin LI 		//
38873ed8e77SXin LI 		// There's no risk of integer overflow here because
38973ed8e77SXin LI 		// Backward Size cannot be greater than 2^34.
39073ed8e77SXin LI 		if (coder->file_target_pos < coder->footer_flags.backward_size
39173ed8e77SXin LI 				+ LZMA_STREAM_HEADER_SIZE)
39273ed8e77SXin LI 			return LZMA_DATA_ERROR;
39373ed8e77SXin LI 
39473ed8e77SXin LI 		// Set the target position to the beginning of the Index field.
39573ed8e77SXin LI 		coder->file_target_pos -= coder->footer_flags.backward_size;
39673ed8e77SXin LI 		coder->sequence = SEQ_INDEX_INIT;
39773ed8e77SXin LI 
39873ed8e77SXin LI 		// We can avoid an external seek if the whole Index field is
39973ed8e77SXin LI 		// already available in coder->temp.
40073ed8e77SXin LI 		if (coder->temp_size >= coder->footer_flags.backward_size) {
40173ed8e77SXin LI 			// Set coder->temp_pos to point to the beginning
40273ed8e77SXin LI 			// of the Index.
40373ed8e77SXin LI 			coder->temp_pos = coder->temp_size
40473ed8e77SXin LI 					- coder->footer_flags.backward_size;
40573ed8e77SXin LI 		} else {
40673ed8e77SXin LI 			// These are set to zero to indicate that there's no
40773ed8e77SXin LI 			// useful data (Index or anything else) in coder->temp.
40873ed8e77SXin LI 			coder->temp_pos = 0;
40973ed8e77SXin LI 			coder->temp_size = 0;
41073ed8e77SXin LI 
41173ed8e77SXin LI 			// Seek to the beginning of the Index field.
41273ed8e77SXin LI 			if (seek_to_pos(coder, coder->file_target_pos,
41373ed8e77SXin LI 					in_start, in_pos, in_size))
41473ed8e77SXin LI 				return LZMA_SEEK_NEEDED;
41573ed8e77SXin LI 		}
41673ed8e77SXin LI 
41773ed8e77SXin LI 	// Fall through
41873ed8e77SXin LI 
41973ed8e77SXin LI 	case SEQ_INDEX_INIT: {
42073ed8e77SXin LI 		// Calculate the amount of memory already used by the earlier
42173ed8e77SXin LI 		// Indexes so that we know how big memory limit to pass to
42273ed8e77SXin LI 		// the Index decoder.
42373ed8e77SXin LI 		//
42473ed8e77SXin LI 		// NOTE: When there are multiple Streams, the separate
42573ed8e77SXin LI 		// lzma_index structures can use more RAM (as measured by
42673ed8e77SXin LI 		// lzma_index_memused()) than the final combined lzma_index.
42773ed8e77SXin LI 		// Thus memlimit may need to be slightly higher than the final
42873ed8e77SXin LI 		// calculated memory usage will be. This is perhaps a bit
42973ed8e77SXin LI 		// confusing to the application, but I think it shouldn't
43073ed8e77SXin LI 		// cause problems in practice.
43173ed8e77SXin LI 		uint64_t memused = 0;
43273ed8e77SXin LI 		if (coder->combined_index != NULL) {
43373ed8e77SXin LI 			memused = lzma_index_memused(coder->combined_index);
43473ed8e77SXin LI 			assert(memused <= coder->memlimit);
43573ed8e77SXin LI 			if (memused > coder->memlimit) // Extra sanity check
43673ed8e77SXin LI 				return LZMA_PROG_ERROR;
43773ed8e77SXin LI 		}
43873ed8e77SXin LI 
43973ed8e77SXin LI 		// Initialize the Index decoder.
44073ed8e77SXin LI 		return_if_error(lzma_index_decoder_init(
44173ed8e77SXin LI 				&coder->index_decoder, allocator,
44273ed8e77SXin LI 				&coder->this_index,
44373ed8e77SXin LI 				coder->memlimit - memused));
44473ed8e77SXin LI 
44573ed8e77SXin LI 		coder->index_remaining = coder->footer_flags.backward_size;
44673ed8e77SXin LI 		coder->sequence = SEQ_INDEX_DECODE;
44773ed8e77SXin LI 	}
44873ed8e77SXin LI 
44973ed8e77SXin LI 	// Fall through
45073ed8e77SXin LI 
45173ed8e77SXin LI 	case SEQ_INDEX_DECODE: {
45273ed8e77SXin LI 		// Decode (a part of) the Index. If the whole Index is already
45373ed8e77SXin LI 		// in coder->temp, read it from there. Otherwise read from
45473ed8e77SXin LI 		// in[*in_pos] onwards. Note that index_decode() updates
45573ed8e77SXin LI 		// coder->index_remaining and optionally coder->file_cur_pos.
45673ed8e77SXin LI 		lzma_ret ret;
45773ed8e77SXin LI 		if (coder->temp_size != 0) {
45873ed8e77SXin LI 			assert(coder->temp_size - coder->temp_pos
45973ed8e77SXin LI 					== coder->index_remaining);
46073ed8e77SXin LI 			ret = decode_index(coder, allocator, coder->temp,
46173ed8e77SXin LI 					&coder->temp_pos, coder->temp_size,
46273ed8e77SXin LI 					false);
46373ed8e77SXin LI 		} else {
46473ed8e77SXin LI 			// Don't give the decoder more input than the known
46573ed8e77SXin LI 			// remaining size of the Index field.
46673ed8e77SXin LI 			size_t in_stop = in_size;
46773ed8e77SXin LI 			if (in_size - *in_pos > coder->index_remaining)
46873ed8e77SXin LI 				in_stop = *in_pos
46973ed8e77SXin LI 					+ (size_t)(coder->index_remaining);
47073ed8e77SXin LI 
47173ed8e77SXin LI 			ret = decode_index(coder, allocator,
47273ed8e77SXin LI 					in, in_pos, in_stop, true);
47373ed8e77SXin LI 		}
47473ed8e77SXin LI 
47573ed8e77SXin LI 		switch (ret) {
47673ed8e77SXin LI 		case LZMA_OK:
47773ed8e77SXin LI 			// If the Index docoder asks for more input when we
47873ed8e77SXin LI 			// have already given it as much input as Backward Size
47973ed8e77SXin LI 			// indicated, the file is invalid.
48073ed8e77SXin LI 			if (coder->index_remaining == 0)
48173ed8e77SXin LI 				return LZMA_DATA_ERROR;
48273ed8e77SXin LI 
48373ed8e77SXin LI 			// We cannot get here if we were reading Index from
48473ed8e77SXin LI 			// coder->temp because when reading from coder->temp
48573ed8e77SXin LI 			// we give the Index decoder exactly
48673ed8e77SXin LI 			// coder->index_remaining bytes of input.
48773ed8e77SXin LI 			assert(coder->temp_size == 0);
48873ed8e77SXin LI 
48973ed8e77SXin LI 			return LZMA_OK;
49073ed8e77SXin LI 
49173ed8e77SXin LI 		case LZMA_STREAM_END:
49273ed8e77SXin LI 			// If the decoding seems to be successful, check also
49373ed8e77SXin LI 			// that the Index decoder consumed as much input as
49473ed8e77SXin LI 			// indicated by the Backward Size field.
49573ed8e77SXin LI 			if (coder->index_remaining != 0)
49673ed8e77SXin LI 				return LZMA_DATA_ERROR;
49773ed8e77SXin LI 
49873ed8e77SXin LI 			break;
49973ed8e77SXin LI 
50073ed8e77SXin LI 		default:
50173ed8e77SXin LI 			return ret;
50273ed8e77SXin LI 		}
50373ed8e77SXin LI 
50473ed8e77SXin LI 		// Calculate how much the Index tells us to seek backwards
50573ed8e77SXin LI 		// (relative to the beginning of the Index): Total size of
50673ed8e77SXin LI 		// all Blocks plus the size of the Stream Header field.
50773ed8e77SXin LI 		// No integer overflow here because lzma_index_total_size()
50873ed8e77SXin LI 		// cannot return a value greater than LZMA_VLI_MAX.
50973ed8e77SXin LI 		const uint64_t seek_amount
51073ed8e77SXin LI 				= lzma_index_total_size(coder->this_index)
51173ed8e77SXin LI 					+ LZMA_STREAM_HEADER_SIZE;
51273ed8e77SXin LI 
51373ed8e77SXin LI 		// Check that Index is sane in sense that seek_amount won't
51473ed8e77SXin LI 		// make us seek past the beginning of the file when locating
51573ed8e77SXin LI 		// the Stream Header.
51673ed8e77SXin LI 		//
51773ed8e77SXin LI 		// coder->file_target_pos still points to the beginning of
51873ed8e77SXin LI 		// the Index field.
51973ed8e77SXin LI 		if (coder->file_target_pos < seek_amount)
52073ed8e77SXin LI 			return LZMA_DATA_ERROR;
52173ed8e77SXin LI 
52273ed8e77SXin LI 		// Set the target to the beginning of Stream Header.
52373ed8e77SXin LI 		coder->file_target_pos -= seek_amount;
52473ed8e77SXin LI 
52573ed8e77SXin LI 		if (coder->file_target_pos == 0) {
52673ed8e77SXin LI 			// We would seek to the beginning of the file, but
52773ed8e77SXin LI 			// since we already decoded that Stream Header in
52873ed8e77SXin LI 			// SEQ_MAGIC_BYTES, we can use the cached value from
52973ed8e77SXin LI 			// coder->first_header_flags to avoid the seek.
53073ed8e77SXin LI 			coder->header_flags = coder->first_header_flags;
53173ed8e77SXin LI 			coder->sequence = SEQ_HEADER_COMPARE;
53273ed8e77SXin LI 			break;
53373ed8e77SXin LI 		}
53473ed8e77SXin LI 
53573ed8e77SXin LI 		coder->sequence = SEQ_HEADER_DECODE;
53673ed8e77SXin LI 
53773ed8e77SXin LI 		// Make coder->file_target_pos point to the end of
53873ed8e77SXin LI 		// the Stream Header field.
53973ed8e77SXin LI 		coder->file_target_pos += LZMA_STREAM_HEADER_SIZE;
54073ed8e77SXin LI 
54173ed8e77SXin LI 		// If coder->temp_size is non-zero, it points to the end
54273ed8e77SXin LI 		// of the Index field. Then the beginning of the Index
54373ed8e77SXin LI 		// field is at coder->temp[coder->temp_size
54473ed8e77SXin LI 		// - coder->footer_flags.backward_size].
54573ed8e77SXin LI 		assert(coder->temp_size == 0 || coder->temp_size
54673ed8e77SXin LI 				>= coder->footer_flags.backward_size);
54773ed8e77SXin LI 
54873ed8e77SXin LI 		// If coder->temp contained the whole Index, see if it has
54973ed8e77SXin LI 		// enough data to contain also the Stream Header. If so,
55073ed8e77SXin LI 		// we avoid an external seek.
55173ed8e77SXin LI 		//
55273ed8e77SXin LI 		// NOTE: This can happen only with small .xz files and only
55373ed8e77SXin LI 		// for the non-first Stream as the Stream Flags of the first
55473ed8e77SXin LI 		// Stream are cached and already handled a few lines above.
55573ed8e77SXin LI 		// So this isn't as useful as the other seek-avoidance cases.
55673ed8e77SXin LI 		if (coder->temp_size != 0 && coder->temp_size
55773ed8e77SXin LI 				- coder->footer_flags.backward_size
55873ed8e77SXin LI 				>= seek_amount) {
55973ed8e77SXin LI 			// Make temp_pos and temp_size point to the *end* of
56073ed8e77SXin LI 			// Stream Header so that SEQ_HEADER_DECODE will find
56173ed8e77SXin LI 			// the start of Stream Header from coder->temp[
56273ed8e77SXin LI 			// coder->temp_size - LZMA_STREAM_HEADER_SIZE].
56373ed8e77SXin LI 			coder->temp_pos = coder->temp_size
56473ed8e77SXin LI 					- coder->footer_flags.backward_size
56573ed8e77SXin LI 					- seek_amount
56673ed8e77SXin LI 					+ LZMA_STREAM_HEADER_SIZE;
56773ed8e77SXin LI 			coder->temp_size = coder->temp_pos;
56873ed8e77SXin LI 		} else {
56973ed8e77SXin LI 			// Seek so that Stream Header will be at the end of
57073ed8e77SXin LI 			// coder->temp. With typical multi-Stream files we
57173ed8e77SXin LI 			// will usually also get the Stream Footer and Index
57273ed8e77SXin LI 			// of the *previous* Stream in coder->temp and thus
57373ed8e77SXin LI 			// won't need a separate seek for them.
57473ed8e77SXin LI 			return_if_error(reverse_seek(coder,
57573ed8e77SXin LI 					in_start, in_pos, in_size));
57673ed8e77SXin LI 		}
57773ed8e77SXin LI 	}
57873ed8e77SXin LI 
57973ed8e77SXin LI 	// Fall through
58073ed8e77SXin LI 
58173ed8e77SXin LI 	case SEQ_HEADER_DECODE:
58273ed8e77SXin LI 		// Copy the Stream Header field into coder->temp.
58373ed8e77SXin LI 		// If Stream Header was already available in coder->temp
58473ed8e77SXin LI 		// in SEQ_INDEX_DECODE, then this does nothing.
58573ed8e77SXin LI 		if (fill_temp(coder, in, in_pos, in_size))
58673ed8e77SXin LI 			return LZMA_OK;
58773ed8e77SXin LI 
58873ed8e77SXin LI 		// Make all these point to the beginning of Stream Header.
58973ed8e77SXin LI 		coder->file_target_pos -= LZMA_STREAM_HEADER_SIZE;
59073ed8e77SXin LI 		coder->temp_size -= LZMA_STREAM_HEADER_SIZE;
59173ed8e77SXin LI 		coder->temp_pos = coder->temp_size;
59273ed8e77SXin LI 
59373ed8e77SXin LI 		// Decode the Stream Header.
59473ed8e77SXin LI 		return_if_error(hide_format_error(lzma_stream_header_decode(
59573ed8e77SXin LI 				&coder->header_flags,
59673ed8e77SXin LI 				coder->temp + coder->temp_size)));
59773ed8e77SXin LI 
59873ed8e77SXin LI 		coder->sequence = SEQ_HEADER_COMPARE;
59973ed8e77SXin LI 
60073ed8e77SXin LI 	// Fall through
60173ed8e77SXin LI 
60273ed8e77SXin LI 	case SEQ_HEADER_COMPARE:
60373ed8e77SXin LI 		// Compare Stream Header against Stream Footer. They must
60473ed8e77SXin LI 		// match.
60573ed8e77SXin LI 		return_if_error(lzma_stream_flags_compare(
60673ed8e77SXin LI 				&coder->header_flags, &coder->footer_flags));
60773ed8e77SXin LI 
60873ed8e77SXin LI 		// Store the decoded Stream Flags into the Index. Use the
60973ed8e77SXin LI 		// Footer Flags because it contains Backward Size, although
61073ed8e77SXin LI 		// it shouldn't matter in practice.
61173ed8e77SXin LI 		if (lzma_index_stream_flags(coder->this_index,
61273ed8e77SXin LI 				&coder->footer_flags) != LZMA_OK)
61373ed8e77SXin LI 			return LZMA_PROG_ERROR;
61473ed8e77SXin LI 
61573ed8e77SXin LI 		// Store also the size of the Stream Padding field. It is
61673ed8e77SXin LI 		// needed to calculate the offsets of the Streams correctly.
61773ed8e77SXin LI 		if (lzma_index_stream_padding(coder->this_index,
61873ed8e77SXin LI 				coder->stream_padding) != LZMA_OK)
61973ed8e77SXin LI 			return LZMA_PROG_ERROR;
62073ed8e77SXin LI 
62173ed8e77SXin LI 		// Reset it so that it's ready for the next Stream.
62273ed8e77SXin LI 		coder->stream_padding = 0;
62373ed8e77SXin LI 
62473ed8e77SXin LI 		// Append the earlier decoded Indexes after this_index.
62573ed8e77SXin LI 		if (coder->combined_index != NULL)
62673ed8e77SXin LI 			return_if_error(lzma_index_cat(coder->this_index,
62773ed8e77SXin LI 					coder->combined_index, allocator));
62873ed8e77SXin LI 
62973ed8e77SXin LI 		coder->combined_index = coder->this_index;
63073ed8e77SXin LI 		coder->this_index = NULL;
63173ed8e77SXin LI 
63273ed8e77SXin LI 		// If the whole file was decoded, tell the caller that we
63373ed8e77SXin LI 		// are finished.
63473ed8e77SXin LI 		if (coder->file_target_pos == 0) {
63573ed8e77SXin LI 			// The combined index must indicate the same file
63673ed8e77SXin LI 			// size as was told to us at initialization.
63773ed8e77SXin LI 			assert(lzma_index_file_size(coder->combined_index)
63873ed8e77SXin LI 					== coder->file_size);
63973ed8e77SXin LI 
64073ed8e77SXin LI 			// Make the combined index available to
64173ed8e77SXin LI 			// the application.
64273ed8e77SXin LI 			*coder->dest_index = coder->combined_index;
64373ed8e77SXin LI 			coder->combined_index = NULL;
64473ed8e77SXin LI 
64573ed8e77SXin LI 			// Mark the input buffer as used since we may have
64673ed8e77SXin LI 			// done internal seeking and thus don't know how
64773ed8e77SXin LI 			// many input bytes were actually used. This way
64873ed8e77SXin LI 			// lzma_stream.total_in gets a slightly better
64973ed8e77SXin LI 			// estimate of the amount of input used.
65073ed8e77SXin LI 			*in_pos = in_size;
65173ed8e77SXin LI 			return LZMA_STREAM_END;
65273ed8e77SXin LI 		}
65373ed8e77SXin LI 
65473ed8e77SXin LI 		// We didn't hit the beginning of the file yet, so continue
65573ed8e77SXin LI 		// reading backwards in the file. If we have unprocessed
65673ed8e77SXin LI 		// data in coder->temp, use it before requesting more data
65773ed8e77SXin LI 		// from the application.
65873ed8e77SXin LI 		//
65973ed8e77SXin LI 		// coder->file_target_pos, coder->temp_size, and
66073ed8e77SXin LI 		// coder->temp_pos all point to the beginning of Stream Header
66173ed8e77SXin LI 		// and thus the end of the previous Stream in the file.
66273ed8e77SXin LI 		coder->sequence = coder->temp_size > 0
66373ed8e77SXin LI 				? SEQ_PADDING_DECODE : SEQ_PADDING_SEEK;
66473ed8e77SXin LI 		break;
66573ed8e77SXin LI 
66673ed8e77SXin LI 	default:
66773ed8e77SXin LI 		assert(0);
66873ed8e77SXin LI 		return LZMA_PROG_ERROR;
66973ed8e77SXin LI 	}
67073ed8e77SXin LI }
67173ed8e77SXin LI 
67273ed8e77SXin LI 
67373ed8e77SXin LI static lzma_ret
67473ed8e77SXin LI file_info_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
67573ed8e77SXin LI 		uint64_t *old_memlimit, uint64_t new_memlimit)
67673ed8e77SXin LI {
67773ed8e77SXin LI 	lzma_file_info_coder *coder = coder_ptr;
67873ed8e77SXin LI 
67973ed8e77SXin LI 	// The memory usage calculation comes from three things:
68073ed8e77SXin LI 	//
68173ed8e77SXin LI 	// (1) The Indexes that have already been decoded and processed into
68273ed8e77SXin LI 	//     coder->combined_index.
68373ed8e77SXin LI 	//
68473ed8e77SXin LI 	// (2) The latest Index in coder->this_index that has been decoded but
68573ed8e77SXin LI 	//     not yet put into coder->combined_index.
68673ed8e77SXin LI 	//
68773ed8e77SXin LI 	// (3) The latest Index that we have started decoding but haven't
68873ed8e77SXin LI 	//     finished and thus isn't available in coder->this_index yet.
68973ed8e77SXin LI 	//     Memory usage and limit information needs to be communicated
69073ed8e77SXin LI 	//     from/to coder->index_decoder.
69173ed8e77SXin LI 	//
69273ed8e77SXin LI 	// Care has to be taken to not do both (2) and (3) when calculating
69373ed8e77SXin LI 	// the memory usage.
69473ed8e77SXin LI 	uint64_t combined_index_memusage = 0;
69573ed8e77SXin LI 	uint64_t this_index_memusage = 0;
69673ed8e77SXin LI 
69773ed8e77SXin LI 	// (1) If we have already successfully decoded one or more Indexes,
69873ed8e77SXin LI 	// get their memory usage.
69973ed8e77SXin LI 	if (coder->combined_index != NULL)
70073ed8e77SXin LI 		combined_index_memusage = lzma_index_memused(
70173ed8e77SXin LI 				coder->combined_index);
70273ed8e77SXin LI 
70373ed8e77SXin LI 	// Choose between (2), (3), or neither.
70473ed8e77SXin LI 	if (coder->this_index != NULL) {
70573ed8e77SXin LI 		// (2) The latest Index is available. Use its memory usage.
70673ed8e77SXin LI 		this_index_memusage = lzma_index_memused(coder->this_index);
70773ed8e77SXin LI 
70873ed8e77SXin LI 	} else if (coder->sequence == SEQ_INDEX_DECODE) {
70973ed8e77SXin LI 		// (3) The Index decoder is activate and hasn't yet stored
71073ed8e77SXin LI 		// the new index in coder->this_index. Get the memory usage
71173ed8e77SXin LI 		// information from the Index decoder.
71273ed8e77SXin LI 		//
71373ed8e77SXin LI 		// NOTE: If the Index decoder doesn't yet know how much memory
71473ed8e77SXin LI 		// it will eventually need, it will return a tiny value here.
71573ed8e77SXin LI 		uint64_t dummy;
71673ed8e77SXin LI 		if (coder->index_decoder.memconfig(coder->index_decoder.coder,
71773ed8e77SXin LI 					&this_index_memusage, &dummy, 0)
71873ed8e77SXin LI 				!= LZMA_OK) {
71973ed8e77SXin LI 			assert(0);
72073ed8e77SXin LI 			return LZMA_PROG_ERROR;
72173ed8e77SXin LI 		}
72273ed8e77SXin LI 	}
72373ed8e77SXin LI 
72473ed8e77SXin LI 	// Now we know the total memory usage/requirement. If we had neither
72573ed8e77SXin LI 	// old Indexes nor a new Index, this will be zero which isn't
72673ed8e77SXin LI 	// acceptable as lzma_memusage() has to return non-zero on success
72773ed8e77SXin LI 	// and even with an empty .xz file we will end up with a lzma_index
72873ed8e77SXin LI 	// that takes some memory.
72973ed8e77SXin LI 	*memusage = combined_index_memusage + this_index_memusage;
73073ed8e77SXin LI 	if (*memusage == 0)
73173ed8e77SXin LI 		*memusage = lzma_index_memusage(1, 0);
73273ed8e77SXin LI 
73373ed8e77SXin LI 	*old_memlimit = coder->memlimit;
73473ed8e77SXin LI 
73573ed8e77SXin LI 	// If requested, set a new memory usage limit.
73673ed8e77SXin LI 	if (new_memlimit != 0) {
73773ed8e77SXin LI 		if (new_memlimit < *memusage)
73873ed8e77SXin LI 			return LZMA_MEMLIMIT_ERROR;
73973ed8e77SXin LI 
74073ed8e77SXin LI 		// In the condition (3) we need to tell the Index decoder
74173ed8e77SXin LI 		// its new memory usage limit.
74273ed8e77SXin LI 		if (coder->this_index == NULL
74373ed8e77SXin LI 				&& coder->sequence == SEQ_INDEX_DECODE) {
74473ed8e77SXin LI 			const uint64_t idec_new_memlimit = new_memlimit
74573ed8e77SXin LI 					- combined_index_memusage;
74673ed8e77SXin LI 
74773ed8e77SXin LI 			assert(this_index_memusage > 0);
74873ed8e77SXin LI 			assert(idec_new_memlimit > 0);
74973ed8e77SXin LI 
75073ed8e77SXin LI 			uint64_t dummy1;
75173ed8e77SXin LI 			uint64_t dummy2;
75273ed8e77SXin LI 
75373ed8e77SXin LI 			if (coder->index_decoder.memconfig(
75473ed8e77SXin LI 					coder->index_decoder.coder,
75573ed8e77SXin LI 					&dummy1, &dummy2, idec_new_memlimit)
75673ed8e77SXin LI 					!= LZMA_OK) {
75773ed8e77SXin LI 				assert(0);
75873ed8e77SXin LI 				return LZMA_PROG_ERROR;
75973ed8e77SXin LI 			}
76073ed8e77SXin LI 		}
76173ed8e77SXin LI 
76273ed8e77SXin LI 		coder->memlimit = new_memlimit;
76373ed8e77SXin LI 	}
76473ed8e77SXin LI 
76573ed8e77SXin LI 	return LZMA_OK;
76673ed8e77SXin LI }
76773ed8e77SXin LI 
76873ed8e77SXin LI 
76973ed8e77SXin LI static void
77073ed8e77SXin LI file_info_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
77173ed8e77SXin LI {
77273ed8e77SXin LI 	lzma_file_info_coder *coder = coder_ptr;
77373ed8e77SXin LI 
77473ed8e77SXin LI 	lzma_next_end(&coder->index_decoder, allocator);
77573ed8e77SXin LI 	lzma_index_end(coder->this_index, allocator);
77673ed8e77SXin LI 	lzma_index_end(coder->combined_index, allocator);
77773ed8e77SXin LI 
77873ed8e77SXin LI 	lzma_free(coder, allocator);
77973ed8e77SXin LI 	return;
78073ed8e77SXin LI }
78173ed8e77SXin LI 
78273ed8e77SXin LI 
78373ed8e77SXin LI static lzma_ret
78473ed8e77SXin LI lzma_file_info_decoder_init(lzma_next_coder *next,
78573ed8e77SXin LI 		const lzma_allocator *allocator, uint64_t *seek_pos,
78673ed8e77SXin LI 		lzma_index **dest_index,
78773ed8e77SXin LI 		uint64_t memlimit, uint64_t file_size)
78873ed8e77SXin LI {
78973ed8e77SXin LI 	lzma_next_coder_init(&lzma_file_info_decoder_init, next, allocator);
79073ed8e77SXin LI 
79173ed8e77SXin LI 	if (dest_index == NULL)
79273ed8e77SXin LI 		return LZMA_PROG_ERROR;
79373ed8e77SXin LI 
79473ed8e77SXin LI 	lzma_file_info_coder *coder = next->coder;
79573ed8e77SXin LI 	if (coder == NULL) {
79673ed8e77SXin LI 		coder = lzma_alloc(sizeof(lzma_file_info_coder), allocator);
79773ed8e77SXin LI 		if (coder == NULL)
79873ed8e77SXin LI 			return LZMA_MEM_ERROR;
79973ed8e77SXin LI 
80073ed8e77SXin LI 		next->coder = coder;
80173ed8e77SXin LI 		next->code = &file_info_decode;
80273ed8e77SXin LI 		next->end = &file_info_decoder_end;
80373ed8e77SXin LI 		next->memconfig = &file_info_decoder_memconfig;
80473ed8e77SXin LI 
80573ed8e77SXin LI 		coder->index_decoder = LZMA_NEXT_CODER_INIT;
80673ed8e77SXin LI 		coder->this_index = NULL;
80773ed8e77SXin LI 		coder->combined_index = NULL;
80873ed8e77SXin LI 	}
80973ed8e77SXin LI 
81073ed8e77SXin LI 	coder->sequence = SEQ_MAGIC_BYTES;
81173ed8e77SXin LI 	coder->file_cur_pos = 0;
81273ed8e77SXin LI 	coder->file_target_pos = 0;
81373ed8e77SXin LI 	coder->file_size = file_size;
81473ed8e77SXin LI 
81573ed8e77SXin LI 	lzma_index_end(coder->this_index, allocator);
81673ed8e77SXin LI 	coder->this_index = NULL;
81773ed8e77SXin LI 
81873ed8e77SXin LI 	lzma_index_end(coder->combined_index, allocator);
81973ed8e77SXin LI 	coder->combined_index = NULL;
82073ed8e77SXin LI 
82173ed8e77SXin LI 	coder->stream_padding = 0;
82273ed8e77SXin LI 
82373ed8e77SXin LI 	coder->dest_index = dest_index;
82473ed8e77SXin LI 	coder->external_seek_pos = seek_pos;
82573ed8e77SXin LI 
82673ed8e77SXin LI 	// If memlimit is 0, make it 1 to ensure that lzma_memlimit_get()
82773ed8e77SXin LI 	// won't return 0 (which would indicate an error).
82873ed8e77SXin LI 	coder->memlimit = my_max(1, memlimit);
82973ed8e77SXin LI 
83073ed8e77SXin LI 	// Prepare these for reading the first Stream Header into coder->temp.
83173ed8e77SXin LI 	coder->temp_pos = 0;
83273ed8e77SXin LI 	coder->temp_size = LZMA_STREAM_HEADER_SIZE;
83373ed8e77SXin LI 
83473ed8e77SXin LI 	return LZMA_OK;
83573ed8e77SXin LI }
83673ed8e77SXin LI 
83773ed8e77SXin LI 
83873ed8e77SXin LI extern LZMA_API(lzma_ret)
83973ed8e77SXin LI lzma_file_info_decoder(lzma_stream *strm, lzma_index **dest_index,
84073ed8e77SXin LI 		uint64_t memlimit, uint64_t file_size)
84173ed8e77SXin LI {
84273ed8e77SXin LI 	lzma_next_strm_init(lzma_file_info_decoder_init, strm, &strm->seek_pos,
84373ed8e77SXin LI 			dest_index, memlimit, file_size);
84473ed8e77SXin LI 
84573ed8e77SXin LI 	// We allow LZMA_FINISH in addition to LZMA_RUN for convenience.
84673ed8e77SXin LI 	// lzma_code() is able to handle the LZMA_FINISH + LZMA_SEEK_NEEDED
84773ed8e77SXin LI 	// combination in a sane way. Applications still need to be careful
84873ed8e77SXin LI 	// if they use LZMA_FINISH so that they remember to reset it back
84973ed8e77SXin LI 	// to LZMA_RUN after seeking if needed.
85073ed8e77SXin LI 	strm->internal->supported_actions[LZMA_RUN] = true;
85173ed8e77SXin LI 	strm->internal->supported_actions[LZMA_FINISH] = true;
85273ed8e77SXin LI 
85373ed8e77SXin LI 	return LZMA_OK;
85473ed8e77SXin LI }
855