/src/xz/src/liblzma/lzma/lzma2_decoder.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: 0BSD |
2 | | |
3 | | /////////////////////////////////////////////////////////////////////////////// |
4 | | // |
5 | | /// \file lzma2_decoder.c |
6 | | /// \brief LZMA2 decoder |
7 | | /// |
8 | | // Authors: Igor Pavlov |
9 | | // Lasse Collin |
10 | | // |
11 | | /////////////////////////////////////////////////////////////////////////////// |
12 | | |
13 | | #include "lzma2_decoder.h" |
14 | | #include "lz_decoder.h" |
15 | | #include "lzma_decoder.h" |
16 | | |
17 | | |
18 | | typedef struct { |
19 | | enum sequence { |
20 | | SEQ_CONTROL, |
21 | | SEQ_UNCOMPRESSED_1, |
22 | | SEQ_UNCOMPRESSED_2, |
23 | | SEQ_COMPRESSED_0, |
24 | | SEQ_COMPRESSED_1, |
25 | | SEQ_PROPERTIES, |
26 | | SEQ_LZMA, |
27 | | SEQ_COPY, |
28 | | } sequence; |
29 | | |
30 | | /// Sequence after the size fields have been decoded. |
31 | | enum sequence next_sequence; |
32 | | |
33 | | /// LZMA decoder |
34 | | lzma_lz_decoder lzma; |
35 | | |
36 | | /// Uncompressed size of LZMA chunk |
37 | | size_t uncompressed_size; |
38 | | |
39 | | /// Compressed size of the chunk (naturally equals to uncompressed |
40 | | /// size of uncompressed chunk) |
41 | | size_t compressed_size; |
42 | | |
43 | | /// True if properties are needed. This is false before the |
44 | | /// first LZMA chunk. |
45 | | bool need_properties; |
46 | | |
47 | | /// True if dictionary reset is needed. This is false before the |
48 | | /// first chunk (LZMA or uncompressed). |
49 | | bool need_dictionary_reset; |
50 | | |
51 | | lzma_options_lzma options; |
52 | | } lzma_lzma2_coder; |
53 | | |
54 | | |
55 | | static lzma_ret |
56 | | lzma2_decode(void *coder_ptr, lzma_dict *restrict dict, |
57 | | const uint8_t *restrict in, size_t *restrict in_pos, |
58 | | size_t in_size) |
59 | 2.58k | { |
60 | 2.58k | lzma_lzma2_coder *restrict coder = coder_ptr; |
61 | | |
62 | | // With SEQ_LZMA it is possible that no new input is needed to do |
63 | | // some progress. The rest of the sequences assume that there is |
64 | | // at least one byte of input. |
65 | 4.90k | while (*in_pos < in_size || coder->sequence == SEQ_LZMA) |
66 | 4.46k | switch (coder->sequence) { |
67 | 772 | case SEQ_CONTROL: { |
68 | 772 | const uint32_t control = in[*in_pos]; |
69 | 772 | ++*in_pos; |
70 | | |
71 | | // End marker |
72 | 772 | if (control == 0x00) |
73 | 34 | return LZMA_STREAM_END; |
74 | | |
75 | 738 | if (control >= 0xE0 || control == 1) { |
76 | | // Dictionary reset implies that next LZMA chunk has |
77 | | // to set new properties. |
78 | 720 | coder->need_properties = true; |
79 | 720 | coder->need_dictionary_reset = true; |
80 | 720 | } else if (coder->need_dictionary_reset) { |
81 | 1 | return LZMA_DATA_ERROR; |
82 | 1 | } |
83 | | |
84 | 737 | if (control >= 0x80) { |
85 | | // LZMA chunk. The highest five bits of the |
86 | | // uncompressed size are taken from the control byte. |
87 | 248 | coder->uncompressed_size = (control & 0x1F) << 16; |
88 | 248 | coder->sequence = SEQ_UNCOMPRESSED_1; |
89 | | |
90 | | // See if there are new properties or if we need to |
91 | | // reset the state. |
92 | 248 | if (control >= 0xC0) { |
93 | | // When there are new properties, state reset |
94 | | // is done at SEQ_PROPERTIES. |
95 | 245 | coder->need_properties = false; |
96 | 245 | coder->next_sequence = SEQ_PROPERTIES; |
97 | | |
98 | 245 | } else if (coder->need_properties) { |
99 | 3 | return LZMA_DATA_ERROR; |
100 | | |
101 | 3 | } else { |
102 | 0 | coder->next_sequence = SEQ_LZMA; |
103 | | |
104 | | // If only state reset is wanted with old |
105 | | // properties, do the resetting here for |
106 | | // simplicity. |
107 | 0 | if (control >= 0xA0) |
108 | 0 | coder->lzma.reset(coder->lzma.coder, |
109 | 0 | &coder->options); |
110 | 0 | } |
111 | 489 | } else { |
112 | | // Invalid control values |
113 | 489 | if (control > 2) |
114 | 4 | return LZMA_DATA_ERROR; |
115 | | |
116 | | // It's uncompressed chunk |
117 | 485 | coder->sequence = SEQ_COMPRESSED_0; |
118 | 485 | coder->next_sequence = SEQ_COPY; |
119 | 485 | } |
120 | | |
121 | 730 | if (coder->need_dictionary_reset) { |
122 | | // Finish the dictionary reset and let the caller |
123 | | // flush the dictionary to the actual output buffer. |
124 | 720 | coder->need_dictionary_reset = false; |
125 | 720 | dict_reset(dict); |
126 | 720 | return LZMA_OK; |
127 | 720 | } |
128 | | |
129 | 10 | break; |
130 | 730 | } |
131 | | |
132 | 245 | case SEQ_UNCOMPRESSED_1: |
133 | 245 | coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8; |
134 | 245 | coder->sequence = SEQ_UNCOMPRESSED_2; |
135 | 245 | break; |
136 | | |
137 | 245 | case SEQ_UNCOMPRESSED_2: |
138 | 245 | coder->uncompressed_size += in[(*in_pos)++] + 1U; |
139 | 245 | coder->sequence = SEQ_COMPRESSED_0; |
140 | 245 | coder->lzma.set_uncompressed(coder->lzma.coder, |
141 | 245 | coder->uncompressed_size, false); |
142 | 245 | break; |
143 | | |
144 | 730 | case SEQ_COMPRESSED_0: |
145 | 730 | coder->compressed_size = (uint32_t)(in[(*in_pos)++]) << 8; |
146 | 730 | coder->sequence = SEQ_COMPRESSED_1; |
147 | 730 | break; |
148 | | |
149 | 730 | case SEQ_COMPRESSED_1: |
150 | 730 | coder->compressed_size += in[(*in_pos)++] + 1U; |
151 | 730 | coder->sequence = coder->next_sequence; |
152 | 730 | break; |
153 | | |
154 | 245 | case SEQ_PROPERTIES: |
155 | 245 | if (lzma_lzma_lclppb_decode(&coder->options, in[(*in_pos)++])) |
156 | 1 | return LZMA_DATA_ERROR; |
157 | | |
158 | 244 | coder->lzma.reset(coder->lzma.coder, &coder->options); |
159 | | |
160 | 244 | coder->sequence = SEQ_LZMA; |
161 | 244 | break; |
162 | | |
163 | 839 | case SEQ_LZMA: { |
164 | | // Store the start offset so that we can update |
165 | | // coder->compressed_size later. |
166 | 839 | const size_t in_start = *in_pos; |
167 | | |
168 | | // LZMA2 stream ends with the end marker (0x00), so there |
169 | | // must be at least one byte after this chunk. Let the |
170 | | // decoder read at most one byte past the end of the chunk. |
171 | | // If the decoder reads the extra byte, then the input is |
172 | | // corrupt. This way we won't produce (much) junk output |
173 | | // from the input bytes that are past the end of this chunk. |
174 | | // The extra byte makes things simpler, because we can ignore |
175 | | // uncompressed size and not think about some corner cases. |
176 | | // |
177 | | // NOTE: It's not a security issue (information leak) to |
178 | | // pass more input to the decoder than the chunk size. |
179 | | // If an attacker can modify the compressed input, then the |
180 | | // attacker can modify a chunk header so that it specifies |
181 | | // a too large compressed size. liblzma <= 5.8.3 didn't |
182 | | // have in_limit; in_size was passed to the decoder as is. |
183 | 839 | const size_t in_limit = *in_pos + my_min(in_size - *in_pos, |
184 | 839 | coder->compressed_size + 1); |
185 | | |
186 | | // Decode from in[] to *dict. |
187 | 839 | const lzma_ret ret = coder->lzma.code(coder->lzma.coder, |
188 | 839 | dict, in, in_pos, in_limit); |
189 | | |
190 | | // Validate and update coder->compressed_size. If the input |
191 | | // is corrupt, let the caller still see the newly-decoded |
192 | | // output even if it is (partially) corrupt. It might allow |
193 | | // users to recover a small amount of useful data. |
194 | 839 | const size_t in_used = *in_pos - in_start; |
195 | 839 | if (in_used > coder->compressed_size) |
196 | 6 | return LZMA_DATA_ERROR; |
197 | | |
198 | 833 | coder->compressed_size -= in_used; |
199 | | |
200 | | // Return if we didn't finish the chunk, or an error occurred. |
201 | 833 | if (ret != LZMA_STREAM_END) |
202 | 833 | return ret; |
203 | | |
204 | | // The LZMA decoder must have consumed the whole chunk now. |
205 | | // We don't need to worry about uncompressed size since it |
206 | | // is checked by the LZMA decoder. |
207 | 0 | if (coder->compressed_size != 0) |
208 | 0 | return LZMA_DATA_ERROR; |
209 | | |
210 | 0 | coder->sequence = SEQ_CONTROL; |
211 | 0 | break; |
212 | 0 | } |
213 | | |
214 | 662 | case SEQ_COPY: { |
215 | | // Copy from input to the dictionary as is. |
216 | 662 | dict_write(dict, in, in_pos, in_size, &coder->compressed_size); |
217 | 662 | if (coder->compressed_size != 0) |
218 | 555 | return LZMA_OK; |
219 | | |
220 | 107 | coder->sequence = SEQ_CONTROL; |
221 | 107 | break; |
222 | 662 | } |
223 | | |
224 | 0 | default: |
225 | 0 | assert(0); |
226 | 0 | return LZMA_PROG_ERROR; |
227 | 4.46k | } |
228 | | |
229 | 432 | return LZMA_OK; |
230 | 2.58k | } |
231 | | |
232 | | |
233 | | static void |
234 | | lzma2_decoder_end(void *coder_ptr, const lzma_allocator *allocator) |
235 | 666 | { |
236 | 666 | lzma_lzma2_coder *coder = coder_ptr; |
237 | | |
238 | 666 | assert(coder->lzma.end == NULL); |
239 | 666 | lzma_free(coder->lzma.coder, allocator); |
240 | | |
241 | 666 | lzma_free(coder, allocator); |
242 | | |
243 | 666 | return; |
244 | 666 | } |
245 | | |
246 | | |
247 | | static lzma_ret |
248 | | lzma2_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator, |
249 | | lzma_vli id lzma_attribute((__unused__)), const void *opt, |
250 | | lzma_lz_options *lz_options) |
251 | 666 | { |
252 | 666 | lzma_lzma2_coder *coder = lz->coder; |
253 | 666 | if (coder == NULL) { |
254 | 666 | coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator); |
255 | 666 | if (coder == NULL) |
256 | 0 | return LZMA_MEM_ERROR; |
257 | | |
258 | 666 | lz->coder = coder; |
259 | 666 | lz->code = &lzma2_decode; |
260 | 666 | lz->end = &lzma2_decoder_end; |
261 | | |
262 | 666 | coder->lzma = LZMA_LZ_DECODER_INIT; |
263 | 666 | } |
264 | | |
265 | 666 | const lzma_options_lzma *options = opt; |
266 | | |
267 | 666 | coder->sequence = SEQ_CONTROL; |
268 | 666 | coder->need_properties = true; |
269 | 666 | coder->need_dictionary_reset = options->preset_dict == NULL |
270 | 0 | || options->preset_dict_size == 0; |
271 | | |
272 | 666 | return lzma_lzma_decoder_create(&coder->lzma, |
273 | 666 | allocator, options, lz_options); |
274 | 666 | } |
275 | | |
276 | | |
277 | | extern lzma_ret |
278 | | lzma_lzma2_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, |
279 | | const lzma_filter_info *filters) |
280 | 666 | { |
281 | | // LZMA2 can only be the last filter in the chain. This is enforced |
282 | | // by the raw_decoder initialization. |
283 | 666 | assert(filters[1].init == NULL); |
284 | | |
285 | 666 | return lzma_lz_decoder_init(next, allocator, filters, |
286 | 666 | &lzma2_decoder_init); |
287 | 666 | } |
288 | | |
289 | | |
290 | | extern uint64_t |
291 | | lzma_lzma2_decoder_memusage(const void *options) |
292 | 666 | { |
293 | 666 | return sizeof(lzma_lzma2_coder) |
294 | 666 | + lzma_lzma_decoder_memusage_nocheck(options); |
295 | 666 | } |
296 | | |
297 | | |
298 | | extern lzma_ret |
299 | | lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator, |
300 | | const uint8_t *props, size_t props_size) |
301 | 671 | { |
302 | 671 | if (props_size != 1) |
303 | 1 | return LZMA_OPTIONS_ERROR; |
304 | | |
305 | | // Check that reserved bits are unset. |
306 | 670 | if (props[0] & 0xC0) |
307 | 1 | return LZMA_OPTIONS_ERROR; |
308 | | |
309 | | // Decode the dictionary size. |
310 | 669 | if (props[0] > 40) |
311 | 1 | return LZMA_OPTIONS_ERROR; |
312 | | |
313 | 668 | lzma_options_lzma *opt = lzma_alloc( |
314 | 668 | sizeof(lzma_options_lzma), allocator); |
315 | 668 | if (opt == NULL) |
316 | 0 | return LZMA_MEM_ERROR; |
317 | | |
318 | 668 | if (props[0] == 40) { |
319 | 1 | opt->dict_size = UINT32_MAX; |
320 | 667 | } else { |
321 | 667 | opt->dict_size = 2 | (props[0] & 1U); |
322 | 667 | opt->dict_size <<= props[0] / 2U + 11; |
323 | 667 | } |
324 | | |
325 | 668 | opt->preset_dict = NULL; |
326 | 668 | opt->preset_dict_size = 0; |
327 | | |
328 | 668 | *options = opt; |
329 | | |
330 | 668 | return LZMA_OK; |
331 | 668 | } |