xref: /freebsd/contrib/xz/src/liblzma/common/lzip_decoder.c (revision 577b62c2bacc7dfa228591ca3da361e1bc398301)
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       lzip_decoder.c
4 /// \brief      Decodes .lz (lzip) files
5 //
6 //  Author:     Michał Górny
7 //              Lasse Collin
8 //
9 //  This file has been put into the public domain.
10 //  You can do whatever you want with this file.
11 //
12 ///////////////////////////////////////////////////////////////////////////////
13 
14 #include "lzip_decoder.h"
15 #include "lzma_decoder.h"
16 #include "check.h"
17 
18 
19 // .lz format version 0 lacks the 64-bit Member size field in the footer.
20 #define LZIP_V0_FOOTER_SIZE 12
21 #define LZIP_V1_FOOTER_SIZE 20
22 #define LZIP_FOOTER_SIZE_MAX LZIP_V1_FOOTER_SIZE
23 
24 // lc/lp/pb are hardcoded in the .lz format.
25 #define LZIP_LC 3
26 #define LZIP_LP 0
27 #define LZIP_PB 2
28 
29 
30 typedef struct {
31 	enum {
32 		SEQ_ID_STRING,
33 		SEQ_VERSION,
34 		SEQ_DICT_SIZE,
35 		SEQ_CODER_INIT,
36 		SEQ_LZMA_STREAM,
37 		SEQ_MEMBER_FOOTER,
38 	} sequence;
39 
40 	/// .lz member format version
41 	uint32_t version;
42 
43 	/// CRC32 of the uncompressed data in the .lz member
44 	uint32_t crc32;
45 
46 	/// Uncompressed size of the .lz member
47 	uint64_t uncompressed_size;
48 
49 	/// Compressed size of the .lz member
50 	uint64_t member_size;
51 
52 	/// Memory usage limit
53 	uint64_t memlimit;
54 
55 	/// Amount of memory actually needed
56 	uint64_t memusage;
57 
58 	/// If true, LZMA_GET_CHECK is returned after decoding the header
59 	/// fields. As all files use CRC32 this is redundant but it's
60 	/// implemented anyway since the initialization functions supports
61 	/// all other flags in addition to LZMA_TELL_ANY_CHECK.
62 	bool tell_any_check;
63 
64 	/// If true, we won't calculate or verify the CRC32 of
65 	/// the uncompressed data.
66 	bool ignore_check;
67 
68 	/// If true, we will decode concatenated .lz members and stop if
69 	/// non-.lz data is seen after at least one member has been
70 	/// successfully decoded.
71 	bool concatenated;
72 
73 	/// When decoding concatenated .lz members, this is true as long as
74 	/// we are decoding the first .lz member. This is needed to avoid
75 	/// incorrect LZMA_FORMAT_ERROR in case there is non-.lz data at
76 	/// the end of the file.
77 	bool first_member;
78 
79 	/// Reading position in the header and footer fields
80 	size_t pos;
81 
82 	/// Buffer to hold the .lz footer fields
83 	uint8_t buffer[LZIP_FOOTER_SIZE_MAX];
84 
85 	/// Options decoded from the .lz header that needed to initialize
86 	/// the LZMA1 decoder.
87 	lzma_options_lzma options;
88 
89 	/// LZMA1 decoder
90 	lzma_next_coder lzma_decoder;
91 
92 } lzma_lzip_coder;
93 
94 
95 static lzma_ret
96 lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
97 		const uint8_t *restrict in, size_t *restrict in_pos,
98 		size_t in_size, uint8_t *restrict out,
99 		size_t *restrict out_pos, size_t out_size, lzma_action action)
100 {
101 	lzma_lzip_coder *coder = coder_ptr;
102 
103 	while (true)
104 	switch (coder->sequence) {
105 	case SEQ_ID_STRING: {
106 		// The "ID string" or magic bytes are "LZIP" in US-ASCII.
107 		const uint8_t lzip_id_string[4] = { 0x4C, 0x5A, 0x49, 0x50 };
108 
109 		while (coder->pos < sizeof(lzip_id_string)) {
110 			if (*in_pos >= in_size) {
111 				// If we are on the 2nd+ concatenated member
112 				// and the input ends before we can read
113 				// the magic bytes, we discard the bytes that
114 				// were already read (up to 3) and finish.
115 				// See the reasoning below.
116 				return !coder->first_member
117 						&& action == LZMA_FINISH
118 					? LZMA_STREAM_END : LZMA_OK;
119 			}
120 
121 			if (in[*in_pos] != lzip_id_string[coder->pos]) {
122 				// The .lz format allows putting non-.lz data
123 				// at the end of the file. If we have seen
124 				// at least one valid .lz member already,
125 				// then we won't consume the byte at *in_pos
126 				// and will return LZMA_STREAM_END. This way
127 				// apps can easily locate and read the non-.lz
128 				// data after the .lz member(s).
129 				//
130 				// NOTE: If the first 1-3 bytes of the non-.lz
131 				// data match the .lz ID string then the first
132 				// 1-3 bytes of the junk will get ignored by
133 				// us. If apps want to properly locate the
134 				// trailing data they must ensure that the
135 				// first byte of their custom data isn't the
136 				// same as the first byte of .lz ID string.
137 				// With the liblzma API we cannot rewind the
138 				// input position across calls to lzma_code().
139 				return !coder->first_member
140 					? LZMA_STREAM_END : LZMA_FORMAT_ERROR;
141 			}
142 
143 			++*in_pos;
144 			++coder->pos;
145 		}
146 
147 		coder->pos = 0;
148 
149 		coder->crc32 = 0;
150 		coder->uncompressed_size = 0;
151 		coder->member_size = sizeof(lzip_id_string);
152 
153 		coder->sequence = SEQ_VERSION;
154 	}
155 
156 	// Fall through
157 
158 	case SEQ_VERSION:
159 		if (*in_pos >= in_size)
160 			return LZMA_OK;
161 
162 		coder->version = in[(*in_pos)++];
163 
164 		// We support version 0 and unextended version 1.
165 		if (coder->version > 1)
166 			return LZMA_OPTIONS_ERROR;
167 
168 		++coder->member_size;
169 		coder->sequence = SEQ_DICT_SIZE;
170 
171 		// .lz versions 0 and 1 use CRC32 as the integrity check
172 		// so if the application wanted to know that
173 		// (LZMA_TELL_ANY_CHECK) we can tell it now.
174 		if (coder->tell_any_check)
175 			return LZMA_GET_CHECK;
176 
177 	// Fall through
178 
179 	case SEQ_DICT_SIZE: {
180 		if (*in_pos >= in_size)
181 			return LZMA_OK;
182 
183 		const uint32_t ds = in[(*in_pos)++];
184 		++coder->member_size;
185 
186 		// The five lowest bits are for the base-2 logarithm of
187 		// the dictionary size and the highest three bits are
188 		// the fractional part (0/16 to 7/16) that will be
189 		// substracted to get the final value.
190 		//
191 		// For example, with 0xB5:
192 		//     b2log = 21
193 		//     fracnum = 5
194 		//     dict_size = 2^21 - 2^21 * 5 / 16 = 1408 KiB
195 		const uint32_t b2log = ds & 0x1F;
196 		const uint32_t fracnum = ds >> 5;
197 
198 		// The format versions 0 and 1 allow dictionary size in the
199 		// range [4 KiB, 512 MiB].
200 		if (b2log < 12 || b2log > 29 || (b2log == 12 && fracnum > 0))
201 			return LZMA_DATA_ERROR;
202 
203 		//   2^[b2log] - 2^[b2log] * [fracnum] / 16
204 		// = 2^[b2log] - [fracnum] * 2^([b2log] - 4)
205 		coder->options.dict_size = (UINT32_C(1) << b2log)
206 				- (fracnum << (b2log - 4));
207 
208 		assert(coder->options.dict_size >= 4096);
209 		assert(coder->options.dict_size <= (UINT32_C(512) << 20));
210 
211 		coder->options.preset_dict = NULL;
212 		coder->options.lc = LZIP_LC;
213 		coder->options.lp = LZIP_LP;
214 		coder->options.pb = LZIP_PB;
215 
216 		// Calculate the memory usage.
217 		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
218 				+ LZMA_MEMUSAGE_BASE;
219 
220 		// Initialization is a separate step because if we return
221 		// LZMA_MEMLIMIT_ERROR we need to be able to restart after
222 		// the memlimit has been increased.
223 		coder->sequence = SEQ_CODER_INIT;
224 	}
225 
226 	// Fall through
227 
228 	case SEQ_CODER_INIT: {
229 		if (coder->memusage > coder->memlimit)
230 			return LZMA_MEMLIMIT_ERROR;
231 
232 		const lzma_filter_info filters[2] = {
233 			{
234 				.id = LZMA_FILTER_LZMA1,
235 				.init = &lzma_lzma_decoder_init,
236 				.options = &coder->options,
237 			}, {
238 				.init = NULL,
239 			}
240 		};
241 
242 		return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
243 				allocator, filters));
244 
245 		coder->crc32 = 0;
246 		coder->sequence = SEQ_LZMA_STREAM;
247 	}
248 
249 	// Fall through
250 
251 	case SEQ_LZMA_STREAM: {
252 		const size_t in_start = *in_pos;
253 		const size_t out_start = *out_pos;
254 
255 		const lzma_ret ret = coder->lzma_decoder.code(
256 				coder->lzma_decoder.coder, allocator,
257 				in, in_pos, in_size, out, out_pos, out_size,
258 				action);
259 
260 		const size_t out_used = *out_pos - out_start;
261 
262 		coder->member_size += *in_pos - in_start;
263 		coder->uncompressed_size += out_used;
264 
265 		if (!coder->ignore_check)
266 			coder->crc32 = lzma_crc32(out + out_start, out_used,
267 					coder->crc32);
268 
269 		if (ret != LZMA_STREAM_END)
270 			return ret;
271 
272 		coder->sequence = SEQ_MEMBER_FOOTER;
273 	}
274 
275 	// Fall through
276 
277 	case SEQ_MEMBER_FOOTER: {
278 		// The footer of .lz version 0 lacks the Member size field.
279 		// This is the only difference between version 0 and
280 		// unextended version 1 formats.
281 		const size_t footer_size = coder->version == 0
282 				? LZIP_V0_FOOTER_SIZE
283 				: LZIP_V1_FOOTER_SIZE;
284 
285 		// Copy the CRC32, Data size, and Member size fields to
286 		// the internal buffer.
287 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
288 				footer_size);
289 
290 		// Return if we didn't get the whole footer yet.
291 		if (coder->pos < footer_size)
292 			return LZMA_OK;
293 
294 		coder->pos = 0;
295 		coder->member_size += footer_size;
296 
297 		// Check that the footer fields match the observed data.
298 		if (!coder->ignore_check
299 				&& coder->crc32 != read32le(&coder->buffer[0]))
300 			return LZMA_DATA_ERROR;
301 
302 		if (coder->uncompressed_size != read64le(&coder->buffer[4]))
303 			return LZMA_DATA_ERROR;
304 
305 		if (coder->version > 0) {
306 			// .lz version 0 has no Member size field.
307 			if (coder->member_size != read64le(&coder->buffer[12]))
308 				return LZMA_DATA_ERROR;
309 		}
310 
311 		// Decoding is finished if we weren't requested to decode
312 		// more than one .lz member.
313 		if (!coder->concatenated)
314 			return LZMA_STREAM_END;
315 
316 		coder->first_member = false;
317 		coder->sequence = SEQ_ID_STRING;
318 		break;
319 	}
320 
321 	default:
322 		assert(0);
323 		return LZMA_PROG_ERROR;
324 	}
325 
326 	// Never reached
327 }
328 
329 
330 static void
331 lzip_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
332 {
333 	lzma_lzip_coder *coder = coder_ptr;
334 	lzma_next_end(&coder->lzma_decoder, allocator);
335 	lzma_free(coder, allocator);
336 	return;
337 }
338 
339 
340 static lzma_check
341 lzip_decoder_get_check(const void *coder_ptr lzma_attribute((__unused__)))
342 {
343 	return LZMA_CHECK_CRC32;
344 }
345 
346 
347 static lzma_ret
348 lzip_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
349 		uint64_t *old_memlimit, uint64_t new_memlimit)
350 {
351 	lzma_lzip_coder *coder = coder_ptr;
352 
353 	*memusage = coder->memusage;
354 	*old_memlimit = coder->memlimit;
355 
356 	if (new_memlimit != 0) {
357 		if (new_memlimit < coder->memusage)
358 			return LZMA_MEMLIMIT_ERROR;
359 
360 		coder->memlimit = new_memlimit;
361 	}
362 
363 	return LZMA_OK;
364 }
365 
366 
367 extern lzma_ret
368 lzma_lzip_decoder_init(
369 		lzma_next_coder *next, const lzma_allocator *allocator,
370 		uint64_t memlimit, uint32_t flags)
371 {
372 	lzma_next_coder_init(&lzma_lzip_decoder_init, next, allocator);
373 
374 	if (flags & ~LZMA_SUPPORTED_FLAGS)
375 		return LZMA_OPTIONS_ERROR;
376 
377 	lzma_lzip_coder *coder = next->coder;
378 	if (coder == NULL) {
379 		coder = lzma_alloc(sizeof(lzma_lzip_coder), allocator);
380 		if (coder == NULL)
381 			return LZMA_MEM_ERROR;
382 
383 		next->coder = coder;
384 		next->code = &lzip_decode;
385 		next->end = &lzip_decoder_end;
386 		next->get_check = &lzip_decoder_get_check;
387 		next->memconfig = &lzip_decoder_memconfig;
388 
389 		coder->lzma_decoder = LZMA_NEXT_CODER_INIT;
390 	}
391 
392 	coder->sequence = SEQ_ID_STRING;
393 	coder->memlimit = my_max(1, memlimit);
394 	coder->memusage = LZMA_MEMUSAGE_BASE;
395 	coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
396 	coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
397 	coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
398 	coder->first_member = true;
399 	coder->pos = 0;
400 
401 	return LZMA_OK;
402 }
403 
404 
405 extern LZMA_API(lzma_ret)
406 lzma_lzip_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
407 {
408 	lzma_next_strm_init(lzma_lzip_decoder_init, strm, memlimit, flags);
409 
410 	strm->internal->supported_actions[LZMA_RUN] = true;
411 	strm->internal->supported_actions[LZMA_FINISH] = true;
412 
413 	return LZMA_OK;
414 }
415