1207753Smm///////////////////////////////////////////////////////////////////////////////
2207753Smm//
3207753Smm/// \file       alone_decoder.c
4207753Smm/// \brief      Decoder for LZMA_Alone files
5207753Smm//
6207753Smm//  Author:     Lasse Collin
7207753Smm//
8207753Smm//  This file has been put into the public domain.
9207753Smm//  You can do whatever you want with this file.
10207753Smm//
11207753Smm///////////////////////////////////////////////////////////////////////////////
12207753Smm
13207753Smm#include "alone_decoder.h"
14207753Smm#include "lzma_decoder.h"
15207753Smm#include "lz_decoder.h"
16207753Smm
17207753Smm
18312518Sdelphijtypedef struct {
19207753Smm	lzma_next_coder next;
20207753Smm
21207753Smm	enum {
22207753Smm		SEQ_PROPERTIES,
23207753Smm		SEQ_DICTIONARY_SIZE,
24207753Smm		SEQ_UNCOMPRESSED_SIZE,
25207753Smm		SEQ_CODER_INIT,
26207753Smm		SEQ_CODE,
27207753Smm	} sequence;
28207753Smm
29263285Sdelphij	/// If true, reject files that are unlikely to be .lzma files.
30263285Sdelphij	/// If false, more non-.lzma files get accepted and will give
31263285Sdelphij	/// LZMA_DATA_ERROR either immediately or after a few output bytes.
32263285Sdelphij	bool picky;
33263285Sdelphij
34207753Smm	/// Position in the header fields
35207753Smm	size_t pos;
36207753Smm
37207753Smm	/// Uncompressed size decoded from the header
38207753Smm	lzma_vli uncompressed_size;
39207753Smm
40207753Smm	/// Memory usage limit
41207753Smm	uint64_t memlimit;
42207753Smm
43207753Smm	/// Amount of memory actually needed (only an estimate)
44207753Smm	uint64_t memusage;
45207753Smm
46207753Smm	/// Options decoded from the header needed to initialize
47207753Smm	/// the LZMA decoder
48207753Smm	lzma_options_lzma options;
49312518Sdelphij} lzma_alone_coder;
50207753Smm
51207753Smm
52207753Smmstatic lzma_ret
53312518Sdelphijalone_decode(void *coder_ptr,
54292588Sdelphij		const lzma_allocator *allocator lzma_attribute((__unused__)),
55207753Smm		const uint8_t *restrict in, size_t *restrict in_pos,
56207753Smm		size_t in_size, uint8_t *restrict out,
57207753Smm		size_t *restrict out_pos, size_t out_size,
58207753Smm		lzma_action action)
59207753Smm{
60312518Sdelphij	lzma_alone_coder *coder = coder_ptr;
61312518Sdelphij
62207753Smm	while (*out_pos < out_size
63207753Smm			&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
64207753Smm	switch (coder->sequence) {
65207753Smm	case SEQ_PROPERTIES:
66207753Smm		if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
67207753Smm			return LZMA_FORMAT_ERROR;
68207753Smm
69207753Smm		coder->sequence = SEQ_DICTIONARY_SIZE;
70207753Smm		++*in_pos;
71207753Smm		break;
72207753Smm
73207753Smm	case SEQ_DICTIONARY_SIZE:
74207753Smm		coder->options.dict_size
75207753Smm				|= (size_t)(in[*in_pos]) << (coder->pos * 8);
76207753Smm
77207753Smm		if (++coder->pos == 4) {
78263285Sdelphij			if (coder->picky && coder->options.dict_size
79263285Sdelphij					!= UINT32_MAX) {
80207753Smm				// A hack to ditch tons of false positives:
81207753Smm				// We allow only dictionary sizes that are
82207753Smm				// 2^n or 2^n + 2^(n-1). LZMA_Alone created
83207753Smm				// only files with 2^n, but accepts any
84263285Sdelphij				// dictionary size.
85207753Smm				uint32_t d = coder->options.dict_size - 1;
86207753Smm				d |= d >> 2;
87207753Smm				d |= d >> 3;
88207753Smm				d |= d >> 4;
89207753Smm				d |= d >> 8;
90207753Smm				d |= d >> 16;
91207753Smm				++d;
92207753Smm
93207753Smm				if (d != coder->options.dict_size)
94207753Smm					return LZMA_FORMAT_ERROR;
95207753Smm			}
96207753Smm
97207753Smm			coder->pos = 0;
98207753Smm			coder->sequence = SEQ_UNCOMPRESSED_SIZE;
99207753Smm		}
100207753Smm
101207753Smm		++*in_pos;
102207753Smm		break;
103207753Smm
104207753Smm	case SEQ_UNCOMPRESSED_SIZE:
105207753Smm		coder->uncompressed_size
106207753Smm				|= (lzma_vli)(in[*in_pos]) << (coder->pos * 8);
107207753Smm		++*in_pos;
108207753Smm		if (++coder->pos < 8)
109207753Smm			break;
110207753Smm
111207753Smm		// Another hack to ditch false positives: Assume that
112207753Smm		// if the uncompressed size is known, it must be less
113263285Sdelphij		// than 256 GiB.
114263285Sdelphij		if (coder->picky
115263285Sdelphij				&& coder->uncompressed_size != LZMA_VLI_UNKNOWN
116207753Smm				&& coder->uncompressed_size
117207753Smm					>= (LZMA_VLI_C(1) << 38))
118207753Smm			return LZMA_FORMAT_ERROR;
119207753Smm
120207753Smm		// Calculate the memory usage so that it is ready
121207753Smm		// for SEQ_CODER_INIT.
122207753Smm		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
123207753Smm				+ LZMA_MEMUSAGE_BASE;
124207753Smm
125207753Smm		coder->pos = 0;
126207753Smm		coder->sequence = SEQ_CODER_INIT;
127207753Smm
128207753Smm	// Fall through
129207753Smm
130207753Smm	case SEQ_CODER_INIT: {
131207753Smm		if (coder->memusage > coder->memlimit)
132207753Smm			return LZMA_MEMLIMIT_ERROR;
133207753Smm
134207753Smm		lzma_filter_info filters[2] = {
135207753Smm			{
136207753Smm				.init = &lzma_lzma_decoder_init,
137207753Smm				.options = &coder->options,
138207753Smm			}, {
139207753Smm				.init = NULL,
140207753Smm			}
141207753Smm		};
142207753Smm
143207753Smm		const lzma_ret ret = lzma_next_filter_init(&coder->next,
144207753Smm				allocator, filters);
145207753Smm		if (ret != LZMA_OK)
146207753Smm			return ret;
147207753Smm
148207753Smm		// Use a hack to set the uncompressed size.
149207753Smm		lzma_lz_decoder_uncompressed(coder->next.coder,
150207753Smm				coder->uncompressed_size);
151207753Smm
152207753Smm		coder->sequence = SEQ_CODE;
153207753Smm		break;
154207753Smm	}
155207753Smm
156207753Smm	case SEQ_CODE: {
157207753Smm		return coder->next.code(coder->next.coder,
158207753Smm				allocator, in, in_pos, in_size,
159207753Smm				out, out_pos, out_size, action);
160207753Smm	}
161207753Smm
162207753Smm	default:
163207753Smm		return LZMA_PROG_ERROR;
164207753Smm	}
165207753Smm
166207753Smm	return LZMA_OK;
167207753Smm}
168207753Smm
169207753Smm
170207753Smmstatic void
171312518Sdelphijalone_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
172207753Smm{
173312518Sdelphij	lzma_alone_coder *coder = coder_ptr;
174207753Smm	lzma_next_end(&coder->next, allocator);
175207753Smm	lzma_free(coder, allocator);
176207753Smm	return;
177207753Smm}
178207753Smm
179207753Smm
180207753Smmstatic lzma_ret
181312518Sdelphijalone_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
182207753Smm		uint64_t *old_memlimit, uint64_t new_memlimit)
183207753Smm{
184312518Sdelphij	lzma_alone_coder *coder = coder_ptr;
185312518Sdelphij
186207753Smm	*memusage = coder->memusage;
187207753Smm	*old_memlimit = coder->memlimit;
188207753Smm
189207753Smm	if (new_memlimit != 0) {
190207753Smm		if (new_memlimit < coder->memusage)
191207753Smm			return LZMA_MEMLIMIT_ERROR;
192207753Smm
193207753Smm		coder->memlimit = new_memlimit;
194207753Smm	}
195207753Smm
196207753Smm	return LZMA_OK;
197207753Smm}
198207753Smm
199207753Smm
200207753Smmextern lzma_ret
201292588Sdelphijlzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
202263285Sdelphij		uint64_t memlimit, bool picky)
203207753Smm{
204207753Smm	lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
205207753Smm
206207753Smm	if (memlimit == 0)
207207753Smm		return LZMA_PROG_ERROR;
208207753Smm
209312518Sdelphij	lzma_alone_coder *coder = next->coder;
210312518Sdelphij
211312518Sdelphij	if (coder == NULL) {
212312518Sdelphij		coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
213312518Sdelphij		if (coder == NULL)
214207753Smm			return LZMA_MEM_ERROR;
215207753Smm
216312518Sdelphij		next->coder = coder;
217207753Smm		next->code = &alone_decode;
218207753Smm		next->end = &alone_decoder_end;
219207753Smm		next->memconfig = &alone_decoder_memconfig;
220312518Sdelphij		coder->next = LZMA_NEXT_CODER_INIT;
221207753Smm	}
222207753Smm
223312518Sdelphij	coder->sequence = SEQ_PROPERTIES;
224312518Sdelphij	coder->picky = picky;
225312518Sdelphij	coder->pos = 0;
226312518Sdelphij	coder->options.dict_size = 0;
227312518Sdelphij	coder->options.preset_dict = NULL;
228312518Sdelphij	coder->options.preset_dict_size = 0;
229312518Sdelphij	coder->uncompressed_size = 0;
230312518Sdelphij	coder->memlimit = memlimit;
231312518Sdelphij	coder->memusage = LZMA_MEMUSAGE_BASE;
232207753Smm
233207753Smm	return LZMA_OK;
234207753Smm}
235207753Smm
236207753Smm
237207753Smmextern LZMA_API(lzma_ret)
238207753Smmlzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
239207753Smm{
240263285Sdelphij	lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit, false);
241207753Smm
242207753Smm	strm->internal->supported_actions[LZMA_RUN] = true;
243207753Smm	strm->internal->supported_actions[LZMA_FINISH] = true;
244207753Smm
245207753Smm	return LZMA_OK;
246207753Smm}
247