Home | History | Annotate | Download | only in C
      1 /* XzDec.c -- Xz Decode
      2 2015-11-09 : 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   unsigned i, limit;
     36   *value = 0;
     37   limit = (maxSize > 9) ? 9 : (unsigned)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 static void BraState_Free(void *pp, ISzAlloc *alloc)
     70 {
     71   alloc->Free(alloc, pp);
     72 }
     73 
     74 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
     75 {
     76   CBraState *p = ((CBraState *)pp);
     77   UNUSED_VAR(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 static 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   UNUSED_VAR(finishMode);
    133   *destLen = 0;
    134   *srcLen = 0;
    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   UNUSED_VAR(pp);
    239   UNUSED_VAR(props);
    240   UNUSED_VAR(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   UNUSED_VAR(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   UNUSED_VAR(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   unsigned i;
    334   p->alloc = alloc;
    335   p->buf = NULL;
    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   unsigned 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 = NULL; /* 9.31: the BUG was fixed */
    355   }
    356 }
    357 
    358 void MixCoder_Init(CMixCoder *p)
    359 {
    360   unsigned i;
    361   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 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, unsigned 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)
    402   {
    403     p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
    404     if (!p->buf)
    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     unsigned 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   unsigned numFilters, i;
    524   unsigned headerSize = (unsigned)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[%u] = %2X: ", i, (unsigned)filter->id);
    559     {
    560       unsigned 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   unsigned i;
    576   Bool needReInit = True;
    577   unsigned numFilters = XzBlock_GetNumFilters(block);
    578 
    579   if (numFilters == p->numCoders)
    580   {
    581     for (i = 0; i < numFilters; i++)
    582       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
    583         break;
    584     needReInit = (i != numFilters);
    585   }
    586 
    587   if (needReInit)
    588   {
    589     MixCoder_Free(p);
    590     p->numCoders = numFilters;
    591     for (i = 0; i < numFilters; i++)
    592     {
    593       const CXzFilter *f = &block->filters[numFilters - 1 - i];
    594       RINOK(MixCoder_SetFromMethod(p, i, f->id));
    595     }
    596   }
    597 
    598   for (i = 0; i < numFilters; i++)
    599   {
    600     const CXzFilter *f = &block->filters[numFilters - 1 - i];
    601     IStateCoder *sc = &p->coders[i];
    602     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
    603   }
    604 
    605   MixCoder_Init(p);
    606   return SZ_OK;
    607 }
    608 
    609 void XzUnpacker_Init(CXzUnpacker *p)
    610 {
    611   p->state = XZ_STATE_STREAM_HEADER;
    612   p->pos = 0;
    613   p->numStartedStreams = 0;
    614   p->numFinishedStreams = 0;
    615   p->numTotalBlocks = 0;
    616   p->padSize = 0;
    617 }
    618 
    619 void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
    620 {
    621   MixCoder_Construct(&p->decoder, alloc);
    622   XzUnpacker_Init(p);
    623 }
    624 
    625 void XzUnpacker_Free(CXzUnpacker *p)
    626 {
    627   MixCoder_Free(&p->decoder);
    628 }
    629 
    630 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
    631     const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
    632 {
    633   SizeT destLenOrig = *destLen;
    634   SizeT srcLenOrig = *srcLen;
    635   *destLen = 0;
    636   *srcLen = 0;
    637   *status = CODER_STATUS_NOT_SPECIFIED;
    638   for (;;)
    639   {
    640     SizeT srcRem = srcLenOrig - *srcLen;
    641 
    642     if (p->state == XZ_STATE_BLOCK)
    643     {
    644       SizeT destLen2 = destLenOrig - *destLen;
    645       SizeT srcLen2 = srcLenOrig - *srcLen;
    646       SRes res;
    647       if (srcLen2 == 0 && destLen2 == 0)
    648       {
    649         *status = CODER_STATUS_NOT_FINISHED;
    650         return SZ_OK;
    651       }
    652 
    653       res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
    654       XzCheck_Update(&p->check, dest, destLen2);
    655 
    656       (*srcLen) += srcLen2;
    657       src += srcLen2;
    658       p->packSize += srcLen2;
    659 
    660       (*destLen) += destLen2;
    661       dest += destLen2;
    662       p->unpackSize += destLen2;
    663 
    664       RINOK(res);
    665 
    666       if (*status == CODER_STATUS_FINISHED_WITH_MARK)
    667       {
    668         Byte temp[32];
    669         unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
    670         num += Xz_WriteVarInt(temp + num, p->unpackSize);
    671         Sha256_Update(&p->sha, temp, num);
    672         p->indexSize += num;
    673         p->numBlocks++;
    674 
    675         p->state = XZ_STATE_BLOCK_FOOTER;
    676         p->pos = 0;
    677         p->alignPos = 0;
    678       }
    679       else if (srcLen2 == 0 && destLen2 == 0)
    680         return SZ_OK;
    681 
    682       continue;
    683     }
    684 
    685     if (srcRem == 0)
    686     {
    687       *status = CODER_STATUS_NEEDS_MORE_INPUT;
    688       return SZ_OK;
    689     }
    690 
    691     switch (p->state)
    692     {
    693       case XZ_STATE_STREAM_HEADER:
    694       {
    695         if (p->pos < XZ_STREAM_HEADER_SIZE)
    696         {
    697           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
    698             return SZ_ERROR_NO_ARCHIVE;
    699           p->buf[p->pos++] = *src++;
    700           (*srcLen)++;
    701         }
    702         else
    703         {
    704           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
    705           p->numStartedStreams++;
    706           p->state = XZ_STATE_BLOCK_HEADER;
    707           Sha256_Init(&p->sha);
    708           p->indexSize = 0;
    709           p->numBlocks = 0;
    710           p->pos = 0;
    711         }
    712         break;
    713       }
    714 
    715       case XZ_STATE_BLOCK_HEADER:
    716       {
    717         if (p->pos == 0)
    718         {
    719           p->buf[p->pos++] = *src++;
    720           (*srcLen)++;
    721           if (p->buf[0] == 0)
    722           {
    723             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
    724             p->indexPos = p->indexPreSize;
    725             p->indexSize += p->indexPreSize;
    726             Sha256_Final(&p->sha, p->shaDigest);
    727             Sha256_Init(&p->sha);
    728             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
    729             p->state = XZ_STATE_STREAM_INDEX;
    730           }
    731           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
    732         }
    733         else if (p->pos != p->blockHeaderSize)
    734         {
    735           UInt32 cur = p->blockHeaderSize - p->pos;
    736           if (cur > srcRem)
    737             cur = (UInt32)srcRem;
    738           memcpy(p->buf + p->pos, src, cur);
    739           p->pos += cur;
    740           (*srcLen) += cur;
    741           src += cur;
    742         }
    743         else
    744         {
    745           RINOK(XzBlock_Parse(&p->block, p->buf));
    746           p->numTotalBlocks++;
    747           p->state = XZ_STATE_BLOCK;
    748           p->packSize = 0;
    749           p->unpackSize = 0;
    750           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
    751           RINOK(XzDec_Init(&p->decoder, &p->block));
    752         }
    753         break;
    754       }
    755 
    756       case XZ_STATE_BLOCK_FOOTER:
    757       {
    758         if (((p->packSize + p->alignPos) & 3) != 0)
    759         {
    760           (*srcLen)++;
    761           p->alignPos++;
    762           if (*src++ != 0)
    763             return SZ_ERROR_CRC;
    764         }
    765         else
    766         {
    767           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
    768           UInt32 cur = checkSize - p->pos;
    769           if (cur != 0)
    770           {
    771             if (cur > srcRem)
    772               cur = (UInt32)srcRem;
    773             memcpy(p->buf + p->pos, src, cur);
    774             p->pos += cur;
    775             (*srcLen) += cur;
    776             src += cur;
    777           }
    778           else
    779           {
    780             Byte digest[XZ_CHECK_SIZE_MAX];
    781             p->state = XZ_STATE_BLOCK_HEADER;
    782             p->pos = 0;
    783             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
    784               return SZ_ERROR_CRC;
    785           }
    786         }
    787         break;
    788       }
    789 
    790       case XZ_STATE_STREAM_INDEX:
    791       {
    792         if (p->pos < p->indexPreSize)
    793         {
    794           (*srcLen)++;
    795           if (*src++ != p->buf[p->pos++])
    796             return SZ_ERROR_CRC;
    797         }
    798         else
    799         {
    800           if (p->indexPos < p->indexSize)
    801           {
    802             UInt64 cur = p->indexSize - p->indexPos;
    803             if (srcRem > cur)
    804               srcRem = (SizeT)cur;
    805             p->crc = CrcUpdate(p->crc, src, srcRem);
    806             Sha256_Update(&p->sha, src, srcRem);
    807             (*srcLen) += srcRem;
    808             src += srcRem;
    809             p->indexPos += srcRem;
    810           }
    811           else if ((p->indexPos & 3) != 0)
    812           {
    813             Byte b = *src++;
    814             p->crc = CRC_UPDATE_BYTE(p->crc, b);
    815             (*srcLen)++;
    816             p->indexPos++;
    817             p->indexSize++;
    818             if (b != 0)
    819               return SZ_ERROR_CRC;
    820           }
    821           else
    822           {
    823             Byte digest[SHA256_DIGEST_SIZE];
    824             p->state = XZ_STATE_STREAM_INDEX_CRC;
    825             p->indexSize += 4;
    826             p->pos = 0;
    827             Sha256_Final(&p->sha, digest);
    828             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
    829               return SZ_ERROR_CRC;
    830           }
    831         }
    832         break;
    833       }
    834 
    835       case XZ_STATE_STREAM_INDEX_CRC:
    836       {
    837         if (p->pos < 4)
    838         {
    839           (*srcLen)++;
    840           p->buf[p->pos++] = *src++;
    841         }
    842         else
    843         {
    844           p->state = XZ_STATE_STREAM_FOOTER;
    845           p->pos = 0;
    846           if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
    847             return SZ_ERROR_CRC;
    848         }
    849         break;
    850       }
    851 
    852       case XZ_STATE_STREAM_FOOTER:
    853       {
    854         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
    855         if (cur > srcRem)
    856           cur = (UInt32)srcRem;
    857         memcpy(p->buf + p->pos, src, cur);
    858         p->pos += cur;
    859         (*srcLen) += cur;
    860         src += cur;
    861         if (p->pos == XZ_STREAM_FOOTER_SIZE)
    862         {
    863           p->state = XZ_STATE_STREAM_PADDING;
    864           p->numFinishedStreams++;
    865           p->padSize = 0;
    866           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
    867             return SZ_ERROR_CRC;
    868         }
    869         break;
    870       }
    871 
    872       case XZ_STATE_STREAM_PADDING:
    873       {
    874         if (*src != 0)
    875         {
    876           if (((UInt32)p->padSize & 3) != 0)
    877             return SZ_ERROR_NO_ARCHIVE;
    878           p->pos = 0;
    879           p->state = XZ_STATE_STREAM_HEADER;
    880         }
    881         else
    882         {
    883           (*srcLen)++;
    884           src++;
    885           p->padSize++;
    886         }
    887         break;
    888       }
    889 
    890       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
    891     }
    892   }
    893   /*
    894   if (p->state == XZ_STATE_FINISHED)
    895     *status = CODER_STATUS_FINISHED_WITH_MARK;
    896   return SZ_OK;
    897   */
    898 }
    899 
    900 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
    901 {
    902   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
    903 }
    904 
    905 UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)
    906 {
    907   UInt64 num = 0;
    908   if (p->state == XZ_STATE_STREAM_PADDING)
    909     num += p->padSize;
    910   else if (p->state == XZ_STATE_STREAM_HEADER)
    911     num += p->padSize + p->pos;
    912   return num;
    913 }
    914