• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* XzDec.c -- Xz Decode
2 2021-09-04 : Igor Pavlov : Public domain */
3 
4 #include "Precomp.h"
5 
6 // #include <stdio.h>
7 
8 // #define XZ_DUMP
9 
10 /* #define XZ_DUMP */
11 
12 #ifdef XZ_DUMP
13 #include <stdio.h>
14 #endif
15 
16 // #define SHOW_DEBUG_INFO
17 
18 #ifdef SHOW_DEBUG_INFO
19 #include <stdio.h>
20 #endif
21 
22 #ifdef SHOW_DEBUG_INFO
23 #define PRF(x) x
24 #else
25 #define PRF(x)
26 #endif
27 
28 #define PRF_STR(s) PRF(printf("\n" s "\n"))
29 #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include "7zCrc.h"
35 #include "Alloc.h"
36 #include "Bra.h"
37 #include "CpuArch.h"
38 #include "Delta.h"
39 #include "Lzma2Dec.h"
40 
41 // #define USE_SUBBLOCK
42 
43 #ifdef USE_SUBBLOCK
44 #include "Bcj3Dec.c"
45 #include "SbDec.h"
46 #endif
47 
48 #include "Xz.h"
49 
50 #define XZ_CHECK_SIZE_MAX 64
51 
52 #define CODER_BUF_SIZE ((size_t)1 << 17)
53 
Xz_ReadVarInt(const Byte * p,size_t maxSize,UInt64 * value)54 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
55 {
56   unsigned i, limit;
57   *value = 0;
58   limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
59 
60   for (i = 0; i < limit;)
61   {
62     Byte b = p[i];
63     *value |= (UInt64)(b & 0x7F) << (7 * i++);
64     if ((b & 0x80) == 0)
65       return (b == 0 && i != 1) ? 0 : i;
66   }
67   return 0;
68 }
69 
70 /* ---------- BraState ---------- */
71 
72 #define BRA_BUF_SIZE (1 << 14)
73 
74 typedef struct
75 {
76   size_t bufPos;
77   size_t bufConv;
78   size_t bufTotal;
79 
80   int encodeMode;
81 
82   UInt32 methodId;
83   UInt32 delta;
84   UInt32 ip;
85   UInt32 x86State;
86   Byte deltaState[DELTA_STATE_SIZE];
87 
88   Byte buf[BRA_BUF_SIZE];
89 } CBraState;
90 
BraState_Free(void * pp,ISzAllocPtr alloc)91 static void BraState_Free(void *pp, ISzAllocPtr alloc)
92 {
93   ISzAlloc_Free(alloc, pp);
94 }
95 
BraState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)96 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
97 {
98   CBraState *p = ((CBraState *)pp);
99   UNUSED_VAR(alloc);
100   p->ip = 0;
101   if (p->methodId == XZ_ID_Delta)
102   {
103     if (propSize != 1)
104       return SZ_ERROR_UNSUPPORTED;
105     p->delta = (unsigned)props[0] + 1;
106   }
107   else
108   {
109     if (propSize == 4)
110     {
111       UInt32 v = GetUi32(props);
112       switch (p->methodId)
113       {
114         case XZ_ID_PPC:
115         case XZ_ID_ARM:
116         case XZ_ID_SPARC:
117           if ((v & 3) != 0)
118             return SZ_ERROR_UNSUPPORTED;
119           break;
120         case XZ_ID_ARMT:
121           if ((v & 1) != 0)
122             return SZ_ERROR_UNSUPPORTED;
123           break;
124         case XZ_ID_IA64:
125           if ((v & 0xF) != 0)
126             return SZ_ERROR_UNSUPPORTED;
127           break;
128       }
129       p->ip = v;
130     }
131     else if (propSize != 0)
132       return SZ_ERROR_UNSUPPORTED;
133   }
134   return SZ_OK;
135 }
136 
BraState_Init(void * pp)137 static void BraState_Init(void *pp)
138 {
139   CBraState *p = ((CBraState *)pp);
140   p->bufPos = p->bufConv = p->bufTotal = 0;
141   x86_Convert_Init(p->x86State);
142   if (p->methodId == XZ_ID_Delta)
143     Delta_Init(p->deltaState);
144 }
145 
146 
147 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;
148 
BraState_Filter(void * pp,Byte * data,SizeT size)149 static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
150 {
151   CBraState *p = ((CBraState *)pp);
152   switch (p->methodId)
153   {
154     case XZ_ID_Delta:
155       if (p->encodeMode)
156         Delta_Encode(p->deltaState, p->delta, data, size);
157       else
158         Delta_Decode(p->deltaState, p->delta, data, size);
159       break;
160     case XZ_ID_X86:
161       size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);
162       break;
163     CASE_BRA_CONV(PPC)
164     CASE_BRA_CONV(IA64)
165     CASE_BRA_CONV(ARM)
166     CASE_BRA_CONV(ARMT)
167     CASE_BRA_CONV(SPARC)
168   }
169   p->ip += (UInt32)size;
170   return size;
171 }
172 
173 
BraState_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)174 static SRes BraState_Code2(void *pp,
175     Byte *dest, SizeT *destLen,
176     const Byte *src, SizeT *srcLen, int srcWasFinished,
177     ECoderFinishMode finishMode,
178     // int *wasFinished
179     ECoderStatus *status)
180 {
181   CBraState *p = ((CBraState *)pp);
182   SizeT destRem = *destLen;
183   SizeT srcRem = *srcLen;
184   UNUSED_VAR(finishMode);
185 
186   *destLen = 0;
187   *srcLen = 0;
188   // *wasFinished = False;
189   *status = CODER_STATUS_NOT_FINISHED;
190 
191   while (destRem > 0)
192   {
193     if (p->bufPos != p->bufConv)
194     {
195       size_t size = p->bufConv - p->bufPos;
196       if (size > destRem)
197         size = destRem;
198       memcpy(dest, p->buf + p->bufPos, size);
199       p->bufPos += size;
200       *destLen += size;
201       dest += size;
202       destRem -= size;
203       continue;
204     }
205 
206     p->bufTotal -= p->bufPos;
207     memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
208     p->bufPos = 0;
209     p->bufConv = 0;
210     {
211       size_t size = BRA_BUF_SIZE - p->bufTotal;
212       if (size > srcRem)
213         size = srcRem;
214       memcpy(p->buf + p->bufTotal, src, size);
215       *srcLen += size;
216       src += size;
217       srcRem -= size;
218       p->bufTotal += size;
219     }
220     if (p->bufTotal == 0)
221       break;
222 
223     p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
224 
225     if (p->bufConv == 0)
226     {
227       if (!srcWasFinished)
228         break;
229       p->bufConv = p->bufTotal;
230     }
231   }
232 
233   if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
234   {
235     *status = CODER_STATUS_FINISHED_WITH_MARK;
236     // *wasFinished = 1;
237   }
238 
239   return SZ_OK;
240 }
241 
242 
243 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc);
BraState_SetFromMethod(IStateCoder * p,UInt64 id,int encodeMode,ISzAllocPtr alloc)244 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
245 {
246   CBraState *decoder;
247   if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
248     return SZ_ERROR_UNSUPPORTED;
249   decoder = (CBraState *)p->p;
250   if (!decoder)
251   {
252     decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
253     if (!decoder)
254       return SZ_ERROR_MEM;
255     p->p = decoder;
256     p->Free = BraState_Free;
257     p->SetProps = BraState_SetProps;
258     p->Init = BraState_Init;
259     p->Code2 = BraState_Code2;
260     p->Filter = BraState_Filter;
261   }
262   decoder->methodId = (UInt32)id;
263   decoder->encodeMode = encodeMode;
264   return SZ_OK;
265 }
266 
267 
268 
269 /* ---------- SbState ---------- */
270 
271 #ifdef USE_SUBBLOCK
272 
SbState_Free(void * pp,ISzAllocPtr alloc)273 static void SbState_Free(void *pp, ISzAllocPtr alloc)
274 {
275   CSbDec *p = (CSbDec *)pp;
276   SbDec_Free(p);
277   ISzAlloc_Free(alloc, pp);
278 }
279 
SbState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)280 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
281 {
282   UNUSED_VAR(pp);
283   UNUSED_VAR(props);
284   UNUSED_VAR(alloc);
285   return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
286 }
287 
SbState_Init(void * pp)288 static void SbState_Init(void *pp)
289 {
290   SbDec_Init((CSbDec *)pp);
291 }
292 
SbState_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)293 static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
294     int srcWasFinished, ECoderFinishMode finishMode,
295     // int *wasFinished
296     ECoderStatus *status)
297 {
298   CSbDec *p = (CSbDec *)pp;
299   SRes res;
300   UNUSED_VAR(srcWasFinished);
301   p->dest = dest;
302   p->destLen = *destLen;
303   p->src = src;
304   p->srcLen = *srcLen;
305   p->finish = finishMode; /* change it */
306   res = SbDec_Decode((CSbDec *)pp);
307   *destLen -= p->destLen;
308   *srcLen -= p->srcLen;
309   // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
310   *status = (*destLen == 0 && *srcLen == 0) ?
311       CODER_STATUS_FINISHED_WITH_MARK :
312       CODER_STATUS_NOT_FINISHED;
313   return res;
314 }
315 
SbState_SetFromMethod(IStateCoder * p,ISzAllocPtr alloc)316 static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
317 {
318   CSbDec *decoder = (CSbDec *)p->p;
319   if (!decoder)
320   {
321     decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
322     if (!decoder)
323       return SZ_ERROR_MEM;
324     p->p = decoder;
325     p->Free = SbState_Free;
326     p->SetProps = SbState_SetProps;
327     p->Init = SbState_Init;
328     p->Code2 = SbState_Code2;
329     p->Filter = NULL;
330   }
331   SbDec_Construct(decoder);
332   SbDec_SetAlloc(decoder, alloc);
333   return SZ_OK;
334 }
335 
336 #endif
337 
338 
339 
340 /* ---------- Lzma2 ---------- */
341 
342 typedef struct
343 {
344   CLzma2Dec decoder;
345   BoolInt outBufMode;
346 } CLzma2Dec_Spec;
347 
348 
Lzma2State_Free(void * pp,ISzAllocPtr alloc)349 static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
350 {
351   CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
352   if (p->outBufMode)
353     Lzma2Dec_FreeProbs(&p->decoder, alloc);
354   else
355     Lzma2Dec_Free(&p->decoder, alloc);
356   ISzAlloc_Free(alloc, pp);
357 }
358 
Lzma2State_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)359 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
360 {
361   if (propSize != 1)
362     return SZ_ERROR_UNSUPPORTED;
363   {
364     CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
365     if (p->outBufMode)
366       return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
367     else
368       return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
369   }
370 }
371 
Lzma2State_Init(void * pp)372 static void Lzma2State_Init(void *pp)
373 {
374   Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
375 }
376 
377 
378 /*
379   if (outBufMode), then (dest) is not used. Use NULL.
380          Data is unpacked to (spec->decoder.decoder.dic) output buffer.
381 */
382 
Lzma2State_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)383 static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
384     int srcWasFinished, ECoderFinishMode finishMode,
385     // int *wasFinished,
386     ECoderStatus *status)
387 {
388   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
389   ELzmaStatus status2;
390   /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
391   SRes res;
392   UNUSED_VAR(srcWasFinished);
393   if (spec->outBufMode)
394   {
395     SizeT dicPos = spec->decoder.decoder.dicPos;
396     SizeT dicLimit = dicPos + *destLen;
397     res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
398     *destLen = spec->decoder.decoder.dicPos - dicPos;
399   }
400   else
401     res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
402   // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
403   // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
404   *status = (ECoderStatus)status2;
405   return res;
406 }
407 
408 
Lzma2State_SetFromMethod(IStateCoder * p,Byte * outBuf,size_t outBufSize,ISzAllocPtr alloc)409 static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
410 {
411   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
412   if (!spec)
413   {
414     spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
415     if (!spec)
416       return SZ_ERROR_MEM;
417     p->p = spec;
418     p->Free = Lzma2State_Free;
419     p->SetProps = Lzma2State_SetProps;
420     p->Init = Lzma2State_Init;
421     p->Code2 = Lzma2State_Code2;
422     p->Filter = NULL;
423     Lzma2Dec_Construct(&spec->decoder);
424   }
425   spec->outBufMode = False;
426   if (outBuf)
427   {
428     spec->outBufMode = True;
429     spec->decoder.decoder.dic = outBuf;
430     spec->decoder.decoder.dicBufSize = outBufSize;
431   }
432   return SZ_OK;
433 }
434 
435 
Lzma2State_ResetOutBuf(IStateCoder * p,Byte * outBuf,size_t outBufSize)436 static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
437 {
438   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
439   if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
440     return SZ_ERROR_FAIL;
441   if (outBuf)
442   {
443     spec->decoder.decoder.dic = outBuf;
444     spec->decoder.decoder.dicBufSize = outBufSize;
445   }
446   return SZ_OK;
447 }
448 
449 
450 
MixCoder_Construct(CMixCoder * p,ISzAllocPtr alloc)451 static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
452 {
453   unsigned i;
454   p->alloc = alloc;
455   p->buf = NULL;
456   p->numCoders = 0;
457 
458   p->outBufSize = 0;
459   p->outBuf = NULL;
460   // p->SingleBufMode = False;
461 
462   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
463     p->coders[i].p = NULL;
464 }
465 
466 
MixCoder_Free(CMixCoder * p)467 static void MixCoder_Free(CMixCoder *p)
468 {
469   unsigned i;
470   p->numCoders = 0;
471   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
472   {
473     IStateCoder *sc = &p->coders[i];
474     if (sc->p)
475     {
476       sc->Free(sc->p, p->alloc);
477       sc->p = NULL;
478     }
479   }
480   if (p->buf)
481   {
482     ISzAlloc_Free(p->alloc, p->buf);
483     p->buf = NULL; /* 9.31: the BUG was fixed */
484   }
485 }
486 
MixCoder_Init(CMixCoder * p)487 static void MixCoder_Init(CMixCoder *p)
488 {
489   unsigned i;
490   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
491   {
492     p->size[i] = 0;
493     p->pos[i] = 0;
494     p->finished[i] = 0;
495   }
496   for (i = 0; i < p->numCoders; i++)
497   {
498     IStateCoder *coder = &p->coders[i];
499     coder->Init(coder->p);
500     p->results[i] = SZ_OK;
501   }
502   p->outWritten = 0;
503   p->wasFinished = False;
504   p->res = SZ_OK;
505   p->status = CODER_STATUS_NOT_SPECIFIED;
506 }
507 
508 
MixCoder_SetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)509 static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
510 {
511   IStateCoder *sc = &p->coders[coderIndex];
512   p->ids[coderIndex] = methodId;
513   switch (methodId)
514   {
515     case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
516     #ifdef USE_SUBBLOCK
517     case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
518     #endif
519   }
520   if (coderIndex == 0)
521     return SZ_ERROR_UNSUPPORTED;
522   return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
523 }
524 
525 
MixCoder_ResetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)526 static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
527 {
528   IStateCoder *sc = &p->coders[coderIndex];
529   switch (methodId)
530   {
531     case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
532   }
533   return SZ_ERROR_UNSUPPORTED;
534 }
535 
536 
537 
538 /*
539  if (destFinish) - then unpack data block is finished at (*destLen) position,
540                    and we can return data that were not processed by filter
541 
542 output (status) can be :
543   CODER_STATUS_NOT_FINISHED
544   CODER_STATUS_FINISHED_WITH_MARK
545   CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
546 */
547 
MixCoder_Code(CMixCoder * p,Byte * dest,SizeT * destLen,int destFinish,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode)548 static SRes MixCoder_Code(CMixCoder *p,
549     Byte *dest, SizeT *destLen, int destFinish,
550     const Byte *src, SizeT *srcLen, int srcWasFinished,
551     ECoderFinishMode finishMode)
552 {
553   SizeT destLenOrig = *destLen;
554   SizeT srcLenOrig = *srcLen;
555 
556   *destLen = 0;
557   *srcLen = 0;
558 
559   if (p->wasFinished)
560     return p->res;
561 
562   p->status = CODER_STATUS_NOT_FINISHED;
563 
564   // if (p->SingleBufMode)
565   if (p->outBuf)
566   {
567     SRes res;
568     SizeT destLen2, srcLen2;
569     int wasFinished;
570 
571     PRF_STR("------- MixCoder Single ----------");
572 
573     srcLen2 = srcLenOrig;
574     destLen2 = destLenOrig;
575 
576     {
577       IStateCoder *coder = &p->coders[0];
578       res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
579           // &wasFinished,
580           &p->status);
581       wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
582     }
583 
584     p->res = res;
585 
586     /*
587     if (wasFinished)
588       p->status = CODER_STATUS_FINISHED_WITH_MARK;
589     else
590     {
591       if (res == SZ_OK)
592         if (destLen2 != destLenOrig)
593           p->status = CODER_STATUS_NEEDS_MORE_INPUT;
594     }
595     */
596 
597 
598     *srcLen = srcLen2;
599     src += srcLen2;
600     p->outWritten += destLen2;
601 
602     if (res != SZ_OK || srcWasFinished || wasFinished)
603       p->wasFinished = True;
604 
605     if (p->numCoders == 1)
606       *destLen = destLen2;
607     else if (p->wasFinished)
608     {
609       unsigned i;
610       size_t processed = p->outWritten;
611 
612       for (i = 1; i < p->numCoders; i++)
613       {
614         IStateCoder *coder = &p->coders[i];
615         processed = coder->Filter(coder->p, p->outBuf, processed);
616         if (wasFinished || (destFinish && p->outWritten == destLenOrig))
617           processed = p->outWritten;
618         PRF_STR_INT("filter", i);
619       }
620       *destLen = processed;
621     }
622     return res;
623   }
624 
625   PRF_STR("standard mix");
626 
627   if (p->numCoders != 1)
628   {
629     if (!p->buf)
630     {
631       p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
632       if (!p->buf)
633         return SZ_ERROR_MEM;
634     }
635 
636     finishMode = CODER_FINISH_ANY;
637   }
638 
639   for (;;)
640   {
641     BoolInt processed = False;
642     BoolInt allFinished = True;
643     SRes resMain = SZ_OK;
644     unsigned i;
645 
646     p->status = CODER_STATUS_NOT_FINISHED;
647     /*
648     if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
649       break;
650     */
651 
652     for (i = 0; i < p->numCoders; i++)
653     {
654       SRes res;
655       IStateCoder *coder = &p->coders[i];
656       Byte *dest2;
657       SizeT destLen2, srcLen2; // destLen2_Orig;
658       const Byte *src2;
659       int srcFinished2;
660       int encodingWasFinished;
661       ECoderStatus status2;
662 
663       if (i == 0)
664       {
665         src2 = src;
666         srcLen2 = srcLenOrig - *srcLen;
667         srcFinished2 = srcWasFinished;
668       }
669       else
670       {
671         size_t k = i - 1;
672         src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
673         srcLen2 = p->size[k] - p->pos[k];
674         srcFinished2 = p->finished[k];
675       }
676 
677       if (i == p->numCoders - 1)
678       {
679         dest2 = dest;
680         destLen2 = destLenOrig - *destLen;
681       }
682       else
683       {
684         if (p->pos[i] != p->size[i])
685           continue;
686         dest2 = p->buf + (CODER_BUF_SIZE * i);
687         destLen2 = CODER_BUF_SIZE;
688       }
689 
690       // destLen2_Orig = destLen2;
691 
692       if (p->results[i] != SZ_OK)
693       {
694         if (resMain == SZ_OK)
695           resMain = p->results[i];
696         continue;
697       }
698 
699       res = coder->Code2(coder->p,
700           dest2, &destLen2,
701           src2, &srcLen2, srcFinished2,
702           finishMode,
703           // &encodingWasFinished,
704           &status2);
705 
706       if (res != SZ_OK)
707       {
708         p->results[i] = res;
709         if (resMain == SZ_OK)
710           resMain = res;
711       }
712 
713       encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
714 
715       if (!encodingWasFinished)
716       {
717         allFinished = False;
718         if (p->numCoders == 1 && res == SZ_OK)
719           p->status = status2;
720       }
721 
722       if (i == 0)
723       {
724         *srcLen += srcLen2;
725         src += srcLen2;
726       }
727       else
728         p->pos[(size_t)i - 1] += srcLen2;
729 
730       if (i == p->numCoders - 1)
731       {
732         *destLen += destLen2;
733         dest += destLen2;
734       }
735       else
736       {
737         p->size[i] = destLen2;
738         p->pos[i] = 0;
739         p->finished[i] = encodingWasFinished;
740       }
741 
742       if (destLen2 != 0 || srcLen2 != 0)
743         processed = True;
744     }
745 
746     if (!processed)
747     {
748       if (allFinished)
749         p->status = CODER_STATUS_FINISHED_WITH_MARK;
750       return resMain;
751     }
752   }
753 }
754 
755 
Xz_ParseHeader(CXzStreamFlags * p,const Byte * buf)756 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
757 {
758   *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
759   if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
760       GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
761     return SZ_ERROR_NO_ARCHIVE;
762   return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
763 }
764 
Xz_CheckFooter(CXzStreamFlags flags,UInt64 indexSize,const Byte * buf)765 static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
766 {
767   return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
768       && GetUi32(buf) == CrcCalc(buf + 4, 6)
769       && flags == GetBe16(buf + 8)
770       && buf[10] == XZ_FOOTER_SIG_0
771       && buf[11] == XZ_FOOTER_SIG_1;
772 }
773 
774 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
775   { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
776   if (s == 0) return SZ_ERROR_ARCHIVE; \
777   pos += s; }
778 
779 
XzBlock_AreSupportedFilters(const CXzBlock * p)780 static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
781 {
782   unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
783   unsigned i;
784   {
785     const CXzFilter *f = &p->filters[numFilters];
786     if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
787       return False;
788   }
789 
790   for (i = 0; i < numFilters; i++)
791   {
792     const CXzFilter *f = &p->filters[i];
793     if (f->id == XZ_ID_Delta)
794     {
795       if (f->propsSize != 1)
796         return False;
797     }
798     else if (f->id < XZ_ID_Delta
799         || f->id > XZ_ID_SPARC
800         || (f->propsSize != 0 && f->propsSize != 4))
801       return False;
802   }
803   return True;
804 }
805 
806 
XzBlock_Parse(CXzBlock * p,const Byte * header)807 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
808 {
809   unsigned pos;
810   unsigned numFilters, i;
811   unsigned headerSize = (unsigned)header[0] << 2;
812 
813   /* (headerSize != 0) : another code checks */
814 
815   if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
816     return SZ_ERROR_ARCHIVE;
817 
818   pos = 1;
819   p->flags = header[pos++];
820 
821   p->packSize = (UInt64)(Int64)-1;
822   if (XzBlock_HasPackSize(p))
823   {
824     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
825     if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
826       return SZ_ERROR_ARCHIVE;
827   }
828 
829   p->unpackSize = (UInt64)(Int64)-1;
830   if (XzBlock_HasUnpackSize(p))
831     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
832 
833   numFilters = XzBlock_GetNumFilters(p);
834   for (i = 0; i < numFilters; i++)
835   {
836     CXzFilter *filter = p->filters + i;
837     UInt64 size;
838     READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
839     READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
840     if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
841       return SZ_ERROR_ARCHIVE;
842     filter->propsSize = (UInt32)size;
843     memcpy(filter->props, header + pos, (size_t)size);
844     pos += (unsigned)size;
845 
846     #ifdef XZ_DUMP
847     printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
848     {
849       unsigned i;
850       for (i = 0; i < size; i++)
851         printf(" %2X", filter->props[i]);
852     }
853     #endif
854   }
855 
856   if (XzBlock_HasUnsupportedFlags(p))
857     return SZ_ERROR_UNSUPPORTED;
858 
859   while (pos < headerSize)
860     if (header[pos++] != 0)
861       return SZ_ERROR_ARCHIVE;
862   return SZ_OK;
863 }
864 
865 
866 
867 
XzDecMix_Init(CMixCoder * p,const CXzBlock * block,Byte * outBuf,size_t outBufSize)868 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
869 {
870   unsigned i;
871   BoolInt needReInit = True;
872   unsigned numFilters = XzBlock_GetNumFilters(block);
873 
874   if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
875   {
876     needReInit = False;
877     for (i = 0; i < numFilters; i++)
878       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
879       {
880         needReInit = True;
881         break;
882       }
883   }
884 
885   // p->SingleBufMode = (outBuf != NULL);
886   p->outBuf = outBuf;
887   p->outBufSize = outBufSize;
888 
889   // p->SingleBufMode = False;
890   // outBuf = NULL;
891 
892   if (needReInit)
893   {
894     MixCoder_Free(p);
895     for (i = 0; i < numFilters; i++)
896     {
897       RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
898     }
899     p->numCoders = numFilters;
900   }
901   else
902   {
903     RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
904   }
905 
906   for (i = 0; i < numFilters; i++)
907   {
908     const CXzFilter *f = &block->filters[numFilters - 1 - i];
909     IStateCoder *sc = &p->coders[i];
910     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
911   }
912 
913   MixCoder_Init(p);
914   return SZ_OK;
915 }
916 
917 
918 
XzUnpacker_Init(CXzUnpacker * p)919 void XzUnpacker_Init(CXzUnpacker *p)
920 {
921   p->state = XZ_STATE_STREAM_HEADER;
922   p->pos = 0;
923   p->numStartedStreams = 0;
924   p->numFinishedStreams = 0;
925   p->numTotalBlocks = 0;
926   p->padSize = 0;
927   p->decodeOnlyOneBlock = 0;
928 
929   p->parseMode = False;
930   p->decodeToStreamSignature = False;
931 
932   // p->outBuf = NULL;
933   // p->outBufSize = 0;
934   p->outDataWritten = 0;
935 }
936 
937 
XzUnpacker_SetOutBuf(CXzUnpacker * p,Byte * outBuf,size_t outBufSize)938 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
939 {
940   p->outBuf = outBuf;
941   p->outBufSize = outBufSize;
942 }
943 
944 
XzUnpacker_Construct(CXzUnpacker * p,ISzAllocPtr alloc)945 void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
946 {
947   MixCoder_Construct(&p->decoder, alloc);
948   p->outBuf = NULL;
949   p->outBufSize = 0;
950   XzUnpacker_Init(p);
951 }
952 
953 
XzUnpacker_Free(CXzUnpacker * p)954 void XzUnpacker_Free(CXzUnpacker *p)
955 {
956   MixCoder_Free(&p->decoder);
957 }
958 
959 
XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker * p)960 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
961 {
962   p->indexSize = 0;
963   p->numBlocks = 0;
964   Sha256_Init(&p->sha);
965   p->state = XZ_STATE_BLOCK_HEADER;
966   p->pos = 0;
967   p->decodeOnlyOneBlock = 1;
968 }
969 
970 
XzUnpacker_UpdateIndex(CXzUnpacker * p,UInt64 packSize,UInt64 unpackSize)971 static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
972 {
973   Byte temp[32];
974   unsigned num = Xz_WriteVarInt(temp, packSize);
975   num += Xz_WriteVarInt(temp + num, unpackSize);
976   Sha256_Update(&p->sha, temp, num);
977   p->indexSize += num;
978   p->numBlocks++;
979 }
980 
981 
982 
XzUnpacker_Code(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcFinished,ECoderFinishMode finishMode,ECoderStatus * status)983 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
984     const Byte *src, SizeT *srcLen, int srcFinished,
985     ECoderFinishMode finishMode, ECoderStatus *status)
986 {
987   SizeT destLenOrig = *destLen;
988   SizeT srcLenOrig = *srcLen;
989   *destLen = 0;
990   *srcLen = 0;
991   *status = CODER_STATUS_NOT_SPECIFIED;
992 
993   for (;;)
994   {
995     SizeT srcRem;
996 
997     if (p->state == XZ_STATE_BLOCK)
998     {
999       SizeT destLen2 = destLenOrig - *destLen;
1000       SizeT srcLen2 = srcLenOrig - *srcLen;
1001       SRes res;
1002 
1003       ECoderFinishMode finishMode2 = finishMode;
1004       BoolInt srcFinished2 = srcFinished;
1005       BoolInt destFinish = False;
1006 
1007       if (p->block.packSize != (UInt64)(Int64)-1)
1008       {
1009         UInt64 rem = p->block.packSize - p->packSize;
1010         if (srcLen2 >= rem)
1011         {
1012           srcFinished2 = True;
1013           srcLen2 = (SizeT)rem;
1014         }
1015         if (rem == 0 && p->block.unpackSize == p->unpackSize)
1016           return SZ_ERROR_DATA;
1017       }
1018 
1019       if (p->block.unpackSize != (UInt64)(Int64)-1)
1020       {
1021         UInt64 rem = p->block.unpackSize - p->unpackSize;
1022         if (destLen2 >= rem)
1023         {
1024           destFinish = True;
1025           finishMode2 = CODER_FINISH_END;
1026           destLen2 = (SizeT)rem;
1027         }
1028       }
1029 
1030       /*
1031       if (srcLen2 == 0 && destLen2 == 0)
1032       {
1033         *status = CODER_STATUS_NOT_FINISHED;
1034         return SZ_OK;
1035       }
1036       */
1037 
1038       {
1039         res = MixCoder_Code(&p->decoder,
1040             (p->outBuf ? NULL : dest), &destLen2, destFinish,
1041             src, &srcLen2, srcFinished2,
1042             finishMode2);
1043 
1044         *status = p->decoder.status;
1045         XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1046         if (!p->outBuf)
1047           dest += destLen2;
1048         p->outDataWritten += destLen2;
1049       }
1050 
1051       (*srcLen) += srcLen2;
1052       src += srcLen2;
1053       p->packSize += srcLen2;
1054       (*destLen) += destLen2;
1055       p->unpackSize += destLen2;
1056 
1057       RINOK(res);
1058 
1059       if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1060       {
1061         if (p->block.packSize == p->packSize
1062             && *status == CODER_STATUS_NEEDS_MORE_INPUT)
1063         {
1064           PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
1065           *status = CODER_STATUS_NOT_SPECIFIED;
1066           return SZ_ERROR_DATA;
1067         }
1068 
1069         return SZ_OK;
1070       }
1071       {
1072         XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1073         p->state = XZ_STATE_BLOCK_FOOTER;
1074         p->pos = 0;
1075         p->alignPos = 0;
1076         *status = CODER_STATUS_NOT_SPECIFIED;
1077 
1078         if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1079            || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1080         {
1081           PRF_STR("ERROR: block.size mismatch");
1082           return SZ_ERROR_DATA;
1083         }
1084       }
1085       // continue;
1086     }
1087 
1088     srcRem = srcLenOrig - *srcLen;
1089 
1090     // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1091     if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1092     {
1093       *status = CODER_STATUS_NEEDS_MORE_INPUT;
1094       return SZ_OK;
1095     }
1096 
1097     switch (p->state)
1098     {
1099       case XZ_STATE_STREAM_HEADER:
1100       {
1101         if (p->pos < XZ_STREAM_HEADER_SIZE)
1102         {
1103           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1104             return SZ_ERROR_NO_ARCHIVE;
1105           if (p->decodeToStreamSignature)
1106             return SZ_OK;
1107           p->buf[p->pos++] = *src++;
1108           (*srcLen)++;
1109         }
1110         else
1111         {
1112           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
1113           p->numStartedStreams++;
1114           p->indexSize = 0;
1115           p->numBlocks = 0;
1116           Sha256_Init(&p->sha);
1117           p->state = XZ_STATE_BLOCK_HEADER;
1118           p->pos = 0;
1119         }
1120         break;
1121       }
1122 
1123       case XZ_STATE_BLOCK_HEADER:
1124       {
1125         if (p->pos == 0)
1126         {
1127           p->buf[p->pos++] = *src++;
1128           (*srcLen)++;
1129           if (p->buf[0] == 0)
1130           {
1131             if (p->decodeOnlyOneBlock)
1132               return SZ_ERROR_DATA;
1133             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1134             p->indexPos = p->indexPreSize;
1135             p->indexSize += p->indexPreSize;
1136             Sha256_Final(&p->sha, p->shaDigest);
1137             Sha256_Init(&p->sha);
1138             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1139             p->state = XZ_STATE_STREAM_INDEX;
1140             break;
1141           }
1142           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
1143           break;
1144         }
1145 
1146         if (p->pos != p->blockHeaderSize)
1147         {
1148           UInt32 cur = p->blockHeaderSize - p->pos;
1149           if (cur > srcRem)
1150             cur = (UInt32)srcRem;
1151           memcpy(p->buf + p->pos, src, cur);
1152           p->pos += cur;
1153           (*srcLen) += cur;
1154           src += cur;
1155         }
1156         else
1157         {
1158           RINOK(XzBlock_Parse(&p->block, p->buf));
1159           if (!XzBlock_AreSupportedFilters(&p->block))
1160             return SZ_ERROR_UNSUPPORTED;
1161           p->numTotalBlocks++;
1162           p->state = XZ_STATE_BLOCK;
1163           p->packSize = 0;
1164           p->unpackSize = 0;
1165           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1166           if (p->parseMode)
1167           {
1168             p->headerParsedOk = True;
1169             return SZ_OK;
1170           }
1171           RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
1172         }
1173         break;
1174       }
1175 
1176       case XZ_STATE_BLOCK_FOOTER:
1177       {
1178         if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1179         {
1180           if (srcRem == 0)
1181           {
1182             *status = CODER_STATUS_NEEDS_MORE_INPUT;
1183             return SZ_OK;
1184           }
1185           (*srcLen)++;
1186           p->alignPos++;
1187           if (*src++ != 0)
1188             return SZ_ERROR_CRC;
1189         }
1190         else
1191         {
1192           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
1193           UInt32 cur = checkSize - p->pos;
1194           if (cur != 0)
1195           {
1196             if (srcRem == 0)
1197             {
1198               *status = CODER_STATUS_NEEDS_MORE_INPUT;
1199               return SZ_OK;
1200             }
1201             if (cur > srcRem)
1202               cur = (UInt32)srcRem;
1203             memcpy(p->buf + p->pos, src, cur);
1204             p->pos += cur;
1205             (*srcLen) += cur;
1206             src += cur;
1207             if (checkSize != p->pos)
1208               break;
1209           }
1210           {
1211             Byte digest[XZ_CHECK_SIZE_MAX];
1212             p->state = XZ_STATE_BLOCK_HEADER;
1213             p->pos = 0;
1214             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1215               return SZ_ERROR_CRC;
1216             if (p->decodeOnlyOneBlock)
1217             {
1218               *status = CODER_STATUS_FINISHED_WITH_MARK;
1219               return SZ_OK;
1220             }
1221           }
1222         }
1223         break;
1224       }
1225 
1226       case XZ_STATE_STREAM_INDEX:
1227       {
1228         if (p->pos < p->indexPreSize)
1229         {
1230           (*srcLen)++;
1231           if (*src++ != p->buf[p->pos++])
1232             return SZ_ERROR_CRC;
1233         }
1234         else
1235         {
1236           if (p->indexPos < p->indexSize)
1237           {
1238             UInt64 cur = p->indexSize - p->indexPos;
1239             if (srcRem > cur)
1240               srcRem = (SizeT)cur;
1241             p->crc = CrcUpdate(p->crc, src, srcRem);
1242             Sha256_Update(&p->sha, src, srcRem);
1243             (*srcLen) += srcRem;
1244             src += srcRem;
1245             p->indexPos += srcRem;
1246           }
1247           else if ((p->indexPos & 3) != 0)
1248           {
1249             Byte b = *src++;
1250             p->crc = CRC_UPDATE_BYTE(p->crc, b);
1251             (*srcLen)++;
1252             p->indexPos++;
1253             p->indexSize++;
1254             if (b != 0)
1255               return SZ_ERROR_CRC;
1256           }
1257           else
1258           {
1259             Byte digest[SHA256_DIGEST_SIZE];
1260             p->state = XZ_STATE_STREAM_INDEX_CRC;
1261             p->indexSize += 4;
1262             p->pos = 0;
1263             Sha256_Final(&p->sha, digest);
1264             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1265               return SZ_ERROR_CRC;
1266           }
1267         }
1268         break;
1269       }
1270 
1271       case XZ_STATE_STREAM_INDEX_CRC:
1272       {
1273         if (p->pos < 4)
1274         {
1275           (*srcLen)++;
1276           p->buf[p->pos++] = *src++;
1277         }
1278         else
1279         {
1280           const Byte *ptr = p->buf;
1281           p->state = XZ_STATE_STREAM_FOOTER;
1282           p->pos = 0;
1283           if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr))
1284             return SZ_ERROR_CRC;
1285         }
1286         break;
1287       }
1288 
1289       case XZ_STATE_STREAM_FOOTER:
1290       {
1291         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1292         if (cur > srcRem)
1293           cur = (UInt32)srcRem;
1294         memcpy(p->buf + p->pos, src, cur);
1295         p->pos += cur;
1296         (*srcLen) += cur;
1297         src += cur;
1298         if (p->pos == XZ_STREAM_FOOTER_SIZE)
1299         {
1300           p->state = XZ_STATE_STREAM_PADDING;
1301           p->numFinishedStreams++;
1302           p->padSize = 0;
1303           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1304             return SZ_ERROR_CRC;
1305         }
1306         break;
1307       }
1308 
1309       case XZ_STATE_STREAM_PADDING:
1310       {
1311         if (*src != 0)
1312         {
1313           if (((UInt32)p->padSize & 3) != 0)
1314             return SZ_ERROR_NO_ARCHIVE;
1315           p->pos = 0;
1316           p->state = XZ_STATE_STREAM_HEADER;
1317         }
1318         else
1319         {
1320           (*srcLen)++;
1321           src++;
1322           p->padSize++;
1323         }
1324         break;
1325       }
1326 
1327       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1328     }
1329   }
1330   /*
1331   if (p->state == XZ_STATE_FINISHED)
1332     *status = CODER_STATUS_FINISHED_WITH_MARK;
1333   return SZ_OK;
1334   */
1335 }
1336 
1337 
XzUnpacker_CodeFull(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ECoderFinishMode finishMode,ECoderStatus * status)1338 SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1339     const Byte *src, SizeT *srcLen,
1340     ECoderFinishMode finishMode, ECoderStatus *status)
1341 {
1342   XzUnpacker_Init(p);
1343   XzUnpacker_SetOutBuf(p, dest, *destLen);
1344 
1345   return XzUnpacker_Code(p,
1346       NULL, destLen,
1347       src, srcLen, True,
1348       finishMode, status);
1349 }
1350 
1351 
XzUnpacker_IsBlockFinished(const CXzUnpacker * p)1352 BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1353 {
1354   return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1355 }
1356 
XzUnpacker_IsStreamWasFinished(const CXzUnpacker * p)1357 BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1358 {
1359   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1360 }
1361 
XzUnpacker_GetExtraSize(const CXzUnpacker * p)1362 UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1363 {
1364   UInt64 num = 0;
1365   if (p->state == XZ_STATE_STREAM_PADDING)
1366     num = p->padSize;
1367   else if (p->state == XZ_STATE_STREAM_HEADER)
1368     num = p->padSize + p->pos;
1369   return num;
1370 }
1371 
1372 
1373 
1374 
1375 
1376 
1377 
1378 
1379 
1380 
1381 
1382 
1383 
1384 
1385 
1386 
1387 
1388 
1389 
1390 
1391 
1392 #ifndef _7ZIP_ST
1393 #include "MtDec.h"
1394 #endif
1395 
1396 
XzDecMtProps_Init(CXzDecMtProps * p)1397 void XzDecMtProps_Init(CXzDecMtProps *p)
1398 {
1399   p->inBufSize_ST = 1 << 18;
1400   p->outStep_ST = 1 << 20;
1401   p->ignoreErrors = False;
1402 
1403   #ifndef _7ZIP_ST
1404   p->numThreads = 1;
1405   p->inBufSize_MT = 1 << 18;
1406   p->memUseMax = sizeof(size_t) << 28;
1407   #endif
1408 }
1409 
1410 
1411 
1412 #ifndef _7ZIP_ST
1413 
1414 /* ---------- CXzDecMtThread ---------- */
1415 
1416 typedef struct
1417 {
1418   Byte *outBuf;
1419   size_t outBufSize;
1420   size_t outPreSize;
1421   size_t inPreSize;
1422   size_t inPreHeaderSize;
1423   size_t blockPackSize_for_Index;  // including block header and checksum.
1424   size_t blockPackTotal;  // including stream header, block header and checksum.
1425   size_t inCodeSize;
1426   size_t outCodeSize;
1427   ECoderStatus status;
1428   SRes codeRes;
1429   BoolInt skipMode;
1430   // BoolInt finishedWithMark;
1431   EMtDecParseState parseState;
1432   BoolInt parsing_Truncated;
1433   BoolInt atBlockHeader;
1434   CXzStreamFlags streamFlags;
1435   // UInt64 numFinishedStreams
1436   UInt64 numStreams;
1437   UInt64 numTotalBlocks;
1438   UInt64 numBlocks;
1439 
1440   BoolInt dec_created;
1441   CXzUnpacker dec;
1442 
1443   Byte mtPad[1 << 7];
1444 } CXzDecMtThread;
1445 
1446 #endif
1447 
1448 
1449 /* ---------- CXzDecMt ---------- */
1450 
1451 typedef struct
1452 {
1453   CAlignOffsetAlloc alignOffsetAlloc;
1454   ISzAllocPtr allocMid;
1455 
1456   CXzDecMtProps props;
1457   size_t unpackBlockMaxSize;
1458 
1459   ISeqInStream *inStream;
1460   ISeqOutStream *outStream;
1461   ICompressProgress *progress;
1462 
1463   BoolInt finishMode;
1464   BoolInt outSize_Defined;
1465   UInt64 outSize;
1466 
1467   UInt64 outProcessed;
1468   UInt64 inProcessed;
1469   UInt64 readProcessed;
1470   BoolInt readWasFinished;
1471   SRes readRes;
1472   SRes writeRes;
1473 
1474   Byte *outBuf;
1475   size_t outBufSize;
1476   Byte *inBuf;
1477   size_t inBufSize;
1478 
1479   CXzUnpacker dec;
1480 
1481   ECoderStatus status;
1482   SRes codeRes;
1483 
1484   #ifndef _7ZIP_ST
1485   BoolInt mainDecoderWasCalled;
1486   // int statErrorDefined;
1487   int finishedDecoderIndex;
1488 
1489   // global values that are used in Parse stage
1490   CXzStreamFlags streamFlags;
1491   // UInt64 numFinishedStreams
1492   UInt64 numStreams;
1493   UInt64 numTotalBlocks;
1494   UInt64 numBlocks;
1495 
1496   // UInt64 numBadBlocks;
1497   SRes mainErrorCode;  // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage
1498                        // it can be = SZ_ERROR_INPUT_EOF
1499                        // it can be = SZ_ERROR_DATA, in some another cases
1500   BoolInt isBlockHeaderState_Parse;
1501   BoolInt isBlockHeaderState_Write;
1502   UInt64 outProcessed_Parse;
1503   BoolInt parsing_Truncated;
1504 
1505   BoolInt mtc_WasConstructed;
1506   CMtDec mtc;
1507   CXzDecMtThread coders[MTDEC__THREADS_MAX];
1508   #endif
1509 
1510 } CXzDecMt;
1511 
1512 
1513 
XzDecMt_Create(ISzAllocPtr alloc,ISzAllocPtr allocMid)1514 CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1515 {
1516   CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1517   if (!p)
1518     return NULL;
1519 
1520   AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1521   p->alignOffsetAlloc.baseAlloc = alloc;
1522   p->alignOffsetAlloc.numAlignBits = 7;
1523   p->alignOffsetAlloc.offset = 0;
1524 
1525   p->allocMid = allocMid;
1526 
1527   p->outBuf = NULL;
1528   p->outBufSize = 0;
1529   p->inBuf = NULL;
1530   p->inBufSize = 0;
1531 
1532   XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1533 
1534   p->unpackBlockMaxSize = 0;
1535 
1536   XzDecMtProps_Init(&p->props);
1537 
1538   #ifndef _7ZIP_ST
1539   p->mtc_WasConstructed = False;
1540   {
1541     unsigned i;
1542     for (i = 0; i < MTDEC__THREADS_MAX; i++)
1543     {
1544       CXzDecMtThread *coder = &p->coders[i];
1545       coder->dec_created = False;
1546       coder->outBuf = NULL;
1547       coder->outBufSize = 0;
1548     }
1549   }
1550   #endif
1551 
1552   return p;
1553 }
1554 
1555 
1556 #ifndef _7ZIP_ST
1557 
XzDecMt_FreeOutBufs(CXzDecMt * p)1558 static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1559 {
1560   unsigned i;
1561   for (i = 0; i < MTDEC__THREADS_MAX; i++)
1562   {
1563     CXzDecMtThread *coder = &p->coders[i];
1564     if (coder->outBuf)
1565     {
1566       ISzAlloc_Free(p->allocMid, coder->outBuf);
1567       coder->outBuf = NULL;
1568       coder->outBufSize = 0;
1569     }
1570   }
1571   p->unpackBlockMaxSize = 0;
1572 }
1573 
1574 #endif
1575 
1576 
1577 
XzDecMt_FreeSt(CXzDecMt * p)1578 static void XzDecMt_FreeSt(CXzDecMt *p)
1579 {
1580   XzUnpacker_Free(&p->dec);
1581 
1582   if (p->outBuf)
1583   {
1584     ISzAlloc_Free(p->allocMid, p->outBuf);
1585     p->outBuf = NULL;
1586   }
1587   p->outBufSize = 0;
1588 
1589   if (p->inBuf)
1590   {
1591     ISzAlloc_Free(p->allocMid, p->inBuf);
1592     p->inBuf = NULL;
1593   }
1594   p->inBufSize = 0;
1595 }
1596 
1597 
XzDecMt_Destroy(CXzDecMtHandle pp)1598 void XzDecMt_Destroy(CXzDecMtHandle pp)
1599 {
1600   CXzDecMt *p = (CXzDecMt *)pp;
1601 
1602   XzDecMt_FreeSt(p);
1603 
1604   #ifndef _7ZIP_ST
1605 
1606   if (p->mtc_WasConstructed)
1607   {
1608     MtDec_Destruct(&p->mtc);
1609     p->mtc_WasConstructed = False;
1610   }
1611   {
1612     unsigned i;
1613     for (i = 0; i < MTDEC__THREADS_MAX; i++)
1614     {
1615       CXzDecMtThread *t = &p->coders[i];
1616       if (t->dec_created)
1617       {
1618         // we don't need to free dict here
1619         XzUnpacker_Free(&t->dec);
1620         t->dec_created = False;
1621       }
1622     }
1623   }
1624   XzDecMt_FreeOutBufs(p);
1625 
1626   #endif
1627 
1628   ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1629 }
1630 
1631 
1632 
1633 #ifndef _7ZIP_ST
1634 
XzDecMt_Callback_Parse(void * obj,unsigned coderIndex,CMtDecCallbackInfo * cc)1635 static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1636 {
1637   CXzDecMt *me = (CXzDecMt *)obj;
1638   CXzDecMtThread *coder = &me->coders[coderIndex];
1639   size_t srcSize = cc->srcSize;
1640 
1641   cc->srcSize = 0;
1642   cc->outPos = 0;
1643   cc->state = MTDEC_PARSE_CONTINUE;
1644 
1645   cc->canCreateNewThread = True;
1646 
1647   if (cc->startCall)
1648   {
1649     coder->outPreSize = 0;
1650     coder->inPreSize = 0;
1651     coder->inPreHeaderSize = 0;
1652     coder->parseState = MTDEC_PARSE_CONTINUE;
1653     coder->parsing_Truncated = False;
1654     coder->skipMode = False;
1655     coder->codeRes = SZ_OK;
1656     coder->status = CODER_STATUS_NOT_SPECIFIED;
1657     coder->inCodeSize = 0;
1658     coder->outCodeSize = 0;
1659 
1660     coder->numStreams = me->numStreams;
1661     coder->numTotalBlocks = me->numTotalBlocks;
1662     coder->numBlocks = me->numBlocks;
1663 
1664     if (!coder->dec_created)
1665     {
1666       XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1667       coder->dec_created = True;
1668     }
1669 
1670     XzUnpacker_Init(&coder->dec);
1671 
1672     if (me->isBlockHeaderState_Parse)
1673     {
1674       coder->dec.streamFlags = me->streamFlags;
1675       coder->atBlockHeader = True;
1676       XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1677     }
1678     else
1679     {
1680       coder->atBlockHeader = False;
1681       me->isBlockHeaderState_Parse = True;
1682     }
1683 
1684     coder->dec.numStartedStreams = me->numStreams;
1685     coder->dec.numTotalBlocks = me->numTotalBlocks;
1686     coder->dec.numBlocks = me->numBlocks;
1687   }
1688 
1689   while (!coder->skipMode)
1690   {
1691     ECoderStatus status;
1692     SRes res;
1693     size_t srcSize2 = srcSize;
1694     size_t destSize = (size_t)0 - 1;
1695 
1696     coder->dec.parseMode = True;
1697     coder->dec.headerParsedOk = False;
1698 
1699     PRF_STR_INT("Parse", srcSize2);
1700 
1701     res = XzUnpacker_Code(&coder->dec,
1702         NULL, &destSize,
1703         cc->src, &srcSize2, cc->srcFinished,
1704         CODER_FINISH_END, &status);
1705 
1706     // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1707 
1708     coder->codeRes = res;
1709     coder->status = status;
1710     cc->srcSize += srcSize2;
1711     srcSize -= srcSize2;
1712     coder->inPreHeaderSize += srcSize2;
1713     coder->inPreSize = coder->inPreHeaderSize;
1714 
1715     if (res != SZ_OK)
1716     {
1717       cc->state =
1718       coder->parseState = MTDEC_PARSE_END;
1719       /*
1720       if (res == SZ_ERROR_MEM)
1721         return res;
1722       return SZ_OK;
1723       */
1724       return; // res;
1725     }
1726 
1727     if (coder->dec.headerParsedOk)
1728     {
1729       const CXzBlock *block = &coder->dec.block;
1730       if (XzBlock_HasUnpackSize(block)
1731           // && block->unpackSize <= me->props.outBlockMax
1732           && XzBlock_HasPackSize(block))
1733       {
1734         {
1735           if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1736           {
1737             cc->state = MTDEC_PARSE_OVERFLOW;
1738             return; // SZ_OK;
1739           }
1740         }
1741         {
1742         UInt64 packSize = block->packSize;
1743         UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1744         UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1745         UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1746         // if (blockPackSum <= me->props.inBlockMax)
1747         // unpackBlockMaxSize
1748         {
1749           coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1750           coder->blockPackTotal = (size_t)blockPackSum;
1751           coder->outPreSize = (size_t)block->unpackSize;
1752           coder->streamFlags = coder->dec.streamFlags;
1753           me->streamFlags = coder->dec.streamFlags;
1754           coder->skipMode = True;
1755           break;
1756         }
1757         }
1758       }
1759     }
1760     else
1761     // if (coder->inPreSize <= me->props.inBlockMax)
1762     {
1763       if (!cc->srcFinished)
1764         return; // SZ_OK;
1765       cc->state =
1766       coder->parseState = MTDEC_PARSE_END;
1767       return; // SZ_OK;
1768     }
1769     cc->state = MTDEC_PARSE_OVERFLOW;
1770     return; // SZ_OK;
1771   }
1772 
1773   // ---------- skipMode ----------
1774   {
1775     UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1776     size_t cur = srcSize;
1777     if (cur > rem)
1778       cur = (size_t)rem;
1779     cc->srcSize += cur;
1780     coder->inPreSize += cur;
1781     srcSize -= cur;
1782 
1783     if (coder->inPreSize == coder->blockPackTotal)
1784     {
1785       if (srcSize == 0)
1786       {
1787         if (!cc->srcFinished)
1788           return; // SZ_OK;
1789         cc->state = MTDEC_PARSE_END;
1790       }
1791       else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1792         cc->state = MTDEC_PARSE_END;
1793       else
1794       {
1795         cc->state = MTDEC_PARSE_NEW;
1796 
1797         {
1798           size_t blockMax = me->unpackBlockMaxSize;
1799           if (blockMax < coder->outPreSize)
1800             blockMax = coder->outPreSize;
1801           {
1802             UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1803             if (me->props.memUseMax < required)
1804               cc->canCreateNewThread = False;
1805           }
1806         }
1807 
1808         if (me->outSize_Defined)
1809         {
1810           // next block can be zero size
1811           const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1812           if (rem2 < coder->outPreSize)
1813           {
1814             coder->parsing_Truncated = True;
1815             cc->state = MTDEC_PARSE_END;
1816           }
1817           me->outProcessed_Parse += coder->outPreSize;
1818         }
1819       }
1820     }
1821     else if (cc->srcFinished)
1822       cc->state = MTDEC_PARSE_END;
1823     else
1824       return; // SZ_OK;
1825 
1826     coder->parseState = cc->state;
1827     cc->outPos = coder->outPreSize;
1828 
1829     me->numStreams = coder->dec.numStartedStreams;
1830     me->numTotalBlocks = coder->dec.numTotalBlocks;
1831     me->numBlocks = coder->dec.numBlocks + 1;
1832     return; // SZ_OK;
1833   }
1834 }
1835 
1836 
XzDecMt_Callback_PreCode(void * pp,unsigned coderIndex)1837 static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1838 {
1839   CXzDecMt *me = (CXzDecMt *)pp;
1840   CXzDecMtThread *coder = &me->coders[coderIndex];
1841   Byte *dest;
1842 
1843   if (!coder->dec.headerParsedOk)
1844     return SZ_OK;
1845 
1846   dest = coder->outBuf;
1847 
1848   if (!dest || coder->outBufSize < coder->outPreSize)
1849   {
1850     if (dest)
1851     {
1852       ISzAlloc_Free(me->allocMid, dest);
1853       coder->outBuf = NULL;
1854       coder->outBufSize = 0;
1855     }
1856     {
1857       size_t outPreSize = coder->outPreSize;
1858       if (outPreSize == 0)
1859         outPreSize = 1;
1860       dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1861     }
1862     if (!dest)
1863       return SZ_ERROR_MEM;
1864     coder->outBuf = dest;
1865     coder->outBufSize = coder->outPreSize;
1866 
1867     if (coder->outBufSize > me->unpackBlockMaxSize)
1868       me->unpackBlockMaxSize = coder->outBufSize;
1869   }
1870 
1871   // return SZ_ERROR_MEM;
1872 
1873   XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1874 
1875   {
1876     SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1877     // res = SZ_ERROR_UNSUPPORTED; // to test
1878     coder->codeRes = res;
1879     if (res != SZ_OK)
1880     {
1881       // if (res == SZ_ERROR_MEM) return res;
1882       if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1883         return SZ_OK;
1884       return res;
1885     }
1886   }
1887 
1888   return SZ_OK;
1889 }
1890 
1891 
XzDecMt_Callback_Code(void * pp,unsigned coderIndex,const Byte * src,size_t srcSize,int srcFinished,UInt64 * inCodePos,UInt64 * outCodePos,int * stop)1892 static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1893     const Byte *src, size_t srcSize, int srcFinished,
1894     // int finished, int blockFinished,
1895     UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1896 {
1897   CXzDecMt *me = (CXzDecMt *)pp;
1898   CXzDecMtThread *coder = &me->coders[coderIndex];
1899 
1900   *inCodePos = coder->inCodeSize;
1901   *outCodePos = coder->outCodeSize;
1902   *stop = True;
1903 
1904   if (srcSize > coder->inPreSize - coder->inCodeSize)
1905     return SZ_ERROR_FAIL;
1906 
1907   if (coder->inCodeSize < coder->inPreHeaderSize)
1908   {
1909     size_t step = coder->inPreHeaderSize - coder->inCodeSize;
1910     if (step > srcSize)
1911       step = srcSize;
1912     src += step;
1913     srcSize -= step;
1914     coder->inCodeSize += step;
1915     *inCodePos = coder->inCodeSize;
1916     if (coder->inCodeSize < coder->inPreHeaderSize)
1917     {
1918       *stop = False;
1919       return SZ_OK;
1920     }
1921   }
1922 
1923   if (!coder->dec.headerParsedOk)
1924     return SZ_OK;
1925   if (!coder->outBuf)
1926     return SZ_OK;
1927 
1928   if (coder->codeRes == SZ_OK)
1929   {
1930     ECoderStatus status;
1931     SRes res;
1932     size_t srcProcessed = srcSize;
1933     size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1934 
1935     // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1936 
1937     res = XzUnpacker_Code(&coder->dec,
1938         NULL, &outSizeCur,
1939         src, &srcProcessed, srcFinished,
1940         // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1941         CODER_FINISH_END,
1942         &status);
1943 
1944     // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1945 
1946     coder->codeRes = res;
1947     coder->status = status;
1948     coder->inCodeSize += srcProcessed;
1949     coder->outCodeSize = coder->dec.outDataWritten;
1950     *inCodePos = coder->inCodeSize;
1951     *outCodePos = coder->outCodeSize;
1952 
1953     if (res == SZ_OK)
1954     {
1955       if (srcProcessed == srcSize)
1956         *stop = False;
1957       return SZ_OK;
1958     }
1959   }
1960 
1961   if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1962   {
1963     *inCodePos = coder->inPreSize;
1964     *outCodePos = coder->outPreSize;
1965     return SZ_OK;
1966   }
1967   return coder->codeRes;
1968 }
1969 
1970 
1971 #define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1972 
XzDecMt_Callback_Write(void * pp,unsigned coderIndex,BoolInt needWriteToStream,const Byte * src,size_t srcSize,BoolInt isCross,BoolInt * needContinue,BoolInt * canRecode)1973 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1974     BoolInt needWriteToStream,
1975     const Byte *src, size_t srcSize, BoolInt isCross,
1976     // int srcFinished,
1977     BoolInt *needContinue,
1978     BoolInt *canRecode)
1979 {
1980   CXzDecMt *me = (CXzDecMt *)pp;
1981   const CXzDecMtThread *coder = &me->coders[coderIndex];
1982 
1983   // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1984 
1985   *needContinue = False;
1986   *canRecode = True;
1987 
1988   if (!needWriteToStream)
1989     return SZ_OK;
1990 
1991   if (!coder->dec.headerParsedOk || !coder->outBuf)
1992   {
1993     if (me->finishedDecoderIndex < 0)
1994       me->finishedDecoderIndex = (int)coderIndex;
1995     return SZ_OK;
1996   }
1997 
1998   if (me->finishedDecoderIndex >= 0)
1999     return SZ_OK;
2000 
2001   me->mtc.inProcessed += coder->inCodeSize;
2002 
2003   *canRecode = False;
2004 
2005   {
2006     SRes res;
2007     size_t size = coder->outCodeSize;
2008     Byte *data = coder->outBuf;
2009 
2010     // we use in me->dec: sha, numBlocks, indexSize
2011 
2012     if (!me->isBlockHeaderState_Write)
2013     {
2014       XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2015       me->dec.decodeOnlyOneBlock = False;
2016       me->dec.numStartedStreams = coder->dec.numStartedStreams;
2017       me->dec.streamFlags = coder->streamFlags;
2018 
2019       me->isBlockHeaderState_Write = True;
2020     }
2021 
2022     me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2023     XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2024 
2025     if (coder->outPreSize != size)
2026     {
2027       if (me->props.ignoreErrors)
2028       {
2029         memset(data + size, 0, coder->outPreSize - size);
2030         size = coder->outPreSize;
2031       }
2032       // me->numBadBlocks++;
2033       if (me->mainErrorCode == SZ_OK)
2034       {
2035         if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2036           me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2037         else
2038           me->mainErrorCode = SZ_ERROR_DATA;
2039       }
2040     }
2041 
2042     if (me->writeRes != SZ_OK)
2043       return me->writeRes;
2044 
2045     res = SZ_OK;
2046     {
2047       if (me->outSize_Defined)
2048       {
2049         const UInt64 rem = me->outSize - me->outProcessed;
2050         if (size > rem)
2051           size = (SizeT)rem;
2052       }
2053 
2054       for (;;)
2055       {
2056         size_t cur = size;
2057         size_t written;
2058         if (cur > XZDECMT_STREAM_WRITE_STEP)
2059           cur = XZDECMT_STREAM_WRITE_STEP;
2060 
2061         written = ISeqOutStream_Write(me->outStream, data, cur);
2062 
2063         // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2064 
2065         me->outProcessed += written;
2066         if (written != cur)
2067         {
2068           me->writeRes = SZ_ERROR_WRITE;
2069           res = me->writeRes;
2070           break;
2071         }
2072         data += cur;
2073         size -= cur;
2074         // PRF_STR_INT("Written size =", size);
2075         if (size == 0)
2076           break;
2077         res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2078         if (res != SZ_OK)
2079           break;
2080       }
2081     }
2082 
2083     if (coder->codeRes != SZ_OK)
2084       if (!me->props.ignoreErrors)
2085       {
2086         me->finishedDecoderIndex = (int)coderIndex;
2087         return res;
2088       }
2089 
2090     RINOK(res);
2091 
2092     if (coder->inPreSize != coder->inCodeSize
2093         || coder->blockPackTotal != coder->inCodeSize)
2094     {
2095       me->finishedDecoderIndex = (int)coderIndex;
2096       return SZ_OK;
2097     }
2098 
2099     if (coder->parseState != MTDEC_PARSE_END)
2100     {
2101       *needContinue = True;
2102       return SZ_OK;
2103     }
2104   }
2105 
2106   // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2107   // so we can use mtc variables without lock
2108 
2109   PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2110 
2111   me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2112   {
2113     CXzUnpacker *dec = &me->dec;
2114 
2115     PRF_STR_INT("PostSingle", srcSize);
2116 
2117     {
2118       size_t srcProcessed = srcSize;
2119       ECoderStatus status;
2120       size_t outSizeCur = 0;
2121       SRes res;
2122 
2123       // dec->decodeOnlyOneBlock = False;
2124       dec->decodeToStreamSignature = True;
2125 
2126       me->mainDecoderWasCalled = True;
2127 
2128       if (coder->parsing_Truncated)
2129       {
2130         me->parsing_Truncated = True;
2131         return SZ_OK;
2132       }
2133 
2134       /*
2135       We have processed all xz-blocks of stream,
2136       And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where
2137       (src) is a pointer to xz-Index structure.
2138       We finish reading of current xz-Stream, including Zero padding after xz-Stream.
2139       We exit, if we reach extra byte (first byte of new-Stream or another data).
2140       But we don't update input stream pointer for that new extra byte.
2141       If extra byte is not correct first byte of xz-signature,
2142       we have SZ_ERROR_NO_ARCHIVE error here.
2143       */
2144 
2145       res = XzUnpacker_Code(dec,
2146           NULL, &outSizeCur,
2147           src, &srcProcessed,
2148           me->mtc.readWasFinished, // srcFinished
2149           CODER_FINISH_END, // CODER_FINISH_ANY,
2150           &status);
2151 
2152       // res = SZ_ERROR_ARCHIVE; // for failure test
2153 
2154       me->status = status;
2155       me->codeRes = res;
2156 
2157       if (isCross)
2158         me->mtc.crossStart += srcProcessed;
2159 
2160       me->mtc.inProcessed += srcProcessed;
2161       me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2162 
2163       srcSize -= srcProcessed;
2164       src += srcProcessed;
2165 
2166       if (res != SZ_OK)
2167       {
2168         return SZ_OK;
2169         // return res;
2170       }
2171 
2172       if (dec->state == XZ_STATE_STREAM_HEADER)
2173       {
2174         *needContinue = True;
2175         me->isBlockHeaderState_Parse = False;
2176         me->isBlockHeaderState_Write = False;
2177 
2178         if (!isCross)
2179         {
2180           Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2181           if (!crossBuf)
2182             return SZ_ERROR_MEM;
2183           if (srcSize != 0)
2184             memcpy(crossBuf, src, srcSize);
2185           me->mtc.crossStart = 0;
2186           me->mtc.crossEnd = srcSize;
2187         }
2188 
2189         PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd);
2190 
2191         return SZ_OK;
2192       }
2193 
2194       if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0)
2195       {
2196         return SZ_ERROR_FAIL;
2197       }
2198 
2199       if (me->mtc.readWasFinished)
2200       {
2201         return SZ_OK;
2202       }
2203     }
2204 
2205     {
2206       size_t inPos;
2207       size_t inLim;
2208       // const Byte *inData;
2209       UInt64 inProgressPrev = me->mtc.inProcessed;
2210 
2211       // XzDecMt_Prepare_InBuf_ST(p);
2212       Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2213       if (!crossBuf)
2214         return SZ_ERROR_MEM;
2215 
2216       inPos = 0;
2217       inLim = 0;
2218 
2219       // inData = crossBuf;
2220 
2221       for (;;)
2222       {
2223         SizeT inProcessed;
2224         SizeT outProcessed;
2225         ECoderStatus status;
2226         SRes res;
2227 
2228         if (inPos == inLim)
2229         {
2230           if (!me->mtc.readWasFinished)
2231           {
2232             inPos = 0;
2233             inLim = me->mtc.inBufSize;
2234             me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim);
2235             me->mtc.readProcessed += inLim;
2236             if (inLim == 0 || me->mtc.readRes != SZ_OK)
2237               me->mtc.readWasFinished = True;
2238           }
2239         }
2240 
2241         inProcessed = inLim - inPos;
2242         outProcessed = 0;
2243 
2244         res = XzUnpacker_Code(dec,
2245             NULL, &outProcessed,
2246             crossBuf + inPos, &inProcessed,
2247             (inProcessed == 0), // srcFinished
2248             CODER_FINISH_END, &status);
2249 
2250         me->codeRes = res;
2251         me->status = status;
2252         inPos += inProcessed;
2253         me->mtc.inProcessed += inProcessed;
2254         me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2255 
2256         if (res != SZ_OK)
2257         {
2258           return SZ_OK;
2259           // return res;
2260         }
2261 
2262         if (dec->state == XZ_STATE_STREAM_HEADER)
2263         {
2264           *needContinue = True;
2265           me->mtc.crossStart = inPos;
2266           me->mtc.crossEnd = inLim;
2267           me->isBlockHeaderState_Parse = False;
2268           me->isBlockHeaderState_Write = False;
2269           return SZ_OK;
2270         }
2271 
2272         if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2273           return SZ_ERROR_FAIL;
2274 
2275         if (me->mtc.progress)
2276         {
2277           UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2278           if (inDelta >= (1 << 22))
2279           {
2280             RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2281             inProgressPrev = me->mtc.inProcessed;
2282           }
2283         }
2284         if (me->mtc.readWasFinished)
2285           return SZ_OK;
2286       }
2287     }
2288   }
2289 }
2290 
2291 
2292 #endif
2293 
2294 
2295 
XzStatInfo_Clear(CXzStatInfo * p)2296 void XzStatInfo_Clear(CXzStatInfo *p)
2297 {
2298   p->InSize = 0;
2299   p->OutSize = 0;
2300 
2301   p->NumStreams = 0;
2302   p->NumBlocks = 0;
2303 
2304   p->UnpackSize_Defined = False;
2305 
2306   p->NumStreams_Defined = False;
2307   p->NumBlocks_Defined = False;
2308 
2309   p->DataAfterEnd = False;
2310   p->DecodingTruncated = False;
2311 
2312   p->DecodeRes = SZ_OK;
2313   p->ReadRes = SZ_OK;
2314   p->ProgressRes = SZ_OK;
2315 
2316   p->CombinedRes = SZ_OK;
2317   p->CombinedRes_Type = SZ_OK;
2318 }
2319 
2320 
2321 
2322 /*
2323   XzDecMt_Decode_ST() can return SZ_OK or the following errors
2324      - SZ_ERROR_MEM for memory allocation error
2325      - error from XzUnpacker_Code() function
2326      - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case
2327      - ICompressProgress::Progress() error,  stat->CombinedRes_Type = SZ_ERROR_PROGRESS.
2328   But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors.
2329   ISeqInStream::Read() result is set to p->readRes.
2330   also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
2331 */
2332 
XzDecMt_Decode_ST(CXzDecMt * p,BoolInt tMode,CXzStatInfo * stat)2333 static SRes XzDecMt_Decode_ST(CXzDecMt *p
2334     #ifndef _7ZIP_ST
2335     , BoolInt tMode
2336     #endif
2337     , CXzStatInfo *stat)
2338 {
2339   size_t outPos;
2340   size_t inPos, inLim;
2341   const Byte *inData;
2342   UInt64 inPrev, outPrev;
2343 
2344   CXzUnpacker *dec;
2345 
2346   #ifndef _7ZIP_ST
2347   if (tMode)
2348   {
2349     XzDecMt_FreeOutBufs(p);
2350     tMode = MtDec_PrepareRead(&p->mtc);
2351   }
2352   #endif
2353 
2354   if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2355   {
2356     ISzAlloc_Free(p->allocMid, p->outBuf);
2357     p->outBufSize = 0;
2358     p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2359     if (!p->outBuf)
2360       return SZ_ERROR_MEM;
2361     p->outBufSize = p->props.outStep_ST;
2362   }
2363 
2364   if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2365   {
2366     ISzAlloc_Free(p->allocMid, p->inBuf);
2367     p->inBufSize = 0;
2368     p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2369     if (!p->inBuf)
2370       return SZ_ERROR_MEM;
2371     p->inBufSize = p->props.inBufSize_ST;
2372   }
2373 
2374   dec = &p->dec;
2375   dec->decodeToStreamSignature = False;
2376   // dec->decodeOnlyOneBlock = False;
2377 
2378   XzUnpacker_SetOutBuf(dec, NULL, 0);
2379 
2380   inPrev = p->inProcessed;
2381   outPrev = p->outProcessed;
2382 
2383   inPos = 0;
2384   inLim = 0;
2385   inData = NULL;
2386   outPos = 0;
2387 
2388   for (;;)
2389   {
2390     SizeT outSize;
2391     BoolInt finished;
2392     ECoderFinishMode finishMode;
2393     SizeT inProcessed;
2394     ECoderStatus status;
2395     SRes res;
2396 
2397     SizeT outProcessed;
2398 
2399 
2400 
2401     if (inPos == inLim)
2402     {
2403       #ifndef _7ZIP_ST
2404       if (tMode)
2405       {
2406         inData = MtDec_Read(&p->mtc, &inLim);
2407         inPos = 0;
2408         if (inData)
2409           continue;
2410         tMode = False;
2411         inLim = 0;
2412       }
2413       #endif
2414 
2415       if (!p->readWasFinished)
2416       {
2417         inPos = 0;
2418         inLim = p->inBufSize;
2419         inData = p->inBuf;
2420         p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim);
2421         p->readProcessed += inLim;
2422         if (inLim == 0 || p->readRes != SZ_OK)
2423           p->readWasFinished = True;
2424       }
2425     }
2426 
2427     outSize = p->props.outStep_ST - outPos;
2428 
2429     finishMode = CODER_FINISH_ANY;
2430     if (p->outSize_Defined)
2431     {
2432       const UInt64 rem = p->outSize - p->outProcessed;
2433       if (outSize >= rem)
2434       {
2435         outSize = (SizeT)rem;
2436         if (p->finishMode)
2437           finishMode = CODER_FINISH_END;
2438       }
2439     }
2440 
2441     inProcessed = inLim - inPos;
2442     outProcessed = outSize;
2443 
2444     res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2445         inData + inPos, &inProcessed,
2446         (inPos == inLim), // srcFinished
2447         finishMode, &status);
2448 
2449     p->codeRes = res;
2450     p->status = status;
2451 
2452     inPos += inProcessed;
2453     outPos += outProcessed;
2454     p->inProcessed += inProcessed;
2455     p->outProcessed += outProcessed;
2456 
2457     finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2458 
2459     if (finished || outProcessed >= outSize)
2460       if (outPos != 0)
2461       {
2462         const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2463         // p->outProcessed += written; // 21.01: BUG fixed
2464         if (written != outPos)
2465         {
2466           stat->CombinedRes_Type = SZ_ERROR_WRITE;
2467           return SZ_ERROR_WRITE;
2468         }
2469         outPos = 0;
2470       }
2471 
2472     if (p->progress && res == SZ_OK)
2473     {
2474       if (p->inProcessed - inPrev >= (1 << 22) ||
2475           p->outProcessed - outPrev >= (1 << 22))
2476       {
2477         res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2478         if (res != SZ_OK)
2479         {
2480           stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2481           stat->ProgressRes = res;
2482           return res;
2483         }
2484         inPrev = p->inProcessed;
2485         outPrev = p->outProcessed;
2486       }
2487     }
2488 
2489     if (finished)
2490     {
2491       // p->codeRes is preliminary error from XzUnpacker_Code.
2492       // and it can be corrected later as final result
2493       // so we return SZ_OK here instead of (res);
2494       return SZ_OK;
2495       // return res;
2496     }
2497   }
2498 }
2499 
2500 
2501 
2502 /*
2503 XzStatInfo_SetStat() transforms
2504     CXzUnpacker return code and status to combined CXzStatInfo results.
2505     it can convert SZ_OK to SZ_ERROR_INPUT_EOF
2506     it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1)
2507 */
2508 
XzStatInfo_SetStat(const CXzUnpacker * dec,int finishMode,UInt64 inProcessed,SRes res,ECoderStatus status,BoolInt decodingTruncated,CXzStatInfo * stat)2509 static void XzStatInfo_SetStat(const CXzUnpacker *dec,
2510     int finishMode,
2511     // UInt64 readProcessed,
2512     UInt64 inProcessed,
2513     SRes res,                     // it's result from CXzUnpacker unpacker
2514     ECoderStatus status,
2515     BoolInt decodingTruncated,
2516     CXzStatInfo *stat)
2517 {
2518   UInt64 extraSize;
2519 
2520   stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2521   stat->InSize = inProcessed;
2522   stat->NumStreams = dec->numStartedStreams;
2523   stat->NumBlocks = dec->numTotalBlocks;
2524 
2525   stat->UnpackSize_Defined = True;
2526   stat->NumStreams_Defined = True;
2527   stat->NumBlocks_Defined = True;
2528 
2529   extraSize = XzUnpacker_GetExtraSize(dec);
2530 
2531   if (res == SZ_OK)
2532   {
2533     if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2534     {
2535       // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2536       // any extra data is part of correct data
2537       extraSize = 0;
2538       // if xz stream was not finished, then we need more data
2539       if (!XzUnpacker_IsStreamWasFinished(dec))
2540         res = SZ_ERROR_INPUT_EOF;
2541     }
2542     else
2543     {
2544       // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding
2545       // so he we have (status == CODER_STATUS_NOT_FINISHED)
2546       // if (status != CODER_STATUS_FINISHED_WITH_MARK)
2547       if (!decodingTruncated || finishMode)
2548         res = SZ_ERROR_DATA;
2549     }
2550   }
2551   else if (res == SZ_ERROR_NO_ARCHIVE)
2552   {
2553     /*
2554     SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2555       XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC
2556       XZ_STATE_STREAM_PADDING - if non-zero padding data
2557     extraSize and inProcessed don't include "bad" byte
2558     */
2559     // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error
2560     if (inProcessed != extraSize) // if there were good xz streams before error
2561     {
2562       // if (extraSize != 0 || readProcessed != inProcessed)
2563       {
2564         // he we suppose that all xz streams were finsihed OK, and we have
2565         // some extra data after all streams
2566         stat->DataAfterEnd = True;
2567         res = SZ_OK;
2568       }
2569     }
2570   }
2571 
2572   if (stat->DecodeRes == SZ_OK)
2573     stat->DecodeRes = res;
2574 
2575   stat->InSize -= extraSize;
2576 }
2577 
2578 
2579 
XzDecMt_Decode(CXzDecMtHandle pp,const CXzDecMtProps * props,const UInt64 * outDataSize,int finishMode,ISeqOutStream * outStream,ISeqInStream * inStream,CXzStatInfo * stat,int * isMT,ICompressProgress * progress)2580 SRes XzDecMt_Decode(CXzDecMtHandle pp,
2581     const CXzDecMtProps *props,
2582     const UInt64 *outDataSize, int finishMode,
2583     ISeqOutStream *outStream,
2584     // Byte *outBuf, size_t *outBufSize,
2585     ISeqInStream *inStream,
2586     // const Byte *inData, size_t inDataSize,
2587     CXzStatInfo *stat,
2588     int *isMT,
2589     ICompressProgress *progress)
2590 {
2591   CXzDecMt *p = (CXzDecMt *)pp;
2592   #ifndef _7ZIP_ST
2593   BoolInt tMode;
2594   #endif
2595 
2596   XzStatInfo_Clear(stat);
2597 
2598   p->props = *props;
2599 
2600   p->inStream = inStream;
2601   p->outStream = outStream;
2602   p->progress = progress;
2603   // p->stat = stat;
2604 
2605   p->outSize = 0;
2606   p->outSize_Defined = False;
2607   if (outDataSize)
2608   {
2609     p->outSize_Defined = True;
2610     p->outSize = *outDataSize;
2611   }
2612 
2613   p->finishMode = finishMode;
2614 
2615   // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2616 
2617   p->writeRes = SZ_OK;
2618   p->outProcessed = 0;
2619   p->inProcessed = 0;
2620   p->readProcessed = 0;
2621   p->readWasFinished = False;
2622   p->readRes = SZ_OK;
2623 
2624   p->codeRes = SZ_OK;
2625   p->status = CODER_STATUS_NOT_SPECIFIED;
2626 
2627   XzUnpacker_Init(&p->dec);
2628 
2629   *isMT = False;
2630 
2631     /*
2632     p->outBuf = NULL;
2633     p->outBufSize = 0;
2634     if (!outStream)
2635     {
2636       p->outBuf = outBuf;
2637       p->outBufSize = *outBufSize;
2638       *outBufSize = 0;
2639     }
2640     */
2641 
2642 
2643   #ifndef _7ZIP_ST
2644 
2645   p->isBlockHeaderState_Parse = False;
2646   p->isBlockHeaderState_Write = False;
2647   // p->numBadBlocks = 0;
2648   p->mainErrorCode = SZ_OK;
2649   p->mainDecoderWasCalled = False;
2650 
2651   tMode = False;
2652 
2653   if (p->props.numThreads > 1)
2654   {
2655     IMtDecCallback2 vt;
2656     BoolInt needContinue;
2657     SRes res;
2658     // we just free ST buffers here
2659     // but we still keep state variables, that was set in XzUnpacker_Init()
2660     XzDecMt_FreeSt(p);
2661 
2662     p->outProcessed_Parse = 0;
2663     p->parsing_Truncated = False;
2664 
2665     p->numStreams = 0;
2666     p->numTotalBlocks = 0;
2667     p->numBlocks = 0;
2668     p->finishedDecoderIndex = -1;
2669 
2670     if (!p->mtc_WasConstructed)
2671     {
2672       p->mtc_WasConstructed = True;
2673       MtDec_Construct(&p->mtc);
2674     }
2675 
2676     p->mtc.mtCallback = &vt;
2677     p->mtc.mtCallbackObject = p;
2678 
2679     p->mtc.progress = progress;
2680     p->mtc.inStream = inStream;
2681     p->mtc.alloc = &p->alignOffsetAlloc.vt;
2682     // p->mtc.inData = inData;
2683     // p->mtc.inDataSize = inDataSize;
2684     p->mtc.inBufSize = p->props.inBufSize_MT;
2685     // p->mtc.inBlockMax = p->props.inBlockMax;
2686     p->mtc.numThreadsMax = p->props.numThreads;
2687 
2688     *isMT = True;
2689 
2690     vt.Parse = XzDecMt_Callback_Parse;
2691     vt.PreCode = XzDecMt_Callback_PreCode;
2692     vt.Code = XzDecMt_Callback_Code;
2693     vt.Write = XzDecMt_Callback_Write;
2694 
2695 
2696     res = MtDec_Code(&p->mtc);
2697 
2698 
2699     stat->InSize = p->mtc.inProcessed;
2700 
2701     p->inProcessed = p->mtc.inProcessed;
2702     p->readRes = p->mtc.readRes;
2703     p->readWasFinished = p->mtc.readWasFinished;
2704     p->readProcessed = p->mtc.readProcessed;
2705 
2706     tMode = True;
2707     needContinue = False;
2708 
2709     if (res == SZ_OK)
2710     {
2711       if (p->mtc.mtProgress.res != SZ_OK)
2712       {
2713         res = p->mtc.mtProgress.res;
2714         stat->ProgressRes = res;
2715         stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2716       }
2717       else
2718         needContinue = p->mtc.needContinue;
2719     }
2720 
2721     if (!needContinue)
2722     {
2723       {
2724         SRes codeRes;
2725         BoolInt truncated = False;
2726         ECoderStatus status;
2727         const CXzUnpacker *dec;
2728 
2729         stat->OutSize = p->outProcessed;
2730 
2731         if (p->finishedDecoderIndex >= 0)
2732         {
2733           const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2734           codeRes = coder->codeRes;
2735           dec = &coder->dec;
2736           status = coder->status;
2737         }
2738         else if (p->mainDecoderWasCalled)
2739         {
2740           codeRes = p->codeRes;
2741           dec = &p->dec;
2742           status = p->status;
2743           truncated = p->parsing_Truncated;
2744         }
2745         else
2746           return SZ_ERROR_FAIL;
2747 
2748         if (p->mainErrorCode != SZ_OK)
2749           stat->DecodeRes = p->mainErrorCode;
2750 
2751         XzStatInfo_SetStat(dec, p->finishMode,
2752             // p->mtc.readProcessed,
2753             p->mtc.inProcessed,
2754             codeRes, status,
2755             truncated,
2756             stat);
2757       }
2758 
2759       if (res == SZ_OK)
2760       {
2761         stat->ReadRes = p->mtc.readRes;
2762 
2763         if (p->writeRes != SZ_OK)
2764         {
2765           res = p->writeRes;
2766           stat->CombinedRes_Type = SZ_ERROR_WRITE;
2767         }
2768         else if (p->mtc.readRes != SZ_OK
2769             // && p->mtc.inProcessed == p->mtc.readProcessed
2770             && stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2771         {
2772           res = p->mtc.readRes;
2773           stat->CombinedRes_Type = SZ_ERROR_READ;
2774         }
2775         else if (stat->DecodeRes != SZ_OK)
2776           res = stat->DecodeRes;
2777       }
2778 
2779       stat->CombinedRes = res;
2780       if (stat->CombinedRes_Type == SZ_OK)
2781         stat->CombinedRes_Type = res;
2782       return res;
2783     }
2784 
2785     PRF_STR("----- decoding ST -----");
2786   }
2787 
2788   #endif
2789 
2790 
2791   *isMT = False;
2792 
2793   {
2794     SRes res = XzDecMt_Decode_ST(p
2795         #ifndef _7ZIP_ST
2796         , tMode
2797         #endif
2798         , stat
2799         );
2800 
2801     #ifndef _7ZIP_ST
2802     // we must set error code from MT decoding at first
2803     if (p->mainErrorCode != SZ_OK)
2804       stat->DecodeRes = p->mainErrorCode;
2805     #endif
2806 
2807     XzStatInfo_SetStat(&p->dec,
2808         p->finishMode,
2809         // p->readProcessed,
2810         p->inProcessed,
2811         p->codeRes, p->status,
2812         False, // truncated
2813         stat);
2814 
2815     stat->ReadRes = p->readRes;
2816 
2817     if (res == SZ_OK)
2818     {
2819       if (p->readRes != SZ_OK
2820           // && p->inProcessed == p->readProcessed
2821           && stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2822       {
2823         // we set read error as combined error, only if that error was the reason
2824         // of decoding problem
2825         res = p->readRes;
2826         stat->CombinedRes_Type = SZ_ERROR_READ;
2827       }
2828       else if (stat->DecodeRes != SZ_OK)
2829         res = stat->DecodeRes;
2830     }
2831 
2832     stat->CombinedRes = res;
2833     if (stat->CombinedRes_Type == SZ_OK)
2834       stat->CombinedRes_Type = res;
2835     return res;
2836   }
2837 }
2838