Fix version.sh compatiblity with Solaris
[xz/debian.git] / src / liblzma / common / index_decoder.c
blob4bcb306921157810ab5e3efa7d1dd59a9eccf2ce
1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file index_decoder.c
6 /// \brief Decodes the Index field
7 //
8 // Author: Lasse Collin
9 //
10 ///////////////////////////////////////////////////////////////////////////////
12 #include "index_decoder.h"
13 #include "check.h"
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;
28 /// Memory usage limit
29 uint64_t memlimit;
31 /// Target Index
32 lzma_index *index;
34 /// Pointer give by the application, which is set after
35 /// successful decoding.
36 lzma_index **index_ptr;
38 /// Number of Records left to decode.
39 lzma_vli count;
41 /// The most recent Unpadded Size field
42 lzma_vli unpadded_size;
44 /// The most recent Uncompressed Size field
45 lzma_vli uncompressed_size;
47 /// Position in integers
48 size_t pos;
50 /// CRC32 of the List of Records field
51 uint32_t crc32;
52 } lzma_index_coder;
55 static lzma_ret
56 index_decode(void *coder_ptr, const lzma_allocator *allocator,
57 const uint8_t *restrict in, size_t *restrict in_pos,
58 size_t in_size,
59 uint8_t *restrict out lzma_attribute((__unused__)),
60 size_t *restrict out_pos lzma_attribute((__unused__)),
61 size_t out_size lzma_attribute((__unused__)),
62 lzma_action action lzma_attribute((__unused__)))
64 lzma_index_coder *coder = coder_ptr;
66 // Similar optimization as in index_encoder.c
67 const size_t in_start = *in_pos;
68 lzma_ret ret = LZMA_OK;
70 while (*in_pos < in_size)
71 switch (coder->sequence) {
72 case SEQ_INDICATOR:
73 // Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
74 // LZMA_FORMAT_ERROR, because a typical usage case for Index
75 // decoder is when parsing the Stream backwards. If seeking
76 // backward from the Stream Footer gives us something that
77 // doesn't begin with Index Indicator, the file is considered
78 // corrupt, not "programming error" or "unrecognized file
79 // format". One could argue that the application should
80 // verify the Index Indicator before trying to decode the
81 // Index, but well, I suppose it is simpler this way.
82 if (in[(*in_pos)++] != INDEX_INDICATOR)
83 return LZMA_DATA_ERROR;
85 coder->sequence = SEQ_COUNT;
86 break;
88 case SEQ_COUNT:
89 ret = lzma_vli_decode(&coder->count, &coder->pos,
90 in, in_pos, in_size);
91 if (ret != LZMA_STREAM_END)
92 goto out;
94 coder->pos = 0;
95 coder->sequence = SEQ_MEMUSAGE;
97 // Fall through
99 case SEQ_MEMUSAGE:
100 if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
101 ret = LZMA_MEMLIMIT_ERROR;
102 goto out;
105 // Tell the Index handling code how many Records this
106 // Index has to allow it to allocate memory more efficiently.
107 lzma_index_prealloc(coder->index, coder->count);
109 ret = LZMA_OK;
110 coder->sequence = coder->count == 0
111 ? SEQ_PADDING_INIT : SEQ_UNPADDED;
112 break;
114 case SEQ_UNPADDED:
115 case SEQ_UNCOMPRESSED: {
116 lzma_vli *size = coder->sequence == SEQ_UNPADDED
117 ? &coder->unpadded_size
118 : &coder->uncompressed_size;
120 ret = lzma_vli_decode(size, &coder->pos,
121 in, in_pos, in_size);
122 if (ret != LZMA_STREAM_END)
123 goto out;
125 ret = LZMA_OK;
126 coder->pos = 0;
128 if (coder->sequence == SEQ_UNPADDED) {
129 // Validate that encoded Unpadded Size isn't too small
130 // or too big.
131 if (coder->unpadded_size < UNPADDED_SIZE_MIN
132 || coder->unpadded_size
133 > UNPADDED_SIZE_MAX)
134 return LZMA_DATA_ERROR;
136 coder->sequence = SEQ_UNCOMPRESSED;
137 } else {
138 // Add the decoded Record to the Index.
139 return_if_error(lzma_index_append(
140 coder->index, allocator,
141 coder->unpadded_size,
142 coder->uncompressed_size));
144 // Check if this was the last Record.
145 coder->sequence = --coder->count == 0
146 ? SEQ_PADDING_INIT
147 : SEQ_UNPADDED;
150 break;
153 case SEQ_PADDING_INIT:
154 coder->pos = lzma_index_padding_size(coder->index);
155 coder->sequence = SEQ_PADDING;
157 // Fall through
159 case SEQ_PADDING:
160 if (coder->pos > 0) {
161 --coder->pos;
162 if (in[(*in_pos)++] != 0x00)
163 return LZMA_DATA_ERROR;
165 break;
168 // Finish the CRC32 calculation.
169 coder->crc32 = lzma_crc32(in + in_start,
170 *in_pos - in_start, coder->crc32);
172 coder->sequence = SEQ_CRC32;
174 // Fall through
176 case SEQ_CRC32:
177 do {
178 if (*in_pos == in_size)
179 return LZMA_OK;
181 if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
182 != in[(*in_pos)++]) {
183 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
184 return LZMA_DATA_ERROR;
185 #endif
188 } while (++coder->pos < 4);
190 // Decoding was successful, now we can let the application
191 // see the decoded Index.
192 *coder->index_ptr = coder->index;
194 // Make index NULL so we don't free it unintentionally.
195 coder->index = NULL;
197 return LZMA_STREAM_END;
199 default:
200 assert(0);
201 return LZMA_PROG_ERROR;
204 out:
205 // Update the CRC32.
207 // Avoid null pointer + 0 (undefined behavior) in "in + in_start".
208 // In such a case we had no input and thus in_used == 0.
210 const size_t in_used = *in_pos - in_start;
211 if (in_used > 0)
212 coder->crc32 = lzma_crc32(in + in_start,
213 in_used, coder->crc32);
216 return ret;
220 static void
221 index_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
223 lzma_index_coder *coder = coder_ptr;
224 lzma_index_end(coder->index, allocator);
225 lzma_free(coder, allocator);
226 return;
230 static lzma_ret
231 index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
232 uint64_t *old_memlimit, uint64_t new_memlimit)
234 lzma_index_coder *coder = coder_ptr;
236 *memusage = lzma_index_memusage(1, coder->count);
237 *old_memlimit = coder->memlimit;
239 if (new_memlimit != 0) {
240 if (new_memlimit < *memusage)
241 return LZMA_MEMLIMIT_ERROR;
243 coder->memlimit = new_memlimit;
246 return LZMA_OK;
250 static lzma_ret
251 index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
252 lzma_index **i, uint64_t memlimit)
254 // Remember the pointer given by the application. We will set it
255 // to point to the decoded Index only if decoding is successful.
256 // Before that, keep it NULL so that applications can always safely
257 // pass it to lzma_index_end() no matter did decoding succeed or not.
258 coder->index_ptr = i;
259 *i = NULL;
261 // We always allocate a new lzma_index.
262 coder->index = lzma_index_init(allocator);
263 if (coder->index == NULL)
264 return LZMA_MEM_ERROR;
266 // Initialize the rest.
267 coder->sequence = SEQ_INDICATOR;
268 coder->memlimit = my_max(1, memlimit);
269 coder->count = 0; // Needs to be initialized due to _memconfig().
270 coder->pos = 0;
271 coder->crc32 = 0;
273 return LZMA_OK;
277 extern lzma_ret
278 lzma_index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
279 lzma_index **i, uint64_t memlimit)
281 lzma_next_coder_init(&lzma_index_decoder_init, next, allocator);
283 if (i == NULL)
284 return LZMA_PROG_ERROR;
286 lzma_index_coder *coder = next->coder;
287 if (coder == NULL) {
288 coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
289 if (coder == NULL)
290 return LZMA_MEM_ERROR;
292 next->coder = coder;
293 next->code = &index_decode;
294 next->end = &index_decoder_end;
295 next->memconfig = &index_decoder_memconfig;
296 coder->index = NULL;
297 } else {
298 lzma_index_end(coder->index, allocator);
301 return index_decoder_reset(coder, allocator, i, memlimit);
305 extern LZMA_API(lzma_ret)
306 lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
308 // If i isn't NULL, *i must always be initialized due to
309 // the wording in the API docs. This way it is initialized
310 // if we return LZMA_PROG_ERROR due to strm == NULL.
311 if (i != NULL)
312 *i = NULL;
314 lzma_next_strm_init(lzma_index_decoder_init, strm, i, memlimit);
316 strm->internal->supported_actions[LZMA_RUN] = true;
317 strm->internal->supported_actions[LZMA_FINISH] = true;
319 return LZMA_OK;
323 extern LZMA_API(lzma_ret)
324 lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
325 const lzma_allocator *allocator,
326 const uint8_t *in, size_t *in_pos, size_t in_size)
328 // If i isn't NULL, *i must always be initialized due to
329 // the wording in the API docs.
330 if (i != NULL)
331 *i = NULL;
333 // Sanity checks
334 if (i == NULL || memlimit == NULL
335 || in == NULL || in_pos == NULL || *in_pos > in_size)
336 return LZMA_PROG_ERROR;
338 // Initialize the decoder.
339 lzma_index_coder coder;
340 return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
342 // Store the input start position so that we can restore it in case
343 // of an error.
344 const size_t in_start = *in_pos;
346 // Do the actual decoding.
347 lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
348 NULL, NULL, 0, LZMA_RUN);
350 if (ret == LZMA_STREAM_END) {
351 ret = LZMA_OK;
352 } else {
353 // Something went wrong, free the Index structure and restore
354 // the input position.
355 lzma_index_end(coder.index, allocator);
356 *in_pos = in_start;
358 if (ret == LZMA_OK) {
359 // The input is truncated or otherwise corrupt.
360 // Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
361 // like lzma_vli_decode() does in single-call mode.
362 ret = LZMA_DATA_ERROR;
364 } else if (ret == LZMA_MEMLIMIT_ERROR) {
365 // Tell the caller how much memory would have
366 // been needed.
367 *memlimit = lzma_index_memusage(1, coder.count);
371 return ret;