The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
49813 ripley 1
///////////////////////////////////////////////////////////////////////////////
2
//
3
/// \file       stream_decoder.c
4
/// \brief      Decodes .xz Streams
5
//
6
//  Author:     Lasse Collin
7
//
8
//  This file has been put into the public domain.
9
//  You can do whatever you want with this file.
10
//
11
///////////////////////////////////////////////////////////////////////////////
12
 
13
#include "stream_decoder.h"
14
#include "block_decoder.h"
15
 
16
 
17
struct lzma_coder_s {
18
	enum {
19
		SEQ_STREAM_HEADER,
20
		SEQ_BLOCK_HEADER,
21
		SEQ_BLOCK,
22
		SEQ_INDEX,
23
		SEQ_STREAM_FOOTER,
24
		SEQ_STREAM_PADDING,
25
	} sequence;
26
 
27
	/// Block or Metadata decoder. This takes little memory and the same
28
	/// data structure can be used to decode every Block Header, so it's
29
	/// a good idea to have a separate lzma_next_coder structure for it.
30
	lzma_next_coder block_decoder;
31
 
32
	/// Block options decoded by the Block Header decoder and used by
33
	/// the Block decoder.
34
	lzma_block block_options;
35
 
36
	/// Stream Flags from Stream Header
37
	lzma_stream_flags stream_flags;
38
 
39
	/// Index is hashed so that it can be compared to the sizes of Blocks
40
	/// with O(1) memory usage.
41
	lzma_index_hash *index_hash;
42
 
43
	/// Memory usage limit
44
	uint64_t memlimit;
45
 
46
	/// Amount of memory actually needed (only an estimate)
47
	uint64_t memusage;
48
 
49
	/// If true, LZMA_NO_CHECK is returned if the Stream has
50
	/// no integrity check.
51
	bool tell_no_check;
52
 
53
	/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
54
	/// an integrity check that isn't supported by this liblzma build.
55
	bool tell_unsupported_check;
56
 
57
	/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
58
	bool tell_any_check;
59
 
60
	/// If true, we will decode concatenated Streams that possibly have
61
	/// Stream Padding between or after them. LZMA_STREAM_END is returned
62
	/// once the application isn't giving us any new input, and we aren't
63
	/// in the middle of a Stream, and possible Stream Padding is a
64
	/// multiple of four bytes.
65
	bool concatenated;
66
 
67
	/// When decoding concatenated Streams, this is true as long as we
68
	/// are decoding the first Stream. This is needed to avoid misleading
69
	/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
70
	/// bytes.
71
	bool first_stream;
72
 
73
	/// Write position in buffer[] and position in Stream Padding
74
	size_t pos;
75
 
76
	/// Buffer to hold Stream Header, Block Header, and Stream Footer.
77
	/// Block Header has biggest maximum size.
78
	uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
79
};
80
 
81
 
82
static lzma_ret
83
stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
84
{
85
	// Initialize the Index hash used to verify the Index.
86
	coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
87
	if (coder->index_hash == NULL)
88
		return LZMA_MEM_ERROR;
89
 
90
	// Reset the rest of the variables.
91
	coder->sequence = SEQ_STREAM_HEADER;
92
	coder->pos = 0;
93
 
94
	return LZMA_OK;
95
}
96
 
97
 
98
static lzma_ret
99
stream_decode(lzma_coder *coder, lzma_allocator *allocator,
100
		const uint8_t *restrict in, size_t *restrict in_pos,
101
		size_t in_size, uint8_t *restrict out,
102
		size_t *restrict out_pos, size_t out_size, lzma_action action)
103
{
104
	// When decoding the actual Block, it may be able to produce more
105
	// output even if we don't give it any new input.
106
	while (true)
107
	switch (coder->sequence) {
108
	case SEQ_STREAM_HEADER: {
109
		// Copy the Stream Header to the internal buffer.
110
		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
111
				LZMA_STREAM_HEADER_SIZE);
112
 
113
		// Return if we didn't get the whole Stream Header yet.
114
		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
115
			return LZMA_OK;
116
 
117
		coder->pos = 0;
118
 
119
		// Decode the Stream Header.
120
		const lzma_ret ret = lzma_stream_header_decode(
121
				&coder->stream_flags, coder->buffer);
122
		if (ret != LZMA_OK)
123
			return ret == LZMA_FORMAT_ERROR && !coder->first_stream
124
					? LZMA_DATA_ERROR : ret;
125
 
126
		// If we are decoding concatenated Streams, and the later
127
		// Streams have invalid Header Magic Bytes, we give
128
		// LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
129
		coder->first_stream = false;
130
 
131
		// Copy the type of the Check so that Block Header and Block
132
		// decoders see it.
133
		coder->block_options.check = coder->stream_flags.check;
134
 
135
		// Even if we return LZMA_*_CHECK below, we want
136
		// to continue from Block Header decoding.
137
		coder->sequence = SEQ_BLOCK_HEADER;
138
 
139
		// Detect if there's no integrity check or if it is
140
		// unsupported if those were requested by the application.
141
		if (coder->tell_no_check && coder->stream_flags.check
142
				== LZMA_CHECK_NONE)
143
			return LZMA_NO_CHECK;
144
 
145
		if (coder->tell_unsupported_check
146
				&& !lzma_check_is_supported(
147
					coder->stream_flags.check))
148
			return LZMA_UNSUPPORTED_CHECK;
149
 
150
		if (coder->tell_any_check)
151
			return LZMA_GET_CHECK;
152
	}
153
 
154
	// Fall through
155
 
156
	case SEQ_BLOCK_HEADER: {
157
		if (*in_pos >= in_size)
158
			return LZMA_OK;
159
 
160
		if (coder->pos == 0) {
161
			// Detect if it's Index.
162
			if (in[*in_pos] == 0x00) {
163
				coder->sequence = SEQ_INDEX;
164
				break;
165
			}
166
 
167
			// Calculate the size of the Block Header. Note that
168
			// Block Header decoder wants to see this byte too
169
			// so don't advance *in_pos.
170
			coder->block_options.header_size
171
					= lzma_block_header_size_decode(
172
						in[*in_pos]);
173
		}
174
 
175
		// Copy the Block Header to the internal buffer.
176
		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
177
				coder->block_options.header_size);
178
 
179
		// Return if we didn't get the whole Block Header yet.
180
		if (coder->pos < coder->block_options.header_size)
181
			return LZMA_OK;
182
 
183
		coder->pos = 0;
184
 
53508 ripley 185
		// Version 0 is currently the only possible version.
186
		coder->block_options.version = 0;
187
 
49813 ripley 188
		// Set up a buffer to hold the filter chain. Block Header
189
		// decoder will initialize all members of this array so
190
		// we don't need to do it here.
191
		lzma_filter filters[LZMA_FILTERS_MAX + 1];
192
		coder->block_options.filters = filters;
193
 
194
		// Decode the Block Header.
195
		return_if_error(lzma_block_header_decode(&coder->block_options,
196
				allocator, coder->buffer));
197
 
198
		// Check the memory usage limit.
199
		const uint64_t memusage = lzma_raw_decoder_memusage(filters);
200
		lzma_ret ret;
201
 
202
		if (memusage == UINT64_MAX) {
203
			// One or more unknown Filter IDs.
204
			ret = LZMA_OPTIONS_ERROR;
205
		} else {
206
			// Now we can set coder->memusage since we know that
207
			// the filter chain is valid. We don't want
208
			// lzma_memusage() to return UINT64_MAX in case of
209
			// invalid filter chain.
210
			coder->memusage = memusage;
211
 
212
			if (memusage > coder->memlimit) {
213
				// The chain would need too much memory.
214
				ret = LZMA_MEMLIMIT_ERROR;
215
			} else {
216
				// Memory usage is OK.
217
				// Initialize the Block decoder.
218
				ret = lzma_block_decoder_init(
219
						&coder->block_decoder,
220
						allocator,
221
						&coder->block_options);
222
			}
223
		}
224
 
225
		// Free the allocated filter options since they are needed
226
		// only to initialize the Block decoder.
227
		for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
228
			lzma_free(filters[i].options, allocator);
229
 
230
		coder->block_options.filters = NULL;
231
 
232
		// Check if memory usage calculation and Block enocoder
233
		// initialization succeeded.
234
		if (ret != LZMA_OK)
235
			return ret;
236
 
237
		coder->sequence = SEQ_BLOCK;
238
	}
239
 
240
	// Fall through
241
 
242
	case SEQ_BLOCK: {
243
		const lzma_ret ret = coder->block_decoder.code(
244
				coder->block_decoder.coder, allocator,
245
				in, in_pos, in_size, out, out_pos, out_size,
246
				action);
247
 
248
		if (ret != LZMA_STREAM_END)
249
			return ret;
250
 
251
		// Block decoded successfully. Add the new size pair to
252
		// the Index hash.
253
		return_if_error(lzma_index_hash_append(coder->index_hash,
254
				lzma_block_unpadded_size(
255
					&coder->block_options),
256
				coder->block_options.uncompressed_size));
257
 
258
		coder->sequence = SEQ_BLOCK_HEADER;
259
		break;
260
	}
261
 
262
	case SEQ_INDEX: {
263
		// If we don't have any input, don't call
264
		// lzma_index_hash_decode() since it would return
265
		// LZMA_BUF_ERROR, which we must not do here.
266
		if (*in_pos >= in_size)
267
			return LZMA_OK;
268
 
269
		// Decode the Index and compare it to the hash calculated
270
		// from the sizes of the Blocks (if any).
271
		const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
272
				in, in_pos, in_size);
273
		if (ret != LZMA_STREAM_END)
274
			return ret;
275
 
276
		coder->sequence = SEQ_STREAM_FOOTER;
277
	}
278
 
279
	// Fall through
280
 
281
	case SEQ_STREAM_FOOTER: {
282
		// Copy the Stream Footer to the internal buffer.
283
		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
284
				LZMA_STREAM_HEADER_SIZE);
285
 
286
		// Return if we didn't get the whole Stream Footer yet.
287
		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
288
			return LZMA_OK;
289
 
290
		coder->pos = 0;
291
 
292
		// Decode the Stream Footer. The decoder gives
293
		// LZMA_FORMAT_ERROR if the magic bytes don't match,
294
		// so convert that return code to LZMA_DATA_ERROR.
295
		lzma_stream_flags footer_flags;
296
		const lzma_ret ret = lzma_stream_footer_decode(
297
				&footer_flags, coder->buffer);
298
		if (ret != LZMA_OK)
299
			return ret == LZMA_FORMAT_ERROR
300
					? LZMA_DATA_ERROR : ret;
301
 
302
		// Check that Index Size stored in the Stream Footer matches
303
		// the real size of the Index field.
304
		if (lzma_index_hash_size(coder->index_hash)
305
				!= footer_flags.backward_size)
306
			return LZMA_DATA_ERROR;
307
 
308
		// Compare that the Stream Flags fields are identical in
309
		// both Stream Header and Stream Footer.
310
		return_if_error(lzma_stream_flags_compare(
311
				&coder->stream_flags, &footer_flags));
312
 
313
		if (!coder->concatenated)
314
			return LZMA_STREAM_END;
315
 
316
		coder->sequence = SEQ_STREAM_PADDING;
317
	}
318
 
319
	// Fall through
320
 
321
	case SEQ_STREAM_PADDING:
322
		assert(coder->concatenated);
323
 
324
		// Skip over possible Stream Padding.
325
		while (true) {
326
			if (*in_pos >= in_size) {
327
				// Unless LZMA_FINISH was used, we cannot
328
				// know if there's more input coming later.
329
				if (action != LZMA_FINISH)
330
					return LZMA_OK;
331
 
332
				// Stream Padding must be a multiple of
333
				// four bytes.
334
				return coder->pos == 0
335
						? LZMA_STREAM_END
336
						: LZMA_DATA_ERROR;
337
			}
338
 
339
			// If the byte is not zero, it probably indicates
340
			// beginning of a new Stream (or the file is corrupt).
341
			if (in[*in_pos] != 0x00)
342
				break;
343
 
344
			++*in_pos;
345
			coder->pos = (coder->pos + 1) & 3;
346
		}
347
 
348
		// Stream Padding must be a multiple of four bytes (empty
349
		// Stream Padding is OK).
350
		if (coder->pos != 0) {
351
			++*in_pos;
352
			return LZMA_DATA_ERROR;
353
		}
354
 
355
		// Prepare to decode the next Stream.
356
		return_if_error(stream_decoder_reset(coder, allocator));
357
		break;
358
 
359
	default:
360
		assert(0);
361
		return LZMA_PROG_ERROR;
362
	}
363
 
53508 ripley 364
	// Never reached
49813 ripley 365
}
366
 
367
 
368
static void
369
stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
370
{
371
	lzma_next_end(&coder->block_decoder, allocator);
372
	lzma_index_hash_end(coder->index_hash, allocator);
373
	lzma_free(coder, allocator);
374
	return;
375
}
376
 
377
 
378
static lzma_check
379
stream_decoder_get_check(const lzma_coder *coder)
380
{
381
	return coder->stream_flags.check;
382
}
383
 
384
 
385
static lzma_ret
386
stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
387
		uint64_t *old_memlimit, uint64_t new_memlimit)
388
{
389
	*memusage = coder->memusage;
390
	*old_memlimit = coder->memlimit;
391
 
53508 ripley 392
	if (new_memlimit != 0) {
393
		if (new_memlimit < coder->memusage)
394
			return LZMA_MEMLIMIT_ERROR;
395
 
396
		coder->memlimit = new_memlimit;
397
	}
398
 
49813 ripley 399
	return LZMA_OK;
400
}
401
 
402
 
403
extern lzma_ret
404
lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
405
		uint64_t memlimit, uint32_t flags)
406
{
407
	lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
408
 
409
	if (memlimit == 0)
410
		return LZMA_PROG_ERROR;
411
 
412
	if (flags & ~LZMA_SUPPORTED_FLAGS)
413
		return LZMA_OPTIONS_ERROR;
414
 
415
	if (next->coder == NULL) {
416
		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
417
		if (next->coder == NULL)
418
			return LZMA_MEM_ERROR;
419
 
420
		next->code = &stream_decode;
421
		next->end = &stream_decoder_end;
422
		next->get_check = &stream_decoder_get_check;
423
		next->memconfig = &stream_decoder_memconfig;
424
 
425
		next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
426
		next->coder->index_hash = NULL;
427
	}
428
 
429
	next->coder->memlimit = memlimit;
430
	next->coder->memusage = LZMA_MEMUSAGE_BASE;
431
	next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
432
	next->coder->tell_unsupported_check
433
			= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
434
	next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
435
	next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
436
	next->coder->first_stream = true;
437
 
438
	return stream_decoder_reset(next->coder, allocator);
439
}
440
 
441
 
442
extern LZMA_API(lzma_ret)
443
lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
444
{
445
	lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
446
 
447
	strm->internal->supported_actions[LZMA_RUN] = true;
448
	strm->internal->supported_actions[LZMA_FINISH] = true;
449
 
450
	return LZMA_OK;
451
}