1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file index_decoder.c
4 /// \brief Decodes the Index field
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "index_decoder.h"
29 /// Memory usage limit
35 /// Pointer give by the application, which is set after
36 /// successful decoding.
37 lzma_index
**index_ptr
;
39 /// Number of Records left to decode.
42 /// The most recent Unpadded Size field
43 lzma_vli unpadded_size
;
45 /// The most recent Uncompressed Size field
46 lzma_vli uncompressed_size
;
48 /// Position in integers
51 /// CRC32 of the List of Records field
57 index_decode(void *coder_ptr
, const lzma_allocator
*allocator
,
58 const uint8_t *restrict in
, size_t *restrict in_pos
,
60 uint8_t *restrict out
lzma_attribute((__unused__
)),
61 size_t *restrict out_pos
lzma_attribute((__unused__
)),
62 size_t out_size
lzma_attribute((__unused__
)),
63 lzma_action action
lzma_attribute((__unused__
)))
65 lzma_index_coder
*coder
= coder_ptr
;
67 // Similar optimization as in index_encoder.c
68 const size_t in_start
= *in_pos
;
69 lzma_ret ret
= LZMA_OK
;
71 while (*in_pos
< in_size
)
72 switch (coder
->sequence
) {
74 // Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
75 // LZMA_FORMAT_ERROR, because a typical usage case for Index
76 // decoder is when parsing the Stream backwards. If seeking
77 // backward from the Stream Footer gives us something that
78 // doesn't begin with Index Indicator, the file is considered
79 // corrupt, not "programming error" or "unrecognized file
80 // format". One could argue that the application should
81 // verify the Index Indicator before trying to decode the
82 // Index, but well, I suppose it is simpler this way.
83 if (in
[(*in_pos
)++] != INDEX_INDICATOR
)
84 return LZMA_DATA_ERROR
;
86 coder
->sequence
= SEQ_COUNT
;
90 ret
= lzma_vli_decode(&coder
->count
, &coder
->pos
,
92 if (ret
!= LZMA_STREAM_END
)
96 coder
->sequence
= SEQ_MEMUSAGE
;
101 if (lzma_index_memusage(1, coder
->count
) > coder
->memlimit
) {
102 ret
= LZMA_MEMLIMIT_ERROR
;
106 // Tell the Index handling code how many Records this
107 // Index has to allow it to allocate memory more efficiently.
108 lzma_index_prealloc(coder
->index
, coder
->count
);
111 coder
->sequence
= coder
->count
== 0
112 ? SEQ_PADDING_INIT
: SEQ_UNPADDED
;
116 case SEQ_UNCOMPRESSED
: {
117 lzma_vli
*size
= coder
->sequence
== SEQ_UNPADDED
118 ? &coder
->unpadded_size
119 : &coder
->uncompressed_size
;
121 ret
= lzma_vli_decode(size
, &coder
->pos
,
122 in
, in_pos
, in_size
);
123 if (ret
!= LZMA_STREAM_END
)
129 if (coder
->sequence
== SEQ_UNPADDED
) {
130 // Validate that encoded Unpadded Size isn't too small
132 if (coder
->unpadded_size
< UNPADDED_SIZE_MIN
133 || coder
->unpadded_size
135 return LZMA_DATA_ERROR
;
137 coder
->sequence
= SEQ_UNCOMPRESSED
;
139 // Add the decoded Record to the Index.
140 return_if_error(lzma_index_append(
141 coder
->index
, allocator
,
142 coder
->unpadded_size
,
143 coder
->uncompressed_size
));
145 // Check if this was the last Record.
146 coder
->sequence
= --coder
->count
== 0
154 case SEQ_PADDING_INIT
:
155 coder
->pos
= lzma_index_padding_size(coder
->index
);
156 coder
->sequence
= SEQ_PADDING
;
161 if (coder
->pos
> 0) {
163 if (in
[(*in_pos
)++] != 0x00)
164 return LZMA_DATA_ERROR
;
169 // Finish the CRC32 calculation.
170 coder
->crc32
= lzma_crc32(in
+ in_start
,
171 *in_pos
- in_start
, coder
->crc32
);
173 coder
->sequence
= SEQ_CRC32
;
179 if (*in_pos
== in_size
)
182 if (((coder
->crc32
>> (coder
->pos
* 8)) & 0xFF)
183 != in
[(*in_pos
)++]) {
184 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
185 return LZMA_DATA_ERROR
;
189 } while (++coder
->pos
< 4);
191 // Decoding was successful, now we can let the application
192 // see the decoded Index.
193 *coder
->index_ptr
= coder
->index
;
195 // Make index NULL so we don't free it unintentionally.
198 return LZMA_STREAM_END
;
202 return LZMA_PROG_ERROR
;
208 // Avoid null pointer + 0 (undefined behavior) in "in + in_start".
209 // In such a case we had no input and thus in_used == 0.
211 const size_t in_used
= *in_pos
- in_start
;
213 coder
->crc32
= lzma_crc32(in
+ in_start
,
214 in_used
, coder
->crc32
);
222 index_decoder_end(void *coder_ptr
, const lzma_allocator
*allocator
)
224 lzma_index_coder
*coder
= coder_ptr
;
225 lzma_index_end(coder
->index
, allocator
);
226 lzma_free(coder
, allocator
);
232 index_decoder_memconfig(void *coder_ptr
, uint64_t *memusage
,
233 uint64_t *old_memlimit
, uint64_t new_memlimit
)
235 lzma_index_coder
*coder
= coder_ptr
;
237 *memusage
= lzma_index_memusage(1, coder
->count
);
238 *old_memlimit
= coder
->memlimit
;
240 if (new_memlimit
!= 0) {
241 if (new_memlimit
< *memusage
)
242 return LZMA_MEMLIMIT_ERROR
;
244 coder
->memlimit
= new_memlimit
;
252 index_decoder_reset(lzma_index_coder
*coder
, const lzma_allocator
*allocator
,
253 lzma_index
**i
, uint64_t memlimit
)
255 // Remember the pointer given by the application. We will set it
256 // to point to the decoded Index only if decoding is successful.
257 // Before that, keep it NULL so that applications can always safely
258 // pass it to lzma_index_end() no matter did decoding succeed or not.
259 coder
->index_ptr
= i
;
262 // We always allocate a new lzma_index.
263 coder
->index
= lzma_index_init(allocator
);
264 if (coder
->index
== NULL
)
265 return LZMA_MEM_ERROR
;
267 // Initialize the rest.
268 coder
->sequence
= SEQ_INDICATOR
;
269 coder
->memlimit
= my_max(1, memlimit
);
270 coder
->count
= 0; // Needs to be initialized due to _memconfig().
279 lzma_index_decoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
280 lzma_index
**i
, uint64_t memlimit
)
282 lzma_next_coder_init(&lzma_index_decoder_init
, next
, allocator
);
285 return LZMA_PROG_ERROR
;
287 lzma_index_coder
*coder
= next
->coder
;
289 coder
= lzma_alloc(sizeof(lzma_index_coder
), allocator
);
291 return LZMA_MEM_ERROR
;
294 next
->code
= &index_decode
;
295 next
->end
= &index_decoder_end
;
296 next
->memconfig
= &index_decoder_memconfig
;
299 lzma_index_end(coder
->index
, allocator
);
302 return index_decoder_reset(coder
, allocator
, i
, memlimit
);
306 extern LZMA_API(lzma_ret
)
307 lzma_index_decoder(lzma_stream
*strm
, lzma_index
**i
, uint64_t memlimit
)
309 lzma_next_strm_init(lzma_index_decoder_init
, strm
, i
, memlimit
);
311 strm
->internal
->supported_actions
[LZMA_RUN
] = true;
312 strm
->internal
->supported_actions
[LZMA_FINISH
] = true;
318 extern LZMA_API(lzma_ret
)
319 lzma_index_buffer_decode(lzma_index
**i
, uint64_t *memlimit
,
320 const lzma_allocator
*allocator
,
321 const uint8_t *in
, size_t *in_pos
, size_t in_size
)
324 if (i
== NULL
|| memlimit
== NULL
325 || in
== NULL
|| in_pos
== NULL
|| *in_pos
> in_size
)
326 return LZMA_PROG_ERROR
;
328 // Initialize the decoder.
329 lzma_index_coder coder
;
330 return_if_error(index_decoder_reset(&coder
, allocator
, i
, *memlimit
));
332 // Store the input start position so that we can restore it in case
334 const size_t in_start
= *in_pos
;
336 // Do the actual decoding.
337 lzma_ret ret
= index_decode(&coder
, allocator
, in
, in_pos
, in_size
,
338 NULL
, NULL
, 0, LZMA_RUN
);
340 if (ret
== LZMA_STREAM_END
) {
343 // Something went wrong, free the Index structure and restore
344 // the input position.
345 lzma_index_end(coder
.index
, allocator
);
348 if (ret
== LZMA_OK
) {
349 // The input is truncated or otherwise corrupt.
350 // Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
351 // like lzma_vli_decode() does in single-call mode.
352 ret
= LZMA_DATA_ERROR
;
354 } else if (ret
== LZMA_MEMLIMIT_ERROR
) {
355 // Tell the caller how much memory would have
357 *memlimit
= lzma_index_memusage(1, coder
.count
);