xref: /freebsd/contrib/xz/src/liblzma/common/index_decoder.c (revision dece5b05f577fc4c6b89af7ad48dfbdf7cc4945c)
1 // SPDX-License-Identifier: 0BSD
2 
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       index_decoder.c
6 /// \brief      Decodes the Index field
7 //
8 //  Author:     Lasse Collin
9 //
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 #include "index_decoder.h"
13 #include "check.h"
14 
15 
16 typedef struct {
17 	enum {
18 		SEQ_INDICATOR,
19 		SEQ_COUNT,
20 		SEQ_MEMUSAGE,
21 		SEQ_UNPADDED,
22 		SEQ_UNCOMPRESSED,
23 		SEQ_PADDING_INIT,
24 		SEQ_PADDING,
25 		SEQ_CRC32,
26 	} sequence;
27 
28 	/// Memory usage limit
29 	uint64_t memlimit;
30 
31 	// Memory used for lzma_index once it has been allocated.
32 	// Before that, this holds a tiny value.
33 	uint64_t memused;
34 
35 	/// Target Index
36 	lzma_index *index;
37 
38 	/// Pointer give by the application, which is set after
39 	/// successful decoding.
40 	lzma_index **index_ptr;
41 
42 	/// If Number of Records contains a value higher than this,
43 	/// the Index is immediately considered to be corrupt.
44 	/// This prevents us from allocating a large amount of memory
45 	/// when we know that the Index isn't big.
46 	lzma_vli number_of_records_max;
47 
48 	/// Number of Records left to decode.
49 	lzma_vli count;
50 
51 	/// The most recent Unpadded Size field
52 	lzma_vli unpadded_size;
53 
54 	/// The most recent Uncompressed Size field
55 	lzma_vli uncompressed_size;
56 
57 	/// Position in integers
58 	size_t pos;
59 
60 	/// CRC32 of the List of Records field
61 	uint32_t crc32;
62 } lzma_index_coder;
63 
64 
65 static lzma_ret
66 index_decode(void *coder_ptr, const lzma_allocator *allocator,
67 		const uint8_t *restrict in, size_t *restrict in_pos,
68 		size_t in_size,
69 		uint8_t *restrict out lzma_attribute((__unused__)),
70 		size_t *restrict out_pos lzma_attribute((__unused__)),
71 		size_t out_size lzma_attribute((__unused__)),
72 		lzma_action action lzma_attribute((__unused__)))
73 {
74 	lzma_index_coder *coder = coder_ptr;
75 
76 	// Similar optimization as in index_encoder.c
77 	const size_t in_start = *in_pos;
78 	lzma_ret ret = LZMA_OK;
79 
80 	while (*in_pos < in_size)
81 	switch (coder->sequence) {
82 	case SEQ_INDICATOR:
83 		// Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
84 		// LZMA_FORMAT_ERROR, because a typical usage case for Index
85 		// decoder is when parsing the Stream backwards. If seeking
86 		// backward from the Stream Footer gives us something that
87 		// doesn't begin with Index Indicator, the file is considered
88 		// corrupt, not "programming error" or "unrecognized file
89 		// format". One could argue that the application should
90 		// verify the Index Indicator before trying to decode the
91 		// Index, but well, I suppose it is simpler this way.
92 		if (in[(*in_pos)++] != INDEX_INDICATOR)
93 			return LZMA_DATA_ERROR;
94 
95 		coder->sequence = SEQ_COUNT;
96 		break;
97 
98 	case SEQ_COUNT:
99 		ret = lzma_vli_decode(&coder->count, &coder->pos,
100 				in, in_pos, in_size);
101 		if (ret != LZMA_STREAM_END)
102 			goto out;
103 
104 		// Reject Number of Records values that are clearly invalid.
105 		if (coder->count > coder->number_of_records_max)
106 			return LZMA_DATA_ERROR;
107 
108 		coder->pos = 0;
109 		coder->sequence = SEQ_MEMUSAGE;
110 		FALLTHROUGH;
111 
112 	case SEQ_MEMUSAGE:
113 		coder->memused = lzma_index_memusage(1, coder->count);
114 
115 		// We sanity-checked coder->count in SEQ_COUNT, which
116 		// guarantees that lzma_index_memusage() won't fail.
117 		assert(coder->memused != UINT64_MAX);
118 
119 		if (coder->memused > coder->memlimit) {
120 			ret = LZMA_MEMLIMIT_ERROR;
121 			goto out;
122 		}
123 
124 		// Tell the Index handling code how many Records this
125 		// Index has to allow it to allocate memory more efficiently.
126 		// If the Record count is so high that memory allocation would
127 		// fail later, return LZMA_MEM_ERROR now.
128 		if (lzma_index_prealloc(coder->index, coder->count))
129 			return LZMA_MEM_ERROR;
130 
131 		ret = LZMA_OK;
132 		coder->sequence = coder->count == 0
133 				? SEQ_PADDING_INIT : SEQ_UNPADDED;
134 		break;
135 
136 	case SEQ_UNPADDED:
137 	case SEQ_UNCOMPRESSED: {
138 		lzma_vli *size = coder->sequence == SEQ_UNPADDED
139 				? &coder->unpadded_size
140 				: &coder->uncompressed_size;
141 
142 		ret = lzma_vli_decode(size, &coder->pos,
143 				in, in_pos, in_size);
144 		if (ret != LZMA_STREAM_END)
145 			goto out;
146 
147 		ret = LZMA_OK;
148 		coder->pos = 0;
149 
150 		if (coder->sequence == SEQ_UNPADDED) {
151 			// Validate that encoded Unpadded Size isn't too small
152 			// or too big.
153 			if (coder->unpadded_size < UNPADDED_SIZE_MIN
154 					|| coder->unpadded_size
155 						> UNPADDED_SIZE_MAX)
156 				return LZMA_DATA_ERROR;
157 
158 			coder->sequence = SEQ_UNCOMPRESSED;
159 		} else {
160 			// Add the decoded Record to the Index.
161 			return_if_error(lzma_index_append(
162 					coder->index, allocator,
163 					coder->unpadded_size,
164 					coder->uncompressed_size));
165 
166 			// Check if this was the last Record.
167 			coder->sequence = --coder->count == 0
168 					? SEQ_PADDING_INIT
169 					: SEQ_UNPADDED;
170 		}
171 
172 		break;
173 	}
174 
175 	case SEQ_PADDING_INIT:
176 		coder->pos = lzma_index_padding_size(coder->index);
177 		coder->sequence = SEQ_PADDING;
178 		FALLTHROUGH;
179 
180 	case SEQ_PADDING:
181 		if (coder->pos > 0) {
182 			--coder->pos;
183 			if (in[(*in_pos)++] != 0x00)
184 				return LZMA_DATA_ERROR;
185 
186 			break;
187 		}
188 
189 		// Finish the CRC32 calculation.
190 		coder->crc32 = lzma_crc32(in + in_start,
191 				*in_pos - in_start, coder->crc32);
192 
193 		coder->sequence = SEQ_CRC32;
194 		FALLTHROUGH;
195 
196 	case SEQ_CRC32:
197 		do {
198 			if (*in_pos == in_size)
199 				return LZMA_OK;
200 
201 			if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
202 					!= in[(*in_pos)++]) {
203 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
204 				return LZMA_DATA_ERROR;
205 #endif
206 			}
207 
208 		} while (++coder->pos < 4);
209 
210 		// Decoding was successful, now we can let the application
211 		// see the decoded Index.
212 		*coder->index_ptr = coder->index;
213 
214 		// Make index NULL so we don't free it unintentionally.
215 		coder->index = NULL;
216 
217 		return LZMA_STREAM_END;
218 
219 	default:
220 		assert(0);
221 		return LZMA_PROG_ERROR;
222 	}
223 
224 out:
225 	// Update the CRC32.
226 	//
227 	// Avoid null pointer + 0 (undefined behavior) in "in + in_start".
228 	// In such a case we had no input and thus in_used == 0.
229 	{
230 		const size_t in_used = *in_pos - in_start;
231 		if (in_used > 0)
232 			coder->crc32 = lzma_crc32(in + in_start,
233 					in_used, coder->crc32);
234 	}
235 
236 	return ret;
237 }
238 
239 
240 static void
241 index_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
242 {
243 	lzma_index_coder *coder = coder_ptr;
244 	lzma_index_end(coder->index, allocator);
245 	lzma_free(coder, allocator);
246 	return;
247 }
248 
249 
250 static lzma_ret
251 index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
252 		uint64_t *old_memlimit, uint64_t new_memlimit)
253 {
254 	lzma_index_coder *coder = coder_ptr;
255 
256 	// Index decoder is special in sense that the returned memusage
257 	// doesn't include the memory usage of the decoder itself; only
258 	// the resulting lzma_index is counted.
259 	*memusage = coder->memused;
260 	*old_memlimit = coder->memlimit;
261 
262 	if (new_memlimit != 0) {
263 		if (new_memlimit < *memusage)
264 			return LZMA_MEMLIMIT_ERROR;
265 
266 		coder->memlimit = new_memlimit;
267 	}
268 
269 	return LZMA_OK;
270 }
271 
272 
273 static lzma_ret
274 index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
275 		lzma_index **i, uint64_t memlimit, uint64_t input_size_max)
276 {
277 	// Remember the pointer given by the application. We will set it
278 	// to point to the decoded Index only if decoding is successful.
279 	// Before that, keep it NULL so that applications can always safely
280 	// pass it to lzma_index_end() no matter did decoding succeed or not.
281 	coder->index_ptr = i;
282 	*i = NULL;
283 
284 	// We always allocate a new lzma_index.
285 	coder->index = lzma_index_init(allocator);
286 	if (coder->index == NULL)
287 		return LZMA_MEM_ERROR;
288 
289 	// Approximate how many Records the Index may contain at most when
290 	// we know that the Index won't be larger than input_size_max bytes.
291 	// Each Record must consume at least two bytes. The CRC32 etc.
292 	// consume a few bytes too, but we don't need an exact value.
293 	//
294 	// file_info.c knows Backward Size and passes it to us. When we have
295 	// no information, input_size_max equals LZMA_BACKWARD_SIZE_MAX.
296 	coder->number_of_records_max = input_size_max / 2;
297 
298 	// Initialize the rest.
299 	coder->sequence = SEQ_INDICATOR;
300 	coder->memlimit = my_max(1, memlimit);
301 	coder->memused = 1; // If _memconfig() is called before SEQ_MEMUSAGE.
302 	coder->pos = 0;
303 	coder->crc32 = 0;
304 
305 	return LZMA_OK;
306 }
307 
308 
309 extern lzma_ret
310 lzma_index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
311 		lzma_index **i, uint64_t memlimit, uint64_t input_size_max)
312 {
313 	lzma_next_coder_init(&lzma_index_decoder_init, next, allocator);
314 
315 	if (i == NULL)
316 		return LZMA_PROG_ERROR;
317 
318 	lzma_index_coder *coder = next->coder;
319 	if (coder == NULL) {
320 		coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
321 		if (coder == NULL)
322 			return LZMA_MEM_ERROR;
323 
324 		next->coder = coder;
325 		next->code = &index_decode;
326 		next->end = &index_decoder_end;
327 		next->memconfig = &index_decoder_memconfig;
328 		coder->index = NULL;
329 	} else {
330 		lzma_index_end(coder->index, allocator);
331 	}
332 
333 	return index_decoder_reset(
334 			coder, allocator, i, memlimit, input_size_max);
335 }
336 
337 
338 extern LZMA_API(lzma_ret)
339 lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
340 {
341 	// If i isn't NULL, *i must always be initialized due to
342 	// the wording in the API docs. This way it is initialized
343 	// if we return LZMA_PROG_ERROR due to strm == NULL.
344 	if (i != NULL)
345 		*i = NULL;
346 
347 	lzma_next_strm_init(lzma_index_decoder_init, strm, i, memlimit,
348 			LZMA_BACKWARD_SIZE_MAX);
349 
350 	strm->internal->supported_actions[LZMA_RUN] = true;
351 	strm->internal->supported_actions[LZMA_FINISH] = true;
352 
353 	return LZMA_OK;
354 }
355 
356 
357 extern LZMA_API(lzma_ret)
358 lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
359 		const lzma_allocator *allocator,
360 		const uint8_t *in, size_t *in_pos, size_t in_size)
361 {
362 	// If i isn't NULL, *i must always be initialized due to
363 	// the wording in the API docs.
364 	if (i != NULL)
365 		*i = NULL;
366 
367 	// Sanity checks
368 	if (i == NULL || memlimit == NULL
369 			|| in == NULL || in_pos == NULL || *in_pos > in_size)
370 		return LZMA_PROG_ERROR;
371 
372 	// Initialize the decoder.
373 	lzma_index_coder coder;
374 	const uint64_t input_size_max = in_size - *in_pos;
375 	return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit,
376 			my_min(input_size_max, LZMA_BACKWARD_SIZE_MAX)));
377 
378 	// Store the input start position so that we can restore it in case
379 	// of an error.
380 	const size_t in_start = *in_pos;
381 
382 	// Do the actual decoding.
383 	lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
384 			NULL, NULL, 0, LZMA_RUN);
385 
386 	if (ret == LZMA_STREAM_END) {
387 		ret = LZMA_OK;
388 	} else {
389 		// Something went wrong, free the Index structure and restore
390 		// the input position.
391 		lzma_index_end(coder.index, allocator);
392 		*in_pos = in_start;
393 
394 		if (ret == LZMA_OK) {
395 			// The input is truncated or otherwise corrupt.
396 			// Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
397 			// like lzma_vli_decode() does in single-call mode.
398 			ret = LZMA_DATA_ERROR;
399 
400 		} else if (ret == LZMA_MEMLIMIT_ERROR) {
401 			// Tell the caller how much memory would have
402 			// been needed.
403 			*memlimit = coder.memused;
404 		}
405 	}
406 
407 	return ret;
408 }
409