Home | History | Annotate | Download | only in C
      1 /* XzDec.c -- Xz Decode
      2 2014-12-30 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 /* #define XZ_DUMP */
      7 
      8 #ifdef XZ_DUMP
      9 #include <stdio.h>
     10 #endif
     11 
     12 #include <stdlib.h>
     13 #include <string.h>
     14 
     15 #include "7zCrc.h"
     16 #include "Alloc.h"
     17 #include "Bra.h"
     18 #include "CpuArch.h"
     19 #include "Delta.h"
     20 #include "Lzma2Dec.h"
     21 
     22 #ifdef USE_SUBBLOCK
     23 #include "Bcj3Dec.c"
     24 #include "SbDec.c"
     25 #endif
     26 
     27 #include "Xz.h"
     28 
     29 #define XZ_CHECK_SIZE_MAX 64
     30 
     31 #define CODER_BUF_SIZE (1 << 17)
     32 
     33 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
     34 {
     35   int i, limit;
     36   *value = 0;
     37   limit = (maxSize > 9) ? 9 : (int)maxSize;
     38 
     39   for (i = 0; i < limit;)
     40   {
     41     Byte b = p[i];
     42     *value |= (UInt64)(b & 0x7F) << (7 * i++);
     43     if ((b & 0x80) == 0)
     44       return (b == 0 && i != 1) ? 0 : i;
     45   }
     46   return 0;
     47 }
     48 
     49 /* ---------- BraState ---------- */
     50 
     51 #define BRA_BUF_SIZE (1 << 14)
     52 
     53 typedef struct
     54 {
     55   size_t bufPos;
     56   size_t bufConv;
     57   size_t bufTotal;
     58 
     59   UInt32 methodId;
     60   int encodeMode;
     61   UInt32 delta;
     62   UInt32 ip;
     63   UInt32 x86State;
     64   Byte deltaState[DELTA_STATE_SIZE];
     65 
     66   Byte buf[BRA_BUF_SIZE];
     67 } CBraState;
     68 
     69 void BraState_Free(void *pp, ISzAlloc *alloc)
     70 {
     71   alloc->Free(alloc, pp);
     72 }
     73 
     74 SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
     75 {
     76   CBraState *p = ((CBraState *)pp);
     77   alloc = alloc;
     78   p->ip = 0;
     79   if (p->methodId == XZ_ID_Delta)
     80   {
     81     if (propSize != 1)
     82       return SZ_ERROR_UNSUPPORTED;
     83     p->delta = (unsigned)props[0] + 1;
     84   }
     85   else
     86   {
     87     if (propSize == 4)
     88     {
     89       UInt32 v = GetUi32(props);
     90       switch(p->methodId)
     91       {
     92         case XZ_ID_PPC:
     93         case XZ_ID_ARM:
     94         case XZ_ID_SPARC:
     95           if ((v & 3) != 0)
     96             return SZ_ERROR_UNSUPPORTED;
     97           break;
     98         case XZ_ID_ARMT:
     99           if ((v & 1) != 0)
    100             return SZ_ERROR_UNSUPPORTED;
    101           break;
    102         case XZ_ID_IA64:
    103           if ((v & 0xF) != 0)
    104             return SZ_ERROR_UNSUPPORTED;
    105           break;
    106       }
    107       p->ip = v;
    108     }
    109     else if (propSize != 0)
    110       return SZ_ERROR_UNSUPPORTED;
    111   }
    112   return SZ_OK;
    113 }
    114 
    115 void BraState_Init(void *pp)
    116 {
    117   CBraState *p = ((CBraState *)pp);
    118   p->bufPos = p->bufConv = p->bufTotal = 0;
    119   x86_Convert_Init(p->x86State);
    120   if (p->methodId == XZ_ID_Delta)
    121     Delta_Init(p->deltaState);
    122 }
    123 
    124 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
    125 
    126 static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    127     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    128 {
    129   CBraState *p = ((CBraState *)pp);
    130   SizeT destLenOrig = *destLen;
    131   SizeT srcLenOrig = *srcLen;
    132   *destLen = 0;
    133   *srcLen = 0;
    134   finishMode = finishMode;
    135   *wasFinished = 0;
    136   while (destLenOrig > 0)
    137   {
    138     if (p->bufPos != p->bufConv)
    139     {
    140       size_t curSize = p->bufConv - p->bufPos;
    141       if (curSize > destLenOrig)
    142         curSize = destLenOrig;
    143       memcpy(dest, p->buf + p->bufPos, curSize);
    144       p->bufPos += curSize;
    145       *destLen += curSize;
    146       dest += curSize;
    147       destLenOrig -= curSize;
    148       continue;
    149     }
    150     p->bufTotal -= p->bufPos;
    151     memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
    152     p->bufPos = 0;
    153     p->bufConv = 0;
    154     {
    155       size_t curSize = BRA_BUF_SIZE - p->bufTotal;
    156       if (curSize > srcLenOrig)
    157         curSize = srcLenOrig;
    158       memcpy(p->buf + p->bufTotal, src, curSize);
    159       *srcLen += curSize;
    160       src += curSize;
    161       srcLenOrig -= curSize;
    162       p->bufTotal += curSize;
    163     }
    164     if (p->bufTotal == 0)
    165       break;
    166     switch(p->methodId)
    167     {
    168       case XZ_ID_Delta:
    169         if (p->encodeMode)
    170           Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
    171         else
    172           Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
    173         p->bufConv = p->bufTotal;
    174         break;
    175       case XZ_ID_X86:
    176         p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
    177         break;
    178       CASE_BRA_CONV(PPC)
    179       CASE_BRA_CONV(IA64)
    180       CASE_BRA_CONV(ARM)
    181       CASE_BRA_CONV(ARMT)
    182       CASE_BRA_CONV(SPARC)
    183       default:
    184         return SZ_ERROR_UNSUPPORTED;
    185     }
    186     p->ip += (UInt32)p->bufConv;
    187 
    188     if (p->bufConv == 0)
    189     {
    190       if (!srcWasFinished)
    191         break;
    192       p->bufConv = p->bufTotal;
    193     }
    194   }
    195   if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
    196     *wasFinished = 1;
    197   return SZ_OK;
    198 }
    199 
    200 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)
    201 {
    202   CBraState *decoder;
    203   if (id != XZ_ID_Delta &&
    204       id != XZ_ID_X86 &&
    205       id != XZ_ID_PPC &&
    206       id != XZ_ID_IA64 &&
    207       id != XZ_ID_ARM &&
    208       id != XZ_ID_ARMT &&
    209       id != XZ_ID_SPARC)
    210     return SZ_ERROR_UNSUPPORTED;
    211   p->p = 0;
    212   decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));
    213   if (decoder == 0)
    214     return SZ_ERROR_MEM;
    215   decoder->methodId = (UInt32)id;
    216   decoder->encodeMode = encodeMode;
    217   p->p = decoder;
    218   p->Free = BraState_Free;
    219   p->SetProps = BraState_SetProps;
    220   p->Init = BraState_Init;
    221   p->Code = BraState_Code;
    222   return SZ_OK;
    223 }
    224 
    225 /* ---------- SbState ---------- */
    226 
    227 #ifdef USE_SUBBLOCK
    228 
    229 static void SbState_Free(void *pp, ISzAlloc *alloc)
    230 {
    231   CSbDec *p = (CSbDec *)pp;
    232   SbDec_Free(p);
    233   alloc->Free(alloc, pp);
    234 }
    235 
    236 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
    237 {
    238   pp = pp;
    239   props = props;
    240   alloc = alloc;
    241   return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    242 }
    243 
    244 static void SbState_Init(void *pp)
    245 {
    246   SbDec_Init((CSbDec *)pp);
    247 }
    248 
    249 static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    250     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    251 {
    252   CSbDec *p = (CSbDec *)pp;
    253   SRes res;
    254   srcWasFinished = srcWasFinished;
    255   p->dest = dest;
    256   p->destLen = *destLen;
    257   p->src = src;
    258   p->srcLen = *srcLen;
    259   p->finish = finishMode; /* change it */
    260   res = SbDec_Decode((CSbDec *)pp);
    261   *destLen -= p->destLen;
    262   *srcLen -= p->srcLen;
    263   *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
    264   return res;
    265 }
    266 
    267 SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
    268 {
    269   CSbDec *decoder;
    270   p->p = 0;
    271   decoder = alloc->Alloc(alloc, sizeof(CSbDec));
    272   if (decoder == 0)
    273     return SZ_ERROR_MEM;
    274   p->p = decoder;
    275   p->Free = SbState_Free;
    276   p->SetProps = SbState_SetProps;
    277   p->Init = SbState_Init;
    278   p->Code = SbState_Code;
    279   SbDec_Construct(decoder);
    280   SbDec_SetAlloc(decoder, alloc);
    281   return SZ_OK;
    282 }
    283 #endif
    284 
    285 /* ---------- Lzma2State ---------- */
    286 
    287 static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
    288 {
    289   Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
    290   alloc->Free(alloc, pp);
    291 }
    292 
    293 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
    294 {
    295   if (propSize != 1)
    296     return SZ_ERROR_UNSUPPORTED;
    297   return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
    298 }
    299 
    300 static void Lzma2State_Init(void *pp)
    301 {
    302   Lzma2Dec_Init((CLzma2Dec *)pp);
    303 }
    304 
    305 static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    306     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    307 {
    308   ELzmaStatus status;
    309   /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
    310   SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);
    311   srcWasFinished = srcWasFinished;
    312   *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
    313   return res;
    314 }
    315 
    316 static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
    317 {
    318   CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));
    319   p->p = decoder;
    320   if (decoder == 0)
    321     return SZ_ERROR_MEM;
    322   p->Free = Lzma2State_Free;
    323   p->SetProps = Lzma2State_SetProps;
    324   p->Init = Lzma2State_Init;
    325   p->Code = Lzma2State_Code;
    326   Lzma2Dec_Construct(decoder);
    327   return SZ_OK;
    328 }
    329 
    330 
    331 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
    332 {
    333   int i;
    334   p->alloc = alloc;
    335   p->buf = 0;
    336   p->numCoders = 0;
    337   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
    338     p->coders[i].p = NULL;
    339 }
    340 
    341 void MixCoder_Free(CMixCoder *p)
    342 {
    343   int i;
    344   for (i = 0; i < p->numCoders; i++)
    345   {
    346     IStateCoder *sc = &p->coders[i];
    347     if (p->alloc && sc->p)
    348       sc->Free(sc->p, p->alloc);
    349   }
    350   p->numCoders = 0;
    351   if (p->buf)
    352   {
    353     p->alloc->Free(p->alloc, p->buf);
    354     p->buf = 0; /* 9.31: the BUG was fixed */
    355   }
    356 }
    357 
    358 void MixCoder_Init(CMixCoder *p)
    359 {
    360   int i;
    361   for (i = 0; i < p->numCoders - 1; i++)
    362   {
    363     p->size[i] = 0;
    364     p->pos[i] = 0;
    365     p->finished[i] = 0;
    366   }
    367   for (i = 0; i < p->numCoders; i++)
    368   {
    369     IStateCoder *coder = &p->coders[i];
    370     coder->Init(coder->p);
    371   }
    372 }
    373 
    374 SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
    375 {
    376   IStateCoder *sc = &p->coders[coderIndex];
    377   p->ids[coderIndex] = methodId;
    378   switch(methodId)
    379   {
    380     case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
    381     #ifdef USE_SUBBLOCK
    382     case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
    383     #endif
    384   }
    385   if (coderIndex == 0)
    386     return SZ_ERROR_UNSUPPORTED;
    387   return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
    388 }
    389 
    390 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
    391     const Byte *src, SizeT *srcLen, int srcWasFinished,
    392     ECoderFinishMode finishMode, ECoderStatus *status)
    393 {
    394   SizeT destLenOrig = *destLen;
    395   SizeT srcLenOrig = *srcLen;
    396   Bool allFinished = True;
    397   *destLen = 0;
    398   *srcLen = 0;
    399   *status = CODER_STATUS_NOT_FINISHED;
    400 
    401   if (p->buf == 0)
    402   {
    403     p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
    404     if (p->buf == 0)
    405       return SZ_ERROR_MEM;
    406   }
    407 
    408   if (p->numCoders != 1)
    409     finishMode = CODER_FINISH_ANY;
    410 
    411   for (;;)
    412   {
    413     Bool processed = False;
    414     int i;
    415     /*
    416     if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
    417       break;
    418     */
    419 
    420     for (i = 0; i < p->numCoders; i++)
    421     {
    422       SRes res;
    423       IStateCoder *coder = &p->coders[i];
    424       Byte *destCur;
    425       SizeT destLenCur, srcLenCur;
    426       const Byte *srcCur;
    427       int srcFinishedCur;
    428       int encodingWasFinished;
    429 
    430       if (i == 0)
    431       {
    432         srcCur = src;
    433         srcLenCur = srcLenOrig - *srcLen;
    434         srcFinishedCur = srcWasFinished;
    435       }
    436       else
    437       {
    438         srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
    439         srcLenCur = p->size[i - 1] - p->pos[i - 1];
    440         srcFinishedCur = p->finished[i - 1];
    441       }
    442 
    443       if (i == p->numCoders - 1)
    444       {
    445         destCur = dest;
    446         destLenCur = destLenOrig - *destLen;
    447       }
    448       else
    449       {
    450         if (p->pos[i] != p->size[i])
    451           continue;
    452         destCur = p->buf + (CODER_BUF_SIZE * i);
    453         destLenCur = CODER_BUF_SIZE;
    454       }
    455 
    456       res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
    457 
    458       if (!encodingWasFinished)
    459         allFinished = False;
    460 
    461       if (i == 0)
    462       {
    463         *srcLen += srcLenCur;
    464         src += srcLenCur;
    465       }
    466       else
    467       {
    468         p->pos[i - 1] += srcLenCur;
    469       }
    470 
    471       if (i == p->numCoders - 1)
    472       {
    473         *destLen += destLenCur;
    474         dest += destLenCur;
    475       }
    476       else
    477       {
    478         p->size[i] = destLenCur;
    479         p->pos[i] = 0;
    480         p->finished[i] = encodingWasFinished;
    481       }
    482 
    483       if (res != SZ_OK)
    484         return res;
    485 
    486       if (destLenCur != 0 || srcLenCur != 0)
    487         processed = True;
    488     }
    489     if (!processed)
    490       break;
    491   }
    492   if (allFinished)
    493     *status = CODER_STATUS_FINISHED_WITH_MARK;
    494   return SZ_OK;
    495 }
    496 
    497 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
    498 {
    499   *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
    500   if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
    501       GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
    502     return SZ_ERROR_NO_ARCHIVE;
    503   return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    504 }
    505 
    506 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
    507 {
    508   return
    509       indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
    510       (GetUi32(buf) == CrcCalc(buf + 4, 6) &&
    511       flags == GetBe16(buf + 8) &&
    512       memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
    513 }
    514 
    515 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
    516   { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
    517   if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
    518 
    519 
    520 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
    521 {
    522   unsigned pos;
    523   int numFilters, i;
    524   UInt32 headerSize = (UInt32)header[0] << 2;
    525 
    526   if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
    527     return SZ_ERROR_ARCHIVE;
    528 
    529   pos = 1;
    530   if (pos == headerSize)
    531     return SZ_ERROR_ARCHIVE;
    532   p->flags = header[pos++];
    533 
    534   if (XzBlock_HasPackSize(p))
    535   {
    536     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
    537     if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
    538       return SZ_ERROR_ARCHIVE;
    539   }
    540 
    541   if (XzBlock_HasUnpackSize(p))
    542     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
    543 
    544   numFilters = XzBlock_GetNumFilters(p);
    545   for (i = 0; i < numFilters; i++)
    546   {
    547     CXzFilter *filter = p->filters + i;
    548     UInt64 size;
    549     READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
    550     READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
    551     if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
    552       return SZ_ERROR_ARCHIVE;
    553     filter->propsSize = (UInt32)size;
    554     memcpy(filter->props, header + pos, (size_t)size);
    555     pos += (unsigned)size;
    556 
    557     #ifdef XZ_DUMP
    558     printf("\nf[%d] = %2X: ", i, filter->id);
    559     {
    560       int i;
    561       for (i = 0; i < size; i++)
    562         printf(" %2X", filter->props[i]);
    563     }
    564     #endif
    565   }
    566 
    567   while (pos < headerSize)
    568     if (header[pos++] != 0)
    569       return SZ_ERROR_ARCHIVE;
    570   return SZ_OK;
    571 }
    572 
    573 SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
    574 {
    575   int i;
    576   Bool needReInit = True;
    577   int numFilters = XzBlock_GetNumFilters(block);
    578   if (numFilters == p->numCoders)
    579   {
    580     for (i = 0; i < numFilters; i++)
    581       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
    582         break;
    583     needReInit = (i != numFilters);
    584   }
    585   if (needReInit)
    586   {
    587     MixCoder_Free(p);
    588     p->numCoders = numFilters;
    589     for (i = 0; i < numFilters; i++)
    590     {
    591       const CXzFilter *f = &block->filters[numFilters - 1 - i];
    592       RINOK(MixCoder_SetFromMethod(p, i, f->id));
    593     }
    594   }
    595   for (i = 0; i < numFilters; i++)
    596   {
    597     const CXzFilter *f = &block->filters[numFilters - 1 - i];
    598     IStateCoder *sc = &p->coders[i];
    599     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
    600   }
    601   MixCoder_Init(p);
    602   return SZ_OK;
    603 }
    604 
    605 void XzUnpacker_Init(CXzUnpacker *p)
    606 {
    607   p->state = XZ_STATE_STREAM_HEADER;
    608   p->pos = 0;
    609   p->numStartedStreams = 0;
    610   p->numFinishedStreams = 0;
    611   p->numTotalBlocks = 0;
    612   p->padSize = 0;
    613 }
    614 
    615 void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
    616 {
    617   MixCoder_Construct(&p->decoder, alloc);
    618   XzUnpacker_Init(p);
    619 }
    620 
    621 void XzUnpacker_Free(CXzUnpacker *p)
    622 {
    623   MixCoder_Free(&p->decoder);
    624 }
    625 
    626 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
    627     const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
    628 {
    629   SizeT destLenOrig = *destLen;
    630   SizeT srcLenOrig = *srcLen;
    631   *destLen = 0;
    632   *srcLen = 0;
    633   *status = CODER_STATUS_NOT_SPECIFIED;
    634   for (;;)
    635   {
    636     SizeT srcRem = srcLenOrig - *srcLen;
    637 
    638     if (p->state == XZ_STATE_BLOCK)
    639     {
    640       SizeT destLen2 = destLenOrig - *destLen;
    641       SizeT srcLen2 = srcLenOrig - *srcLen;
    642       SRes res;
    643       if (srcLen2 == 0 && destLen2 == 0)
    644       {
    645         *status = CODER_STATUS_NOT_FINISHED;
    646         return SZ_OK;
    647       }
    648 
    649       res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
    650       XzCheck_Update(&p->check, dest, destLen2);
    651 
    652       (*srcLen) += srcLen2;
    653       src += srcLen2;
    654       p->packSize += srcLen2;
    655 
    656       (*destLen) += destLen2;
    657       dest += destLen2;
    658       p->unpackSize += destLen2;
    659 
    660       RINOK(res);
    661 
    662       if (*status == CODER_STATUS_FINISHED_WITH_MARK)
    663       {
    664         Byte temp[32];
    665         unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
    666         num += Xz_WriteVarInt(temp + num, p->unpackSize);
    667         Sha256_Update(&p->sha, temp, num);
    668         p->indexSize += num;
    669         p->numBlocks++;
    670 
    671         p->state = XZ_STATE_BLOCK_FOOTER;
    672         p->pos = 0;
    673         p->alignPos = 0;
    674       }
    675       else if (srcLen2 == 0 && destLen2 == 0)
    676         return SZ_OK;
    677 
    678       continue;
    679     }
    680 
    681     if (srcRem == 0)
    682     {
    683       *status = CODER_STATUS_NEEDS_MORE_INPUT;
    684       return SZ_OK;
    685     }
    686 
    687     switch (p->state)
    688     {
    689       case XZ_STATE_STREAM_HEADER:
    690       {
    691         if (p->pos < XZ_STREAM_HEADER_SIZE)
    692         {
    693           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
    694             return SZ_ERROR_NO_ARCHIVE;
    695           p->buf[p->pos++] = *src++;
    696           (*srcLen)++;
    697         }
    698         else
    699         {
    700           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
    701           p->numStartedStreams++;
    702           p->state = XZ_STATE_BLOCK_HEADER;
    703           Sha256_Init(&p->sha);
    704           p->indexSize = 0;
    705           p->numBlocks = 0;
    706           p->pos = 0;
    707         }
    708         break;
    709       }
    710 
    711       case XZ_STATE_BLOCK_HEADER:
    712       {
    713         if (p->pos == 0)
    714         {
    715           p->buf[p->pos++] = *src++;
    716           (*srcLen)++;
    717           if (p->buf[0] == 0)
    718           {
    719             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
    720             p->indexPos = p->indexPreSize;
    721             p->indexSize += p->indexPreSize;
    722             Sha256_Final(&p->sha, p->shaDigest);
    723             Sha256_Init(&p->sha);
    724             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
    725             p->state = XZ_STATE_STREAM_INDEX;
    726           }
    727           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
    728         }
    729         else if (p->pos != p->blockHeaderSize)
    730         {
    731           UInt32 cur = p->blockHeaderSize - p->pos;
    732           if (cur > srcRem)
    733             cur = (UInt32)srcRem;
    734           memcpy(p->buf + p->pos, src, cur);
    735           p->pos += cur;
    736           (*srcLen) += cur;
    737           src += cur;
    738         }
    739         else
    740         {
    741           RINOK(XzBlock_Parse(&p->block, p->buf));
    742           p->numTotalBlocks++;
    743           p->state = XZ_STATE_BLOCK;
    744           p->packSize = 0;
    745           p->unpackSize = 0;
    746           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
    747           RINOK(XzDec_Init(&p->decoder, &p->block));
    748         }
    749         break;
    750       }
    751 
    752       case XZ_STATE_BLOCK_FOOTER:
    753       {
    754         if (((p->packSize + p->alignPos) & 3) != 0)
    755         {
    756           (*srcLen)++;
    757           p->alignPos++;
    758           if (*src++ != 0)
    759             return SZ_ERROR_CRC;
    760         }
    761         else
    762         {
    763           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
    764           UInt32 cur = checkSize - p->pos;
    765           if (cur != 0)
    766           {
    767             if (cur > srcRem)
    768               cur = (UInt32)srcRem;
    769             memcpy(p->buf + p->pos, src, cur);
    770             p->pos += cur;
    771             (*srcLen) += cur;
    772             src += cur;
    773           }
    774           else
    775           {
    776             Byte digest[XZ_CHECK_SIZE_MAX];
    777             p->state = XZ_STATE_BLOCK_HEADER;
    778             p->pos = 0;
    779             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
    780               return SZ_ERROR_CRC;
    781           }
    782         }
    783         break;
    784       }
    785 
    786       case XZ_STATE_STREAM_INDEX:
    787       {
    788         if (p->pos < p->indexPreSize)
    789         {
    790           (*srcLen)++;
    791           if (*src++ != p->buf[p->pos++])
    792             return SZ_ERROR_CRC;
    793         }
    794         else
    795         {
    796           if (p->indexPos < p->indexSize)
    797           {
    798             UInt64 cur = p->indexSize - p->indexPos;
    799             if (srcRem > cur)
    800               srcRem = (SizeT)cur;
    801             p->crc = CrcUpdate(p->crc, src, srcRem);
    802             Sha256_Update(&p->sha, src, srcRem);
    803             (*srcLen) += srcRem;
    804             src += srcRem;
    805             p->indexPos += srcRem;
    806           }
    807           else if ((p->indexPos & 3) != 0)
    808           {
    809             Byte b = *src++;
    810             p->crc = CRC_UPDATE_BYTE(p->crc, b);
    811             (*srcLen)++;
    812             p->indexPos++;
    813             p->indexSize++;
    814             if (b != 0)
    815               return SZ_ERROR_CRC;
    816           }
    817           else
    818           {
    819             Byte digest[SHA256_DIGEST_SIZE];
    820             p->state = XZ_STATE_STREAM_INDEX_CRC;
    821             p->indexSize += 4;
    822             p->pos = 0;
    823             Sha256_Final(&p->sha, digest);
    824             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
    825               return SZ_ERROR_CRC;
    826           }
    827         }
    828         break;
    829       }
    830 
    831       case XZ_STATE_STREAM_INDEX_CRC:
    832       {
    833         if (p->pos < 4)
    834         {
    835           (*srcLen)++;
    836           p->buf[p->pos++] = *src++;
    837         }
    838         else
    839         {
    840           p->state = XZ_STATE_STREAM_FOOTER;
    841           p->pos = 0;
    842           if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
    843             return SZ_ERROR_CRC;
    844         }
    845         break;
    846       }
    847 
    848       case XZ_STATE_STREAM_FOOTER:
    849       {
    850         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
    851         if (cur > srcRem)
    852           cur = (UInt32)srcRem;
    853         memcpy(p->buf + p->pos, src, cur);
    854         p->pos += cur;
    855         (*srcLen) += cur;
    856         src += cur;
    857         if (p->pos == XZ_STREAM_FOOTER_SIZE)
    858         {
    859           p->state = XZ_STATE_STREAM_PADDING;
    860           p->numFinishedStreams++;
    861           p->padSize = 0;
    862           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
    863             return SZ_ERROR_CRC;
    864         }
    865         break;
    866       }
    867 
    868       case XZ_STATE_STREAM_PADDING:
    869       {
    870         if (*src != 0)
    871         {
    872           if (((UInt32)p->padSize & 3) != 0)
    873             return SZ_ERROR_NO_ARCHIVE;
    874           p->pos = 0;
    875           p->state = XZ_STATE_STREAM_HEADER;
    876         }
    877         else
    878         {
    879           (*srcLen)++;
    880           src++;
    881           p->padSize++;
    882         }
    883         break;
    884       }
    885 
    886       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
    887     }
    888   }
    889   /*
    890   if (p->state == XZ_STATE_FINISHED)
    891     *status = CODER_STATUS_FINISHED_WITH_MARK;
    892   return SZ_OK;
    893   */
    894 }
    895 
    896 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
    897 {
    898   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
    899 }
    900 
    901 UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)
    902 {
    903   UInt64 num = 0;
    904   if (p->state == XZ_STATE_STREAM_PADDING)
    905     num += p->padSize;
    906   else if (p->state == XZ_STATE_STREAM_HEADER)
    907     num += p->padSize + p->pos;
    908   return num;
    909 }
    910