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