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