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