1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file block_decoder.c
4 /// \brief Decodes .lzma Blocks
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 ///////////////////////////////////////////////////////////////////////////////
20 #include "block_decoder.h"
21 #include "block_private.h"
22 #include "raw_decoder.h"
33 /// The filters in the chain; initialized with lzma_raw_decoder_init().
36 /// Decoding options; we also write Compressed Size and Uncompressed
37 /// Size back to this structure when the encoding has been finished.
38 lzma_options_block *options;
40 /// Compressed Size calculated while encoding
41 lzma_vli compressed_size;
43 /// Uncompressed Size calculated while encoding
44 lzma_vli uncompressed_size;
46 /// Maximum allowed Compressed Size; this takes into account the
47 /// size of the Block Header and Check fields when Compressed Size
49 lzma_vli compressed_limit;
51 /// Position when reading the Check field
54 /// Check of the uncompressed data
60 block_decode(lzma_coder *coder, lzma_allocator *allocator,
61 const uint8_t *restrict in, size_t *restrict in_pos,
62 size_t in_size, uint8_t *restrict out,
63 size_t *restrict out_pos, size_t out_size, lzma_action action)
65 switch (coder->sequence) {
67 if (*out_pos >= out_size)
70 const size_t in_start = *in_pos;
71 const size_t out_start = *out_pos;
73 const lzma_ret ret = coder->next.code(coder->next.coder,
74 allocator, in, in_pos, in_size,
75 out, out_pos, out_size, action);
77 const size_t in_used = *in_pos - in_start;
78 const size_t out_used = *out_pos - out_start;
80 // NOTE: We compare to compressed_limit here, which prevents
81 // the total size of the Block growing past LZMA_VLI_VALUE_MAX.
82 if (update_size(&coder->compressed_size, in_used,
83 coder->compressed_limit)
84 || update_size(&coder->uncompressed_size,
86 coder->options->uncompressed_size))
87 return LZMA_DATA_ERROR;
89 lzma_check_update(&coder->check, coder->options->check,
90 out + out_start, out_used);
92 if (ret != LZMA_STREAM_END)
95 coder->sequence = SEQ_PADDING;
101 // If Compressed Data is padded to a multiple of four bytes.
102 while (coder->compressed_size & 3) {
103 if (*in_pos >= in_size)
106 if (in[(*in_pos)++] != 0x00)
107 return LZMA_DATA_ERROR;
109 if (update_size(&coder->compressed_size, 1,
110 coder->compressed_limit))
111 return LZMA_DATA_ERROR;
114 // Compressed and Uncompressed Sizes are now at their final
115 // values. Verify that they match the values given to us.
116 if (!is_size_valid(coder->compressed_size,
117 coder->options->compressed_size)
118 || !is_size_valid(coder->uncompressed_size,
119 coder->options->uncompressed_size))
120 return LZMA_DATA_ERROR;
122 // Copy the values into coder->options. The caller
123 // may use this information to construct Index.
124 coder->options->compressed_size = coder->compressed_size;
125 coder->options->uncompressed_size = coder->uncompressed_size;
127 if (coder->options->check == LZMA_CHECK_NONE)
128 return LZMA_STREAM_END;
130 lzma_check_finish(&coder->check, coder->options->check);
131 coder->sequence = SEQ_CHECK;
136 while (*in_pos < in_size) {
137 if (in[(*in_pos)++] != coder->check.buffer[
139 return LZMA_DATA_ERROR;
141 if (++coder->check_pos == lzma_check_sizes[
142 coder->options->check])
143 return LZMA_STREAM_END;
149 return LZMA_PROG_ERROR;
154 block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
156 lzma_next_coder_end(&coder->next, allocator);
157 lzma_free(coder, allocator);
163 block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
164 lzma_options_block *options)
166 // While lzma_block_total_size_get() is meant to calculate the Total
167 // Size, it also validates the options excluding the filters.
168 if (lzma_block_total_size_get(options) == 0)
169 return LZMA_PROG_ERROR;
171 // Allocate and initialize *next->coder if needed.
172 if (next->coder == NULL) {
173 next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
174 if (next->coder == NULL)
175 return LZMA_MEM_ERROR;
177 next->code = &block_decode;
178 next->end = &block_decoder_end;
179 next->coder->next = LZMA_NEXT_CODER_INIT;
182 // Basic initializations
183 next->coder->sequence = SEQ_CODE;
184 next->coder->options = options;
185 next->coder->compressed_size = 0;
186 next->coder->uncompressed_size = 0;
188 // If Compressed Size is not known, we calculate the maximum allowed
189 // value so that Total Size of the Block still is a valid VLI and
190 // a multiple of four.
191 next->coder->compressed_limit
192 = options->compressed_size == LZMA_VLI_VALUE_UNKNOWN
193 ? (LZMA_VLI_VALUE_MAX & ~LZMA_VLI_C(3))
194 - options->header_size
195 - lzma_check_sizes[options->check]
196 : options->compressed_size;
198 // Initialize the check
199 next->coder->check_pos = 0;
200 return_if_error(lzma_check_init(&next->coder->check, options->check));
202 return lzma_raw_decoder_init(&next->coder->next, allocator,
208 lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
209 lzma_options_block *options)
211 lzma_next_coder_init(block_decoder_init, next, allocator, options);
215 extern LZMA_API lzma_ret
216 lzma_block_decoder(lzma_stream *strm, lzma_options_block *options)
218 lzma_next_strm_init(strm, block_decoder_init, options);
220 strm->internal->supported_actions[LZMA_RUN] = true;
221 strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;