Home | History | Annotate | Download | only in C
      1 /* Lzma2Dec.c -- LZMA2 Decoder
      2 2015-11-09 : 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 
     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 
     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 
     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 
     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 
    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 ", (unsigned)p->decoder.dicPos));
    107       PRF(printf(" %2X", (unsigned)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(" %8u", (unsigned)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(" %8u", (unsigned)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       unsigned 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 
    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 
    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 
    183     if (p->state == LZMA2_STATE_ERROR)
    184       return SZ_ERROR_DATA;
    185 
    186     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
    187     {
    188       *status = LZMA_STATUS_NOT_FINISHED;
    189       return SZ_OK;
    190     }
    191 
    192     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
    193     {
    194       if (*srcLen == inSize)
    195       {
    196         *status = LZMA_STATUS_NEEDS_MORE_INPUT;
    197         return SZ_OK;
    198       }
    199       (*srcLen)++;
    200       p->state = Lzma2Dec_UpdateState(p, *src++);
    201 
    202       if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
    203       {
    204         p->state = LZMA2_STATE_ERROR;
    205         return SZ_ERROR_DATA;
    206       }
    207       continue;
    208     }
    209 
    210     {
    211       SizeT destSizeCur = dicLimit - dicPos;
    212       SizeT srcSizeCur = inSize - *srcLen;
    213       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
    214 
    215       if (p->unpackSize <= destSizeCur)
    216       {
    217         destSizeCur = (SizeT)p->unpackSize;
    218         curFinishMode = LZMA_FINISH_END;
    219       }
    220 
    221       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
    222       {
    223         if (*srcLen == inSize)
    224         {
    225           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
    226           return SZ_OK;
    227         }
    228 
    229         if (p->state == LZMA2_STATE_DATA)
    230         {
    231           Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
    232           if (initDic)
    233             p->needInitProp = p->needInitState = True;
    234           else if (p->needInitDic)
    235           {
    236             p->state = LZMA2_STATE_ERROR;
    237             return SZ_ERROR_DATA;
    238           }
    239           p->needInitDic = False;
    240           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
    241         }
    242 
    243         if (srcSizeCur > destSizeCur)
    244           srcSizeCur = destSizeCur;
    245 
    246         if (srcSizeCur == 0)
    247         {
    248           p->state = LZMA2_STATE_ERROR;
    249           return SZ_ERROR_DATA;
    250         }
    251 
    252         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
    253 
    254         src += srcSizeCur;
    255         *srcLen += srcSizeCur;
    256         p->unpackSize -= (UInt32)srcSizeCur;
    257         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
    258       }
    259       else
    260       {
    261         SizeT outSizeProcessed;
    262         SRes res;
    263 
    264         if (p->state == LZMA2_STATE_DATA)
    265         {
    266           unsigned mode = LZMA2_GET_LZMA_MODE(p);
    267           Bool initDic = (mode == 3);
    268           Bool initState = (mode != 0);
    269           if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
    270           {
    271             p->state = LZMA2_STATE_ERROR;
    272             return SZ_ERROR_DATA;
    273           }
    274 
    275           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
    276           p->needInitDic = False;
    277           p->needInitState = False;
    278           p->state = LZMA2_STATE_DATA_CONT;
    279         }
    280 
    281         if (srcSizeCur > p->packSize)
    282           srcSizeCur = (SizeT)p->packSize;
    283 
    284         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
    285 
    286         src += srcSizeCur;
    287         *srcLen += srcSizeCur;
    288         p->packSize -= (UInt32)srcSizeCur;
    289 
    290         outSizeProcessed = p->decoder.dicPos - dicPos;
    291         p->unpackSize -= (UInt32)outSizeProcessed;
    292 
    293         RINOK(res);
    294         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
    295           return res;
    296 
    297         if (srcSizeCur == 0 && outSizeProcessed == 0)
    298         {
    299           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
    300               || p->unpackSize != 0
    301               || p->packSize != 0)
    302           {
    303             p->state = LZMA2_STATE_ERROR;
    304             return SZ_ERROR_DATA;
    305           }
    306           p->state = LZMA2_STATE_CONTROL;
    307         }
    308 
    309         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
    310           *status = LZMA_STATUS_NOT_FINISHED;
    311       }
    312     }
    313   }
    314 
    315   *status = LZMA_STATUS_FINISHED_WITH_MARK;
    316   return SZ_OK;
    317 }
    318 
    319 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
    320 {
    321   SizeT outSize = *destLen, inSize = *srcLen;
    322   *srcLen = *destLen = 0;
    323   for (;;)
    324   {
    325     SizeT srcSizeCur = inSize, outSizeCur, dicPos;
    326     ELzmaFinishMode curFinishMode;
    327     SRes res;
    328     if (p->decoder.dicPos == p->decoder.dicBufSize)
    329       p->decoder.dicPos = 0;
    330     dicPos = p->decoder.dicPos;
    331     if (outSize > p->decoder.dicBufSize - dicPos)
    332     {
    333       outSizeCur = p->decoder.dicBufSize;
    334       curFinishMode = LZMA_FINISH_ANY;
    335     }
    336     else
    337     {
    338       outSizeCur = dicPos + outSize;
    339       curFinishMode = finishMode;
    340     }
    341 
    342     res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
    343     src += srcSizeCur;
    344     inSize -= srcSizeCur;
    345     *srcLen += srcSizeCur;
    346     outSizeCur = p->decoder.dicPos - dicPos;
    347     memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
    348     dest += outSizeCur;
    349     outSize -= outSizeCur;
    350     *destLen += outSizeCur;
    351     if (res != 0)
    352       return res;
    353     if (outSizeCur == 0 || outSize == 0)
    354       return SZ_OK;
    355   }
    356 }
    357 
    358 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    359     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
    360 {
    361   CLzma2Dec p;
    362   SRes res;
    363   SizeT outSize = *destLen, inSize = *srcLen;
    364   *destLen = *srcLen = 0;
    365   *status = LZMA_STATUS_NOT_SPECIFIED;
    366   Lzma2Dec_Construct(&p);
    367   RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
    368   p.decoder.dic = dest;
    369   p.decoder.dicBufSize = outSize;
    370   Lzma2Dec_Init(&p);
    371   *srcLen = inSize;
    372   res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
    373   *destLen = p.decoder.dicPos;
    374   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
    375     res = SZ_ERROR_INPUT_EOF;
    376   Lzma2Dec_FreeProbs(&p, alloc);
    377   return res;
    378 }
    379