xref: /aosp_15_r20/external/lzma/C/Lzma2Dec.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 /* Lzma2Dec.c -- LZMA2 Decoder
2 2024-03-01 : 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 
96 // ELzma2State
Lzma2Dec_UpdateState(CLzma2Dec * p,Byte b)97 static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
98 {
99   switch (p->state)
100   {
101     case LZMA2_STATE_CONTROL:
102       p->isExtraMode = False;
103       p->control = b;
104       PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
105       PRF(printf(" %02X", (unsigned)b));
106       if (b == 0)
107         return LZMA2_STATE_FINISHED;
108       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109       {
110         if (b == LZMA2_CONTROL_COPY_RESET_DIC)
111           p->needInitLevel = 0xC0;
112         else if (b > 2 || p->needInitLevel == 0xE0)
113           return LZMA2_STATE_ERROR;
114       }
115       else
116       {
117         if (b < p->needInitLevel)
118           return LZMA2_STATE_ERROR;
119         p->needInitLevel = 0;
120         p->unpackSize = (UInt32)(b & 0x1F) << 16;
121       }
122       return LZMA2_STATE_UNPACK0;
123 
124     case LZMA2_STATE_UNPACK0:
125       p->unpackSize |= (UInt32)b << 8;
126       return LZMA2_STATE_UNPACK1;
127 
128     case LZMA2_STATE_UNPACK1:
129       p->unpackSize |= (UInt32)b;
130       p->unpackSize++;
131       PRF(printf(" %7u", (unsigned)p->unpackSize));
132       return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
133 
134     case LZMA2_STATE_PACK0:
135       p->packSize = (UInt32)b << 8;
136       return LZMA2_STATE_PACK1;
137 
138     case LZMA2_STATE_PACK1:
139       p->packSize |= (UInt32)b;
140       p->packSize++;
141       // if (p->packSize < 5) return LZMA2_STATE_ERROR;
142       PRF(printf(" %5u", (unsigned)p->packSize));
143       return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
144 
145     case LZMA2_STATE_PROP:
146     {
147       unsigned lc, lp;
148       if (b >= (9 * 5 * 5))
149         return LZMA2_STATE_ERROR;
150       lc = b % 9;
151       b /= 9;
152       p->decoder.prop.pb = (Byte)(b / 5);
153       lp = b % 5;
154       if (lc + lp > LZMA2_LCLP_MAX)
155         return LZMA2_STATE_ERROR;
156       p->decoder.prop.lc = (Byte)lc;
157       p->decoder.prop.lp = (Byte)lp;
158       return LZMA2_STATE_DATA;
159     }
160 
161     default:
162       return LZMA2_STATE_ERROR;
163   }
164 }
165 
LzmaDec_UpdateWithUncompressed(CLzmaDec * p,const Byte * src,SizeT size)166 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
167 {
168   memcpy(p->dic + p->dicPos, src, size);
169   p->dicPos += size;
170   if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
171     p->checkDicSize = p->prop.dicSize;
172   p->processedPos += (UInt32)size;
173 }
174 
175 void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
176 
177 
Lzma2Dec_DecodeToDic(CLzma2Dec * p,SizeT dicLimit,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)178 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
179     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
180 {
181   SizeT inSize = *srcLen;
182   *srcLen = 0;
183   *status = LZMA_STATUS_NOT_SPECIFIED;
184 
185   while (p->state != LZMA2_STATE_ERROR)
186   {
187     SizeT dicPos;
188 
189     if (p->state == LZMA2_STATE_FINISHED)
190     {
191       *status = LZMA_STATUS_FINISHED_WITH_MARK;
192       return SZ_OK;
193     }
194 
195     dicPos = p->decoder.dicPos;
196 
197     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
198     {
199       *status = LZMA_STATUS_NOT_FINISHED;
200       return SZ_OK;
201     }
202 
203     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
204     {
205       if (*srcLen == inSize)
206       {
207         *status = LZMA_STATUS_NEEDS_MORE_INPUT;
208         return SZ_OK;
209       }
210       (*srcLen)++;
211       p->state = Lzma2Dec_UpdateState(p, *src++);
212       if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
213         break;
214       continue;
215     }
216 
217     {
218       SizeT inCur = inSize - *srcLen;
219       SizeT outCur = dicLimit - dicPos;
220       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
221 
222       if (outCur >= p->unpackSize)
223       {
224         outCur = (SizeT)p->unpackSize;
225         curFinishMode = LZMA_FINISH_END;
226       }
227 
228       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
229       {
230         if (inCur == 0)
231         {
232           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
233           return SZ_OK;
234         }
235 
236         if (p->state == LZMA2_STATE_DATA)
237         {
238           BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
239           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
240         }
241 
242         if (inCur > outCur)
243           inCur = outCur;
244         if (inCur == 0)
245           break;
246 
247         LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
248 
249         src += inCur;
250         *srcLen += inCur;
251         p->unpackSize -= (UInt32)inCur;
252         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
253       }
254       else
255       {
256         SRes res;
257 
258         if (p->state == LZMA2_STATE_DATA)
259         {
260           BoolInt initDic = (p->control >= 0xE0);
261           BoolInt initState = (p->control >= 0xA0);
262           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
263           p->state = LZMA2_STATE_DATA_CONT;
264         }
265 
266         if (inCur > p->packSize)
267           inCur = (SizeT)p->packSize;
268 
269         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
270 
271         src += inCur;
272         *srcLen += inCur;
273         p->packSize -= (UInt32)inCur;
274         outCur = p->decoder.dicPos - dicPos;
275         p->unpackSize -= (UInt32)outCur;
276 
277         if (res != 0)
278           break;
279 
280         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
281         {
282           if (p->packSize == 0)
283             break;
284           return SZ_OK;
285         }
286 
287         if (inCur == 0 && outCur == 0)
288         {
289           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
290               || p->unpackSize != 0
291               || p->packSize != 0)
292             break;
293           p->state = LZMA2_STATE_CONTROL;
294         }
295 
296         *status = LZMA_STATUS_NOT_SPECIFIED;
297       }
298     }
299   }
300 
301   *status = LZMA_STATUS_NOT_SPECIFIED;
302   p->state = LZMA2_STATE_ERROR;
303   return SZ_ERROR_DATA;
304 }
305 
306 
307 
308 
Lzma2Dec_Parse(CLzma2Dec * p,SizeT outSize,const Byte * src,SizeT * srcLen,int checkFinishBlock)309 ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
310     SizeT outSize,
311     const Byte *src, SizeT *srcLen,
312     int checkFinishBlock)
313 {
314   SizeT inSize = *srcLen;
315   *srcLen = 0;
316 
317   while (p->state != LZMA2_STATE_ERROR)
318   {
319     if (p->state == LZMA2_STATE_FINISHED)
320       return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
321 
322     if (outSize == 0 && !checkFinishBlock)
323       return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
324 
325     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
326     {
327       if (*srcLen == inSize)
328         return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
329       (*srcLen)++;
330 
331       p->state = Lzma2Dec_UpdateState(p, *src++);
332 
333       if (p->state == LZMA2_STATE_UNPACK0)
334       {
335         // if (p->decoder.dicPos != 0)
336         if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
337           return LZMA2_PARSE_STATUS_NEW_BLOCK;
338         // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
339       }
340 
341       // The following code can be commented.
342       // It's not big problem, if we read additional input bytes.
343       // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
344 
345       if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
346       {
347         // checkFinishBlock is true. So we expect that block must be finished,
348         // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
349         // break;
350         return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
351       }
352 
353       if (p->state == LZMA2_STATE_DATA)
354         return LZMA2_PARSE_STATUS_NEW_CHUNK;
355 
356       continue;
357     }
358 
359     if (outSize == 0)
360       return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
361 
362     {
363       SizeT inCur = inSize - *srcLen;
364 
365       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
366       {
367         if (inCur == 0)
368           return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
369         if (inCur > p->unpackSize)
370           inCur = p->unpackSize;
371         if (inCur > outSize)
372           inCur = outSize;
373         p->decoder.dicPos += inCur;
374         src += inCur;
375         *srcLen += inCur;
376         outSize -= inCur;
377         p->unpackSize -= (UInt32)inCur;
378         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
379       }
380       else
381       {
382         p->isExtraMode = True;
383 
384         if (inCur == 0)
385         {
386           if (p->packSize != 0)
387             return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
388         }
389         else if (p->state == LZMA2_STATE_DATA)
390         {
391           p->state = LZMA2_STATE_DATA_CONT;
392           if (*src != 0)
393           {
394             // first byte of lzma chunk must be Zero
395             *srcLen += 1;
396             p->packSize--;
397             break;
398           }
399         }
400 
401         if (inCur > p->packSize)
402           inCur = (SizeT)p->packSize;
403 
404         src += inCur;
405         *srcLen += inCur;
406         p->packSize -= (UInt32)inCur;
407 
408         if (p->packSize == 0)
409         {
410           SizeT rem = outSize;
411           if (rem > p->unpackSize)
412             rem = p->unpackSize;
413           p->decoder.dicPos += rem;
414           p->unpackSize -= (UInt32)rem;
415           outSize -= rem;
416           if (p->unpackSize == 0)
417             p->state = LZMA2_STATE_CONTROL;
418         }
419       }
420     }
421   }
422 
423   p->state = LZMA2_STATE_ERROR;
424   return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
425 }
426 
427 
428 
429 
Lzma2Dec_DecodeToBuf(CLzma2Dec * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)430 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
431 {
432   SizeT outSize = *destLen, inSize = *srcLen;
433   *srcLen = *destLen = 0;
434 
435   for (;;)
436   {
437     SizeT inCur = inSize, outCur, dicPos;
438     ELzmaFinishMode curFinishMode;
439     SRes res;
440 
441     if (p->decoder.dicPos == p->decoder.dicBufSize)
442       p->decoder.dicPos = 0;
443     dicPos = p->decoder.dicPos;
444     curFinishMode = LZMA_FINISH_ANY;
445     outCur = p->decoder.dicBufSize - dicPos;
446 
447     if (outCur >= outSize)
448     {
449       outCur = outSize;
450       curFinishMode = finishMode;
451     }
452 
453     res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
454 
455     src += inCur;
456     inSize -= inCur;
457     *srcLen += inCur;
458     outCur = p->decoder.dicPos - dicPos;
459     memcpy(dest, p->decoder.dic + dicPos, outCur);
460     dest += outCur;
461     outSize -= outCur;
462     *destLen += outCur;
463     if (res != 0)
464       return res;
465     if (outCur == 0 || outSize == 0)
466       return SZ_OK;
467   }
468 }
469 
470 
Lzma2Decode(Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,Byte prop,ELzmaFinishMode finishMode,ELzmaStatus * status,ISzAllocPtr alloc)471 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
472     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
473 {
474   CLzma2Dec p;
475   SRes res;
476   SizeT outSize = *destLen, inSize = *srcLen;
477   *destLen = *srcLen = 0;
478   *status = LZMA_STATUS_NOT_SPECIFIED;
479   Lzma2Dec_CONSTRUCT(&p)
480   RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
481   p.decoder.dic = dest;
482   p.decoder.dicBufSize = outSize;
483   Lzma2Dec_Init(&p);
484   *srcLen = inSize;
485   res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
486   *destLen = p.decoder.dicPos;
487   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
488     res = SZ_ERROR_INPUT_EOF;
489   Lzma2Dec_FreeProbs(&p, alloc);
490   return res;
491 }
492 
493 #undef PRF
494