1 /* XzDec.c -- Xz Decode
2 2010-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 
Xz_ReadVarInt(const Byte * p,size_t maxSize,UInt64 * value)30 unsigned 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 
50 typedef 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 
BraState_Free(void * pp,ISzAlloc * alloc)66 void BraState_Free(void *pp, ISzAlloc *alloc)
67 {
68   alloc->Free(alloc, pp);
69 }
70 
BraState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAlloc * alloc)71 SRes 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 
BraState_Init(void * pp)113 void 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 
BraState_Code(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,int * wasFinished)124 static 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 
BraState_SetFromMethod(IStateCoder * p,UInt64 id,ISzAlloc * alloc)198 SRes 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 
SbState_Free(void * pp,ISzAlloc * alloc)226 static 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 
SbState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAlloc * alloc)233 static 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 
SbState_Init(void * pp)241 static void SbState_Init(void *pp)
242 {
243   SubblockDec_Init((CSubblockDec *)pp);
244 }
245 
SbState_Code(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,int * wasFinished)246 static 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 
SbState_SetFromMethod(IStateCoder * p,ISzAlloc * alloc)256 SRes 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 
Lzma2State_Free(void * pp,ISzAlloc * alloc)275 static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
276 {
277   Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
278   alloc->Free(alloc, pp);
279 }
280 
Lzma2State_SetProps(void * pp,const Byte * props,size_t propSize,ISzAlloc * alloc)281 static 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 
Lzma2State_Init(void * pp)288 static void Lzma2State_Init(void *pp)
289 {
290   Lzma2Dec_Init((CLzma2Dec *)pp);
291 }
292 
Lzma2State_Code(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,int * wasFinished)293 static 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 
Lzma2State_SetFromMethod(IStateCoder * p,ISzAlloc * alloc)304 static 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 
MixCoder_Construct(CMixCoder * p,ISzAlloc * alloc)319 void 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 
MixCoder_Free(CMixCoder * p)329 void 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 
MixCoder_Init(CMixCoder * p)343 void 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 
MixCoder_SetFromMethod(CMixCoder * p,int coderIndex,UInt64 methodId)359 SRes 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 
MixCoder_Code(CMixCoder * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)375 SRes 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 
Xz_ParseHeader(CXzStreamFlags * p,const Byte * buf)482 SRes 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 
Xz_CheckFooter(CXzStreamFlags flags,UInt64 indexSize,const Byte * buf)491 static 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 
XzBlock_Parse(CXzBlock * p,const Byte * header)505 SRes 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 
XzDec_Init(CMixCoder * p,const CXzBlock * block)558 SRes 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 
XzUnpacker_Create(CXzUnpacker * p,ISzAlloc * alloc)590 SRes 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 
XzUnpacker_Free(CXzUnpacker * p)599 void XzUnpacker_Free(CXzUnpacker *p)
600 {
601   MixCoder_Free(&p->decoder);
602 }
603 
XzUnpacker_Code(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int finishMode,ECoderStatus * status)604 SRes 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 
XzUnpacker_IsStreamWasFinished(CXzUnpacker * p)872 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
873 {
874   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
875 }
876