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