• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Lzma2Dec.c -- LZMA2 Decoder
2 2009-05-03 : Igor Pavlov : Public domain */
3 
4 /* #define SHOW_DEBUG_INFO */
5 
6 #ifdef SHOW_DEBUG_INFO
7 #include <stdio.h>
8 #endif
9 
10 #include <string.h>
11 
12 #include "Lzma2Dec.h"
13 
14 /*
15 00000000  -  EOS
16 00000001 U U  -  Uncompressed Reset Dic
17 00000010 U U  -  Uncompressed No Reset
18 100uuuuu U U P P  -  LZMA no reset
19 101uuuuu U U P P  -  LZMA reset state
20 110uuuuu U U P P S  -  LZMA reset state + new prop
21 111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
22 
23   u, U - Unpack Size
24   P - Pack Size
25   S - Props
26 */
27 
28 #define LZMA2_CONTROL_LZMA (1 << 7)
29 #define LZMA2_CONTROL_COPY_NO_RESET 2
30 #define LZMA2_CONTROL_COPY_RESET_DIC 1
31 #define LZMA2_CONTROL_EOF 0
32 
33 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
34 
35 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
36 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
37 
38 #define LZMA2_LCLP_MAX 4
39 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
40 
41 #ifdef SHOW_DEBUG_INFO
42 #define PRF(x) x
43 #else
44 #define PRF(x)
45 #endif
46 
47 typedef enum
48 {
49   LZMA2_STATE_CONTROL,
50   LZMA2_STATE_UNPACK0,
51   LZMA2_STATE_UNPACK1,
52   LZMA2_STATE_PACK0,
53   LZMA2_STATE_PACK1,
54   LZMA2_STATE_PROP,
55   LZMA2_STATE_DATA,
56   LZMA2_STATE_DATA_CONT,
57   LZMA2_STATE_FINISHED,
58   LZMA2_STATE_ERROR
59 } ELzma2State;
60 
Lzma2Dec_GetOldProps(Byte prop,Byte * props)61 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
62 {
63   UInt32 dicSize;
64   if (prop > 40)
65     return SZ_ERROR_UNSUPPORTED;
66   dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
67   props[0] = (Byte)LZMA2_LCLP_MAX;
68   props[1] = (Byte)(dicSize);
69   props[2] = (Byte)(dicSize >> 8);
70   props[3] = (Byte)(dicSize >> 16);
71   props[4] = (Byte)(dicSize >> 24);
72   return SZ_OK;
73 }
74 
Lzma2Dec_AllocateProbs(CLzma2Dec * p,Byte prop,ISzAlloc * alloc)75 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
76 {
77   Byte props[LZMA_PROPS_SIZE];
78   RINOK(Lzma2Dec_GetOldProps(prop, props));
79   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
80 }
81 
Lzma2Dec_Allocate(CLzma2Dec * p,Byte prop,ISzAlloc * alloc)82 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
83 {
84   Byte props[LZMA_PROPS_SIZE];
85   RINOK(Lzma2Dec_GetOldProps(prop, props));
86   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
87 }
88 
Lzma2Dec_Init(CLzma2Dec * p)89 void Lzma2Dec_Init(CLzma2Dec *p)
90 {
91   p->state = LZMA2_STATE_CONTROL;
92   p->needInitDic = True;
93   p->needInitState = True;
94   p->needInitProp = True;
95   LzmaDec_Init(&p->decoder);
96 }
97 
Lzma2Dec_UpdateState(CLzma2Dec * p,Byte b)98 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
99 {
100   switch(p->state)
101   {
102     case LZMA2_STATE_CONTROL:
103       p->control = b;
104       PRF(printf("\n %4X ", p->decoder.dicPos));
105       PRF(printf(" %2X", b));
106       if (p->control == 0)
107         return LZMA2_STATE_FINISHED;
108       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109       {
110         if ((p->control & 0x7F) > 2)
111           return LZMA2_STATE_ERROR;
112         p->unpackSize = 0;
113       }
114       else
115         p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
116       return LZMA2_STATE_UNPACK0;
117 
118     case LZMA2_STATE_UNPACK0:
119       p->unpackSize |= (UInt32)b << 8;
120       return LZMA2_STATE_UNPACK1;
121 
122     case LZMA2_STATE_UNPACK1:
123       p->unpackSize |= (UInt32)b;
124       p->unpackSize++;
125       PRF(printf(" %8d", p->unpackSize));
126       return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
127 
128     case LZMA2_STATE_PACK0:
129       p->packSize = (UInt32)b << 8;
130       return LZMA2_STATE_PACK1;
131 
132     case LZMA2_STATE_PACK1:
133       p->packSize |= (UInt32)b;
134       p->packSize++;
135       PRF(printf(" %8d", p->packSize));
136       return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
137         (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
138 
139     case LZMA2_STATE_PROP:
140     {
141       int lc, lp;
142       if (b >= (9 * 5 * 5))
143         return LZMA2_STATE_ERROR;
144       lc = b % 9;
145       b /= 9;
146       p->decoder.prop.pb = b / 5;
147       lp = b % 5;
148       if (lc + lp > LZMA2_LCLP_MAX)
149         return LZMA2_STATE_ERROR;
150       p->decoder.prop.lc = lc;
151       p->decoder.prop.lp = lp;
152       p->needInitProp = False;
153       return LZMA2_STATE_DATA;
154     }
155   }
156   return LZMA2_STATE_ERROR;
157 }
158 
LzmaDec_UpdateWithUncompressed(CLzmaDec * p,const Byte * src,SizeT size)159 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
160 {
161   memcpy(p->dic + p->dicPos, src, size);
162   p->dicPos += size;
163   if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
164     p->checkDicSize = p->prop.dicSize;
165   p->processedPos += (UInt32)size;
166 }
167 
168 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
169 
Lzma2Dec_DecodeToDic(CLzma2Dec * p,SizeT dicLimit,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)170 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
171     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
172 {
173   SizeT inSize = *srcLen;
174   *srcLen = 0;
175   *status = LZMA_STATUS_NOT_SPECIFIED;
176 
177   while (p->state != LZMA2_STATE_FINISHED)
178   {
179     SizeT dicPos = p->decoder.dicPos;
180     if (p->state == LZMA2_STATE_ERROR)
181       return SZ_ERROR_DATA;
182     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
183     {
184       *status = LZMA_STATUS_NOT_FINISHED;
185       return SZ_OK;
186     }
187     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
188     {
189       if (*srcLen == inSize)
190       {
191         *status = LZMA_STATUS_NEEDS_MORE_INPUT;
192         return SZ_OK;
193       }
194       (*srcLen)++;
195       p->state = Lzma2Dec_UpdateState(p, *src++);
196       continue;
197     }
198     {
199       SizeT destSizeCur = dicLimit - dicPos;
200       SizeT srcSizeCur = inSize - *srcLen;
201       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
202 
203       if (p->unpackSize <= destSizeCur)
204       {
205         destSizeCur = (SizeT)p->unpackSize;
206         curFinishMode = LZMA_FINISH_END;
207       }
208 
209       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
210       {
211         if (*srcLen == inSize)
212         {
213           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
214           return SZ_OK;
215         }
216 
217         if (p->state == LZMA2_STATE_DATA)
218         {
219           Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
220           if (initDic)
221             p->needInitProp = p->needInitState = True;
222           else if (p->needInitDic)
223             return SZ_ERROR_DATA;
224           p->needInitDic = False;
225           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
226         }
227 
228         if (srcSizeCur > destSizeCur)
229           srcSizeCur = destSizeCur;
230 
231         if (srcSizeCur == 0)
232           return SZ_ERROR_DATA;
233 
234         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
235 
236         src += srcSizeCur;
237         *srcLen += srcSizeCur;
238         p->unpackSize -= (UInt32)srcSizeCur;
239         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
240       }
241       else
242       {
243         SizeT outSizeProcessed;
244         SRes res;
245 
246         if (p->state == LZMA2_STATE_DATA)
247         {
248           int mode = LZMA2_GET_LZMA_MODE(p);
249           Bool initDic = (mode == 3);
250           Bool initState = (mode > 0);
251           if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
252             return SZ_ERROR_DATA;
253 
254           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
255           p->needInitDic = False;
256           p->needInitState = False;
257           p->state = LZMA2_STATE_DATA_CONT;
258         }
259         if (srcSizeCur > p->packSize)
260           srcSizeCur = (SizeT)p->packSize;
261 
262         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
263 
264         src += srcSizeCur;
265         *srcLen += srcSizeCur;
266         p->packSize -= (UInt32)srcSizeCur;
267 
268         outSizeProcessed = p->decoder.dicPos - dicPos;
269         p->unpackSize -= (UInt32)outSizeProcessed;
270 
271         RINOK(res);
272         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
273           return res;
274 
275         if (srcSizeCur == 0 && outSizeProcessed == 0)
276         {
277           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
278               p->unpackSize != 0 || p->packSize != 0)
279             return SZ_ERROR_DATA;
280           p->state = LZMA2_STATE_CONTROL;
281         }
282         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
283           *status = LZMA_STATUS_NOT_FINISHED;
284       }
285     }
286   }
287   *status = LZMA_STATUS_FINISHED_WITH_MARK;
288   return SZ_OK;
289 }
290 
Lzma2Dec_DecodeToBuf(CLzma2Dec * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)291 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
292 {
293   SizeT outSize = *destLen, inSize = *srcLen;
294   *srcLen = *destLen = 0;
295   for (;;)
296   {
297     SizeT srcSizeCur = inSize, outSizeCur, dicPos;
298     ELzmaFinishMode curFinishMode;
299     SRes res;
300     if (p->decoder.dicPos == p->decoder.dicBufSize)
301       p->decoder.dicPos = 0;
302     dicPos = p->decoder.dicPos;
303     if (outSize > p->decoder.dicBufSize - dicPos)
304     {
305       outSizeCur = p->decoder.dicBufSize;
306       curFinishMode = LZMA_FINISH_ANY;
307     }
308     else
309     {
310       outSizeCur = dicPos + outSize;
311       curFinishMode = finishMode;
312     }
313 
314     res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
315     src += srcSizeCur;
316     inSize -= srcSizeCur;
317     *srcLen += srcSizeCur;
318     outSizeCur = p->decoder.dicPos - dicPos;
319     memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
320     dest += outSizeCur;
321     outSize -= outSizeCur;
322     *destLen += outSizeCur;
323     if (res != 0)
324       return res;
325     if (outSizeCur == 0 || outSize == 0)
326       return SZ_OK;
327   }
328 }
329 
Lzma2Decode(Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,Byte prop,ELzmaFinishMode finishMode,ELzmaStatus * status,ISzAlloc * alloc)330 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
331     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
332 {
333   CLzma2Dec decoder;
334   SRes res;
335   SizeT outSize = *destLen, inSize = *srcLen;
336   Byte props[LZMA_PROPS_SIZE];
337 
338   Lzma2Dec_Construct(&decoder);
339 
340   *destLen = *srcLen = 0;
341   *status = LZMA_STATUS_NOT_SPECIFIED;
342   decoder.decoder.dic = dest;
343   decoder.decoder.dicBufSize = outSize;
344 
345   RINOK(Lzma2Dec_GetOldProps(prop, props));
346   RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
347 
348   *srcLen = inSize;
349   res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
350   *destLen = decoder.decoder.dicPos;
351   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
352     res = SZ_ERROR_INPUT_EOF;
353 
354   LzmaDec_FreeProbs(&decoder.decoder, alloc);
355   return res;
356 }
357