• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Lzma2Dec.c -- LZMA2 Decoder
2 2019-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 /*
17 00000000  -  End of data
18 00000001 U U  -  Uncompressed, reset dic, need reset state and set new prop
19 00000010 U U  -  Uncompressed, no reset
20 100uuuuu U U P P  -  LZMA, no reset
21 101uuuuu U U P P  -  LZMA, reset state
22 110uuuuu U U P P S  -  LZMA, reset state + set new prop
23 111uuuuu 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 
43 typedef 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 
Lzma2Dec_GetOldProps(Byte prop,Byte * props)57 static 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 
Lzma2Dec_AllocateProbs(CLzma2Dec * p,Byte prop,ISzAllocPtr alloc)71 SRes 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 
Lzma2Dec_Allocate(CLzma2Dec * p,Byte prop,ISzAllocPtr alloc)78 SRes 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 
Lzma2Dec_Init(CLzma2Dec * p)85 void 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 
Lzma2Dec_UpdateState(CLzma2Dec * p,Byte b)96 static 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 
LzmaDec_UpdateWithUncompressed(CLzmaDec * p,const Byte * src,SizeT size)163 static 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 
172 void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
173 
174 
Lzma2Dec_DecodeToDic(CLzma2Dec * p,SizeT dicLimit,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)175 SRes 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 
Lzma2Dec_Parse(CLzma2Dec * p,SizeT outSize,const Byte * src,SizeT * srcLen,int checkFinishBlock)306 ELzma2ParseStatus 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 
Lzma2Dec_DecodeToBuf(CLzma2Dec * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)427 SRes 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 
Lzma2Decode(Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,Byte prop,ELzmaFinishMode finishMode,ELzmaStatus * status,ISzAllocPtr alloc)468 SRes 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 }
489