1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file block_header_decoder.c
4 /// \brief Decodes Block Header from .lzma files
6 // Copyright (C) 2007 Lasse Collin
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 ///////////////////////////////////////////////////////////////////////////////
25 lzma_options_block *options;
31 SEQ_UNCOMPRESSED_SIZE,
32 SEQ_FILTER_FLAGS_INIT,
33 SEQ_FILTER_FLAGS_DECODE,
38 /// Position in variable-length integers
41 /// CRC32 of the Block Header
44 lzma_next_coder filter_flags_decoder;
49 update_sequence(lzma_coder *coder)
51 switch (coder->sequence) {
53 if (coder->options->compressed_size
54 != LZMA_VLI_VALUE_UNKNOWN) {
56 coder->sequence = SEQ_COMPRESSED_SIZE;
62 case SEQ_COMPRESSED_SIZE:
63 if (coder->options->uncompressed_size
64 != LZMA_VLI_VALUE_UNKNOWN) {
66 coder->sequence = SEQ_UNCOMPRESSED_SIZE;
72 case SEQ_UNCOMPRESSED_SIZE:
77 case SEQ_FILTER_FLAGS_DECODE:
78 if (coder->options->filters[coder->pos].id
79 != LZMA_VLI_VALUE_UNKNOWN) {
80 coder->sequence = SEQ_FILTER_FLAGS_INIT;
84 if (coder->options->has_crc32) {
86 coder->sequence = SEQ_CRC32;
91 if (coder->options->padding != 0) {
93 coder->sequence = SEQ_PADDING;
109 block_header_decode(lzma_coder *coder, lzma_allocator *allocator,
110 const uint8_t *restrict in, size_t *restrict in_pos,
111 size_t in_size, uint8_t *restrict out lzma_attribute((unused)),
112 size_t *restrict out_pos lzma_attribute((unused)),
113 size_t out_size lzma_attribute((unused)),
114 lzma_action action lzma_attribute((unused)))
116 while (*in_pos < in_size)
117 switch (coder->sequence) {
119 // Check that the reserved bit is unset. Use HEADER_ERROR
120 // because newer version of liblzma may support the reserved
121 // bit, although it is likely that this is just a broken file.
122 if (in[*in_pos] & 0x40)
123 return LZMA_HEADER_ERROR;
125 // Number of filters: we prepare appropriate amount of
126 // variables for variable-length integer parsing. The
127 // initialization function has already reset the rest
128 // of the values to LZMA_VLI_VALUE_UNKNOWN, which allows
129 // us to later know how many filters there are.
130 for (int i = (int)(in[*in_pos] & 0x07) - 1; i >= 0; --i)
131 coder->options->filters[i].id = 0;
133 // End of Payload Marker flag
134 coder->options->has_eopm = (in[*in_pos] & 0x08) != 0;
136 // Compressed Size: Prepare for variable-length integer
137 // parsing if it is known.
138 if (in[*in_pos] & 0x10)
139 coder->options->compressed_size = 0;
141 // Uncompressed Size: the same.
142 if (in[*in_pos] & 0x20)
143 coder->options->uncompressed_size = 0;
145 // Is Metadata Block flag
146 coder->options->is_metadata = (in[*in_pos] & 0x80) != 0;
148 // We need at least one: Uncompressed Size or EOPM.
149 if (coder->options->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN
150 && !coder->options->has_eopm)
151 return LZMA_DATA_ERROR;
153 // Update header CRC32.
154 coder->crc32 = lzma_crc32(in + *in_pos, 1, coder->crc32);
157 coder->sequence = SEQ_FLAGS_2;
161 // Check that the reserved bits are unset.
162 if (in[*in_pos] & 0xE0)
163 return LZMA_DATA_ERROR;
165 // Get the size of Header Padding.
166 coder->options->padding = in[*in_pos] & 0x1F;
168 coder->crc32 = lzma_crc32(in + *in_pos, 1, coder->crc32);
172 if (update_sequence(coder))
173 return LZMA_STREAM_END;
177 case SEQ_COMPRESSED_SIZE: {
178 // Store the old input position to be used when
179 // updating coder->header_crc32.
180 const size_t in_start = *in_pos;
182 const lzma_ret ret = lzma_vli_decode(
183 &coder->options->compressed_size,
184 &coder->pos, in, in_pos, in_size);
186 const size_t in_used = *in_pos - in_start;
188 coder->options->compressed_reserve += in_used;
189 assert(coder->options->compressed_reserve
190 <= LZMA_VLI_BYTES_MAX);
192 coder->options->header_size += in_used;
194 coder->crc32 = lzma_crc32(in + in_start, in_used,
197 if (ret != LZMA_STREAM_END)
200 if (update_sequence(coder))
201 return LZMA_STREAM_END;
206 case SEQ_UNCOMPRESSED_SIZE: {
207 const size_t in_start = *in_pos;
209 const lzma_ret ret = lzma_vli_decode(
210 &coder->options->uncompressed_size,
211 &coder->pos, in, in_pos, in_size);
213 const size_t in_used = *in_pos - in_start;
215 coder->options->uncompressed_reserve += in_used;
216 assert(coder->options->uncompressed_reserve
217 <= LZMA_VLI_BYTES_MAX);
219 coder->options->header_size += in_used;
221 coder->crc32 = lzma_crc32(in + in_start, in_used,
224 if (ret != LZMA_STREAM_END)
227 if (update_sequence(coder))
228 return LZMA_STREAM_END;
233 case SEQ_FILTER_FLAGS_INIT: {
234 assert(coder->options->filters[coder->pos].id
235 != LZMA_VLI_VALUE_UNKNOWN);
237 const lzma_ret ret = lzma_filter_flags_decoder_init(
238 &coder->filter_flags_decoder, allocator,
239 &coder->options->filters[coder->pos]);
243 coder->sequence = SEQ_FILTER_FLAGS_DECODE;
248 case SEQ_FILTER_FLAGS_DECODE: {
249 const size_t in_start = *in_pos;
251 const lzma_ret ret = coder->filter_flags_decoder.code(
252 coder->filter_flags_decoder.coder,
253 allocator, in, in_pos, in_size,
254 NULL, NULL, 0, LZMA_RUN);
256 const size_t in_used = *in_pos - in_start;
257 coder->options->header_size += in_used;
258 coder->crc32 = lzma_crc32(in + in_start,
259 in_used, coder->crc32);
261 if (ret != LZMA_STREAM_END)
266 if (update_sequence(coder))
267 return LZMA_STREAM_END;
273 assert(coder->options->has_crc32);
275 if (in[*in_pos] != ((coder->crc32 >> (coder->pos * 8)) & 0xFF))
276 return LZMA_DATA_ERROR;
281 // Check if we reached end of the CRC32 field.
282 if (coder->pos == 4) {
283 coder->options->header_size += 4;
285 if (update_sequence(coder))
286 return LZMA_STREAM_END;
292 if (in[*in_pos] != 0x00)
293 return LZMA_DATA_ERROR;
296 ++coder->options->header_size;
299 if (coder->pos < (size_t)(coder->options->padding))
302 return LZMA_STREAM_END;
305 return LZMA_PROG_ERROR;
313 block_header_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
315 lzma_next_coder_end(&coder->filter_flags_decoder, allocator);
316 lzma_free(coder, allocator);
322 lzma_block_header_decoder_init(lzma_next_coder *next,
323 lzma_allocator *allocator, lzma_options_block *options)
325 if (next->coder == NULL) {
326 next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
327 if (next->coder == NULL)
328 return LZMA_MEM_ERROR;
330 next->code = &block_header_decode;
331 next->end = &block_header_decoder_end;
332 next->coder->filter_flags_decoder = LZMA_NEXT_CODER_INIT;
335 // Assume that Compressed Size and Uncompressed Size are unknown.
336 options->compressed_size = LZMA_VLI_VALUE_UNKNOWN;
337 options->uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
339 // We will calculate the sizes of these fields too so that the
340 // application may rewrite the header if it wishes so.
341 options->compressed_reserve = 0;
342 options->uncompressed_reserve = 0;
344 // The Block Flags field is always present, so include its size here
345 // and we don't need to worry about it in block_header_decode().
346 options->header_size = 2;
348 // Reset filters[] to indicate empty list of filters.
349 // See SEQ_FLAGS_1 in block_header_decode() for reasoning of this.
350 for (size_t i = 0; i < 8; ++i) {
351 options->filters[i].id = LZMA_VLI_VALUE_UNKNOWN;
352 options->filters[i].options = NULL;
355 next->coder->options = options;
356 next->coder->sequence = SEQ_FLAGS_1;
357 next->coder->pos = 0;
358 next->coder->crc32 = 0;
364 extern LZMA_API lzma_ret
365 lzma_block_header_decoder(lzma_stream *strm,
366 lzma_options_block *options)
368 lzma_next_strm_init(strm, lzma_block_header_decoder_init, options);
370 strm->internal->supported_actions[LZMA_RUN] = true;