src/third-party/lzma/Lzma2Dec.c (view raw)
1/* Lzma2Dec.c -- LZMA2 Decoder
22019-02-02 : Igor Pavlov : Public domain */
3
4/* #define SHOW_DEBUG_INFO */
5
6#include "Precomp.h"
7
8#ifdef SHOW_DEBUG_INFO
9#include <stdio.h>
10#endif
11
12#include <string.h>
13
14#include "Lzma2Dec.h"
15
16/*
1700000000 - End of data
1800000001 U U - Uncompressed, reset dic, need reset state and set new prop
1900000010 U U - Uncompressed, no reset
20100uuuuu U U P P - LZMA, no reset
21101uuuuu U U P P - LZMA, reset state
22110uuuuu U U P P S - LZMA, reset state + set new prop
23111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
24
25 u, U - Unpack Size
26 P - Pack Size
27 S - Props
28*/
29
30#define LZMA2_CONTROL_COPY_RESET_DIC 1
31
32#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
33
34#define LZMA2_LCLP_MAX 4
35#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
36
37#ifdef SHOW_DEBUG_INFO
38#define PRF(x) x
39#else
40#define PRF(x)
41#endif
42
43typedef enum
44{
45 LZMA2_STATE_CONTROL,
46 LZMA2_STATE_UNPACK0,
47 LZMA2_STATE_UNPACK1,
48 LZMA2_STATE_PACK0,
49 LZMA2_STATE_PACK1,
50 LZMA2_STATE_PROP,
51 LZMA2_STATE_DATA,
52 LZMA2_STATE_DATA_CONT,
53 LZMA2_STATE_FINISHED,
54 LZMA2_STATE_ERROR
55} ELzma2State;
56
57static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
58{
59 UInt32 dicSize;
60 if (prop > 40)
61 return SZ_ERROR_UNSUPPORTED;
62 dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
63 props[0] = (Byte)LZMA2_LCLP_MAX;
64 props[1] = (Byte)(dicSize);
65 props[2] = (Byte)(dicSize >> 8);
66 props[3] = (Byte)(dicSize >> 16);
67 props[4] = (Byte)(dicSize >> 24);
68 return SZ_OK;
69}
70
71SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
72{
73 Byte props[LZMA_PROPS_SIZE];
74 RINOK(Lzma2Dec_GetOldProps(prop, props));
75 return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
76}
77
78SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
79{
80 Byte props[LZMA_PROPS_SIZE];
81 RINOK(Lzma2Dec_GetOldProps(prop, props));
82 return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
83}
84
85void Lzma2Dec_Init(CLzma2Dec *p)
86{
87 p->state = LZMA2_STATE_CONTROL;
88 p->needInitLevel = 0xE0;
89 p->isExtraMode = False;
90 p->unpackSize = 0;
91
92 // p->decoder.dicPos = 0; // we can use it instead of full init
93 LzmaDec_Init(&p->decoder);
94}
95
96static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
97{
98 switch (p->state)
99 {
100 case LZMA2_STATE_CONTROL:
101 p->isExtraMode = False;
102 p->control = b;
103 PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
104 PRF(printf(" %02X", (unsigned)b));
105 if (b == 0)
106 return LZMA2_STATE_FINISHED;
107 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
108 {
109 if (b == LZMA2_CONTROL_COPY_RESET_DIC)
110 p->needInitLevel = 0xC0;
111 else if (b > 2 || p->needInitLevel == 0xE0)
112 return LZMA2_STATE_ERROR;
113 }
114 else
115 {
116 if (b < p->needInitLevel)
117 return LZMA2_STATE_ERROR;
118 p->needInitLevel = 0;
119 p->unpackSize = (UInt32)(b & 0x1F) << 16;
120 }
121 return LZMA2_STATE_UNPACK0;
122
123 case LZMA2_STATE_UNPACK0:
124 p->unpackSize |= (UInt32)b << 8;
125 return LZMA2_STATE_UNPACK1;
126
127 case LZMA2_STATE_UNPACK1:
128 p->unpackSize |= (UInt32)b;
129 p->unpackSize++;
130 PRF(printf(" %7u", (unsigned)p->unpackSize));
131 return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
132
133 case LZMA2_STATE_PACK0:
134 p->packSize = (UInt32)b << 8;
135 return LZMA2_STATE_PACK1;
136
137 case LZMA2_STATE_PACK1:
138 p->packSize |= (UInt32)b;
139 p->packSize++;
140 // if (p->packSize < 5) return LZMA2_STATE_ERROR;
141 PRF(printf(" %5u", (unsigned)p->packSize));
142 return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
143
144 case LZMA2_STATE_PROP:
145 {
146 unsigned lc, lp;
147 if (b >= (9 * 5 * 5))
148 return LZMA2_STATE_ERROR;
149 lc = b % 9;
150 b /= 9;
151 p->decoder.prop.pb = (Byte)(b / 5);
152 lp = b % 5;
153 if (lc + lp > LZMA2_LCLP_MAX)
154 return LZMA2_STATE_ERROR;
155 p->decoder.prop.lc = (Byte)lc;
156 p->decoder.prop.lp = (Byte)lp;
157 return LZMA2_STATE_DATA;
158 }
159 }
160 return LZMA2_STATE_ERROR;
161}
162
163static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
164{
165 memcpy(p->dic + p->dicPos, src, size);
166 p->dicPos += size;
167 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
168 p->checkDicSize = p->prop.dicSize;
169 p->processedPos += (UInt32)size;
170}
171
172void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
173
174
175SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
176 const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
177{
178 SizeT inSize = *srcLen;
179 *srcLen = 0;
180 *status = LZMA_STATUS_NOT_SPECIFIED;
181
182 while (p->state != LZMA2_STATE_ERROR)
183 {
184 SizeT dicPos;
185
186 if (p->state == LZMA2_STATE_FINISHED)
187 {
188 *status = LZMA_STATUS_FINISHED_WITH_MARK;
189 return SZ_OK;
190 }
191
192 dicPos = p->decoder.dicPos;
193
194 if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
195 {
196 *status = LZMA_STATUS_NOT_FINISHED;
197 return SZ_OK;
198 }
199
200 if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
201 {
202 if (*srcLen == inSize)
203 {
204 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
205 return SZ_OK;
206 }
207 (*srcLen)++;
208 p->state = Lzma2Dec_UpdateState(p, *src++);
209 if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
210 break;
211 continue;
212 }
213
214 {
215 SizeT inCur = inSize - *srcLen;
216 SizeT outCur = dicLimit - dicPos;
217 ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
218
219 if (outCur >= p->unpackSize)
220 {
221 outCur = (SizeT)p->unpackSize;
222 curFinishMode = LZMA_FINISH_END;
223 }
224
225 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
226 {
227 if (inCur == 0)
228 {
229 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
230 return SZ_OK;
231 }
232
233 if (p->state == LZMA2_STATE_DATA)
234 {
235 BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
236 LzmaDec_InitDicAndState(&p->decoder, initDic, False);
237 }
238
239 if (inCur > outCur)
240 inCur = outCur;
241 if (inCur == 0)
242 break;
243
244 LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
245
246 src += inCur;
247 *srcLen += inCur;
248 p->unpackSize -= (UInt32)inCur;
249 p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
250 }
251 else
252 {
253 SRes res;
254
255 if (p->state == LZMA2_STATE_DATA)
256 {
257 BoolInt initDic = (p->control >= 0xE0);
258 BoolInt initState = (p->control >= 0xA0);
259 LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
260 p->state = LZMA2_STATE_DATA_CONT;
261 }
262
263 if (inCur > p->packSize)
264 inCur = (SizeT)p->packSize;
265
266 res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
267
268 src += inCur;
269 *srcLen += inCur;
270 p->packSize -= (UInt32)inCur;
271 outCur = p->decoder.dicPos - dicPos;
272 p->unpackSize -= (UInt32)outCur;
273
274 if (res != 0)
275 break;
276
277 if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
278 {
279 if (p->packSize == 0)
280 break;
281 return SZ_OK;
282 }
283
284 if (inCur == 0 && outCur == 0)
285 {
286 if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
287 || p->unpackSize != 0
288 || p->packSize != 0)
289 break;
290 p->state = LZMA2_STATE_CONTROL;
291 }
292
293 *status = LZMA_STATUS_NOT_SPECIFIED;
294 }
295 }
296 }
297
298 *status = LZMA_STATUS_NOT_SPECIFIED;
299 p->state = LZMA2_STATE_ERROR;
300 return SZ_ERROR_DATA;
301}
302
303
304
305
306ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
307 SizeT outSize,
308 const Byte *src, SizeT *srcLen,
309 int checkFinishBlock)
310{
311 SizeT inSize = *srcLen;
312 *srcLen = 0;
313
314 while (p->state != LZMA2_STATE_ERROR)
315 {
316 if (p->state == LZMA2_STATE_FINISHED)
317 return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
318
319 if (outSize == 0 && !checkFinishBlock)
320 return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
321
322 if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
323 {
324 if (*srcLen == inSize)
325 return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
326 (*srcLen)++;
327
328 p->state = Lzma2Dec_UpdateState(p, *src++);
329
330 if (p->state == LZMA2_STATE_UNPACK0)
331 {
332 // if (p->decoder.dicPos != 0)
333 if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
334 return LZMA2_PARSE_STATUS_NEW_BLOCK;
335 // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
336 }
337
338 // The following code can be commented.
339 // It's not big problem, if we read additional input bytes.
340 // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
341
342 if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
343 {
344 // checkFinishBlock is true. So we expect that block must be finished,
345 // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
346 // break;
347 return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
348 }
349
350 if (p->state == LZMA2_STATE_DATA)
351 return LZMA2_PARSE_STATUS_NEW_CHUNK;
352
353 continue;
354 }
355
356 if (outSize == 0)
357 return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
358
359 {
360 SizeT inCur = inSize - *srcLen;
361
362 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
363 {
364 if (inCur == 0)
365 return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
366 if (inCur > p->unpackSize)
367 inCur = p->unpackSize;
368 if (inCur > outSize)
369 inCur = outSize;
370 p->decoder.dicPos += inCur;
371 src += inCur;
372 *srcLen += inCur;
373 outSize -= inCur;
374 p->unpackSize -= (UInt32)inCur;
375 p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
376 }
377 else
378 {
379 p->isExtraMode = True;
380
381 if (inCur == 0)
382 {
383 if (p->packSize != 0)
384 return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
385 }
386 else if (p->state == LZMA2_STATE_DATA)
387 {
388 p->state = LZMA2_STATE_DATA_CONT;
389 if (*src != 0)
390 {
391 // first byte of lzma chunk must be Zero
392 *srcLen += 1;
393 p->packSize--;
394 break;
395 }
396 }
397
398 if (inCur > p->packSize)
399 inCur = (SizeT)p->packSize;
400
401 src += inCur;
402 *srcLen += inCur;
403 p->packSize -= (UInt32)inCur;
404
405 if (p->packSize == 0)
406 {
407 SizeT rem = outSize;
408 if (rem > p->unpackSize)
409 rem = p->unpackSize;
410 p->decoder.dicPos += rem;
411 p->unpackSize -= (UInt32)rem;
412 outSize -= rem;
413 if (p->unpackSize == 0)
414 p->state = LZMA2_STATE_CONTROL;
415 }
416 }
417 }
418 }
419
420 p->state = LZMA2_STATE_ERROR;
421 return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
422}
423
424
425
426
427SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
428{
429 SizeT outSize = *destLen, inSize = *srcLen;
430 *srcLen = *destLen = 0;
431
432 for (;;)
433 {
434 SizeT inCur = inSize, outCur, dicPos;
435 ELzmaFinishMode curFinishMode;
436 SRes res;
437
438 if (p->decoder.dicPos == p->decoder.dicBufSize)
439 p->decoder.dicPos = 0;
440 dicPos = p->decoder.dicPos;
441 curFinishMode = LZMA_FINISH_ANY;
442 outCur = p->decoder.dicBufSize - dicPos;
443
444 if (outCur >= outSize)
445 {
446 outCur = outSize;
447 curFinishMode = finishMode;
448 }
449
450 res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
451
452 src += inCur;
453 inSize -= inCur;
454 *srcLen += inCur;
455 outCur = p->decoder.dicPos - dicPos;
456 memcpy(dest, p->decoder.dic + dicPos, outCur);
457 dest += outCur;
458 outSize -= outCur;
459 *destLen += outCur;
460 if (res != 0)
461 return res;
462 if (outCur == 0 || outSize == 0)
463 return SZ_OK;
464 }
465}
466
467
468SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
469 Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
470{
471 CLzma2Dec p;
472 SRes res;
473 SizeT outSize = *destLen, inSize = *srcLen;
474 *destLen = *srcLen = 0;
475 *status = LZMA_STATUS_NOT_SPECIFIED;
476 Lzma2Dec_Construct(&p);
477 RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
478 p.decoder.dic = dest;
479 p.decoder.dicBufSize = outSize;
480 Lzma2Dec_Init(&p);
481 *srcLen = inSize;
482 res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
483 *destLen = p.decoder.dicPos;
484 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
485 res = SZ_ERROR_INPUT_EOF;
486 Lzma2Dec_FreeProbs(&p, alloc);
487 return res;
488}