1 /* XzDec.c -- Xz Decode
2 2018-04-24 : 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 
BraState_SetFromMethod(IStateCoder * p,UInt64 id,int encodeMode,ISzAllocPtr alloc)243 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
244 {
245   CBraState *decoder;
246   if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
247     return SZ_ERROR_UNSUPPORTED;
248   decoder = p->p;
249   if (!decoder)
250   {
251     decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
252     if (!decoder)
253       return SZ_ERROR_MEM;
254     p->p = decoder;
255     p->Free = BraState_Free;
256     p->SetProps = BraState_SetProps;
257     p->Init = BraState_Init;
258     p->Code2 = BraState_Code2;
259     p->Filter = BraState_Filter;
260   }
261   decoder->methodId = (UInt32)id;
262   decoder->encodeMode = encodeMode;
263   return SZ_OK;
264 }
265 
266 
267 
268 /* ---------- SbState ---------- */
269 
270 #ifdef USE_SUBBLOCK
271 
SbState_Free(void * pp,ISzAllocPtr alloc)272 static void SbState_Free(void *pp, ISzAllocPtr alloc)
273 {
274   CSbDec *p = (CSbDec *)pp;
275   SbDec_Free(p);
276   ISzAlloc_Free(alloc, pp);
277 }
278 
SbState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)279 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
280 {
281   UNUSED_VAR(pp);
282   UNUSED_VAR(props);
283   UNUSED_VAR(alloc);
284   return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
285 }
286 
SbState_Init(void * pp)287 static void SbState_Init(void *pp)
288 {
289   SbDec_Init((CSbDec *)pp);
290 }
291 
SbState_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)292 static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
293     int srcWasFinished, ECoderFinishMode finishMode,
294     // int *wasFinished
295     ECoderStatus *status)
296 {
297   CSbDec *p = (CSbDec *)pp;
298   SRes res;
299   UNUSED_VAR(srcWasFinished);
300   p->dest = dest;
301   p->destLen = *destLen;
302   p->src = src;
303   p->srcLen = *srcLen;
304   p->finish = finishMode; /* change it */
305   res = SbDec_Decode((CSbDec *)pp);
306   *destLen -= p->destLen;
307   *srcLen -= p->srcLen;
308   // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
309   *status = (*destLen == 0 && *srcLen == 0) ?
310       CODER_STATUS_FINISHED_WITH_MARK :
311       CODER_STATUS_NOT_FINISHED;
312   return res;
313 }
314 
SbState_SetFromMethod(IStateCoder * p,ISzAllocPtr alloc)315 static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
316 {
317   CSbDec *decoder = (CSbDec *)p->p;
318   if (!decoder)
319   {
320     decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
321     if (!decoder)
322       return SZ_ERROR_MEM;
323     p->p = decoder;
324     p->Free = SbState_Free;
325     p->SetProps = SbState_SetProps;
326     p->Init = SbState_Init;
327     p->Code2 = SbState_Code2;
328     p->Filter = NULL;
329   }
330   SbDec_Construct(decoder);
331   SbDec_SetAlloc(decoder, alloc);
332   return SZ_OK;
333 }
334 
335 #endif
336 
337 
338 
339 /* ---------- Lzma2 ---------- */
340 
341 typedef struct
342 {
343   CLzma2Dec decoder;
344   Bool outBufMode;
345 } CLzma2Dec_Spec;
346 
347 
Lzma2State_Free(void * pp,ISzAllocPtr alloc)348 static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
349 {
350   CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
351   if (p->outBufMode)
352     Lzma2Dec_FreeProbs(&p->decoder, alloc);
353   else
354     Lzma2Dec_Free(&p->decoder, alloc);
355   ISzAlloc_Free(alloc, pp);
356 }
357 
Lzma2State_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)358 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
359 {
360   if (propSize != 1)
361     return SZ_ERROR_UNSUPPORTED;
362   {
363     CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
364     if (p->outBufMode)
365       return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
366     else
367       return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
368   }
369 }
370 
Lzma2State_Init(void * pp)371 static void Lzma2State_Init(void *pp)
372 {
373   Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
374 }
375 
376 
377 /*
378   if (outBufMode), then (dest) is not used. Use NULL.
379          Data is unpacked to (spec->decoder.decoder.dic) output buffer.
380 */
381 
Lzma2State_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)382 static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
383     int srcWasFinished, ECoderFinishMode finishMode,
384     // int *wasFinished,
385     ECoderStatus *status)
386 {
387   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
388   ELzmaStatus status2;
389   /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
390   SRes res;
391   UNUSED_VAR(srcWasFinished);
392   if (spec->outBufMode)
393   {
394     SizeT dicPos = spec->decoder.decoder.dicPos;
395     SizeT dicLimit = dicPos + *destLen;
396     res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
397     *destLen = spec->decoder.decoder.dicPos - dicPos;
398   }
399   else
400     res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
401   // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
402   // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
403   *status = status2;
404   return res;
405 }
406 
407 
Lzma2State_SetFromMethod(IStateCoder * p,Byte * outBuf,size_t outBufSize,ISzAllocPtr alloc)408 static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
409 {
410   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
411   if (!spec)
412   {
413     spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
414     if (!spec)
415       return SZ_ERROR_MEM;
416     p->p = spec;
417     p->Free = Lzma2State_Free;
418     p->SetProps = Lzma2State_SetProps;
419     p->Init = Lzma2State_Init;
420     p->Code2 = Lzma2State_Code2;
421     p->Filter = NULL;
422     Lzma2Dec_Construct(&spec->decoder);
423   }
424   spec->outBufMode = False;
425   if (outBuf)
426   {
427     spec->outBufMode = True;
428     spec->decoder.decoder.dic = outBuf;
429     spec->decoder.decoder.dicBufSize = outBufSize;
430   }
431   return SZ_OK;
432 }
433 
434 
Lzma2State_ResetOutBuf(IStateCoder * p,Byte * outBuf,size_t outBufSize)435 static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
436 {
437   CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
438   if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
439     return SZ_ERROR_FAIL;
440   if (outBuf)
441   {
442     spec->decoder.decoder.dic = outBuf;
443     spec->decoder.decoder.dicBufSize = outBufSize;
444   }
445   return SZ_OK;
446 }
447 
448 
449 
MixCoder_Construct(CMixCoder * p,ISzAllocPtr alloc)450 static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
451 {
452   unsigned i;
453   p->alloc = alloc;
454   p->buf = NULL;
455   p->numCoders = 0;
456 
457   p->outBufSize = 0;
458   p->outBuf = NULL;
459   // p->SingleBufMode = False;
460 
461   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
462     p->coders[i].p = NULL;
463 }
464 
465 
MixCoder_Free(CMixCoder * p)466 static void MixCoder_Free(CMixCoder *p)
467 {
468   unsigned i;
469   p->numCoders = 0;
470   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
471   {
472     IStateCoder *sc = &p->coders[i];
473     if (sc->p)
474     {
475       sc->Free(sc->p, p->alloc);
476       sc->p = NULL;
477     }
478   }
479   if (p->buf)
480   {
481     ISzAlloc_Free(p->alloc, p->buf);
482     p->buf = NULL; /* 9.31: the BUG was fixed */
483   }
484 }
485 
MixCoder_Init(CMixCoder * p)486 static void MixCoder_Init(CMixCoder *p)
487 {
488   unsigned i;
489   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
490   {
491     p->size[i] = 0;
492     p->pos[i] = 0;
493     p->finished[i] = 0;
494   }
495   for (i = 0; i < p->numCoders; i++)
496   {
497     IStateCoder *coder = &p->coders[i];
498     coder->Init(coder->p);
499     p->results[i] = SZ_OK;
500   }
501   p->outWritten = 0;
502   p->wasFinished = False;
503   p->res = SZ_OK;
504   p->status = CODER_STATUS_NOT_SPECIFIED;
505 }
506 
507 
MixCoder_SetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)508 static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
509 {
510   IStateCoder *sc = &p->coders[coderIndex];
511   p->ids[coderIndex] = methodId;
512   switch (methodId)
513   {
514     case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
515     #ifdef USE_SUBBLOCK
516     case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
517     #endif
518   }
519   if (coderIndex == 0)
520     return SZ_ERROR_UNSUPPORTED;
521   return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
522 }
523 
524 
MixCoder_ResetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)525 static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
526 {
527   IStateCoder *sc = &p->coders[coderIndex];
528   switch (methodId)
529   {
530     case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
531   }
532   return SZ_ERROR_UNSUPPORTED;
533 }
534 
535 
536 
537 /*
538  if (destFinish) - then unpack data block is finished at (*destLen) position,
539                    and we can return data that were not processed by filter
540 
541 output (status) can be :
542   CODER_STATUS_NOT_FINISHED
543   CODER_STATUS_FINISHED_WITH_MARK
544   CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
545 */
546 
MixCoder_Code(CMixCoder * p,Byte * dest,SizeT * destLen,int destFinish,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode)547 static SRes MixCoder_Code(CMixCoder *p,
548     Byte *dest, SizeT *destLen, int destFinish,
549     const Byte *src, SizeT *srcLen, int srcWasFinished,
550     ECoderFinishMode finishMode)
551 {
552   SizeT destLenOrig = *destLen;
553   SizeT srcLenOrig = *srcLen;
554 
555   *destLen = 0;
556   *srcLen = 0;
557 
558   if (p->wasFinished)
559     return p->res;
560 
561   p->status = CODER_STATUS_NOT_FINISHED;
562 
563   // if (p->SingleBufMode)
564   if (p->outBuf)
565   {
566     SRes res;
567     SizeT destLen2, srcLen2;
568     int wasFinished;
569 
570     PRF_STR("------- MixCoder Single ----------");
571 
572     srcLen2 = srcLenOrig;
573     destLen2 = destLenOrig;
574 
575     {
576       IStateCoder *coder = &p->coders[0];
577       res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
578           // &wasFinished,
579           &p->status);
580       wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
581     }
582 
583     p->res = res;
584 
585     /*
586     if (wasFinished)
587       p->status = CODER_STATUS_FINISHED_WITH_MARK;
588     else
589     {
590       if (res == SZ_OK)
591         if (destLen2 != destLenOrig)
592           p->status = CODER_STATUS_NEEDS_MORE_INPUT;
593     }
594     */
595 
596 
597     *srcLen = srcLen2;
598     src += srcLen2;
599     p->outWritten += destLen2;
600 
601     if (res != SZ_OK || srcWasFinished || wasFinished)
602       p->wasFinished = True;
603 
604     if (p->numCoders == 1)
605       *destLen = destLen2;
606     else if (p->wasFinished)
607     {
608       unsigned i;
609       size_t processed = p->outWritten;
610 
611       for (i = 1; i < p->numCoders; i++)
612       {
613         IStateCoder *coder = &p->coders[i];
614         processed = coder->Filter(coder->p, p->outBuf, processed);
615         if (wasFinished || (destFinish && p->outWritten == destLenOrig))
616           processed = p->outWritten;
617         PRF_STR_INT("filter", i);
618       }
619       *destLen = processed;
620     }
621     return res;
622   }
623 
624   PRF_STR("standard mix");
625 
626   if (p->numCoders != 1)
627   {
628     if (!p->buf)
629     {
630       p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
631       if (!p->buf)
632         return SZ_ERROR_MEM;
633     }
634 
635     finishMode = CODER_FINISH_ANY;
636   }
637 
638   for (;;)
639   {
640     Bool processed = False;
641     Bool allFinished = True;
642     SRes resMain = SZ_OK;
643     unsigned i;
644 
645     p->status = CODER_STATUS_NOT_FINISHED;
646     /*
647     if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
648       break;
649     */
650 
651     for (i = 0; i < p->numCoders; i++)
652     {
653       SRes res;
654       IStateCoder *coder = &p->coders[i];
655       Byte *dest2;
656       SizeT destLen2, srcLen2; // destLen2_Orig;
657       const Byte *src2;
658       int srcFinished2;
659       int encodingWasFinished;
660       ECoderStatus status2;
661 
662       if (i == 0)
663       {
664         src2 = src;
665         srcLen2 = srcLenOrig - *srcLen;
666         srcFinished2 = srcWasFinished;
667       }
668       else
669       {
670         size_t k = i - 1;
671         src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
672         srcLen2 = p->size[k] - p->pos[k];
673         srcFinished2 = p->finished[k];
674       }
675 
676       if (i == p->numCoders - 1)
677       {
678         dest2 = dest;
679         destLen2 = destLenOrig - *destLen;
680       }
681       else
682       {
683         if (p->pos[i] != p->size[i])
684           continue;
685         dest2 = p->buf + (CODER_BUF_SIZE * i);
686         destLen2 = CODER_BUF_SIZE;
687       }
688 
689       // destLen2_Orig = destLen2;
690 
691       if (p->results[i] != SZ_OK)
692       {
693         if (resMain == SZ_OK)
694           resMain = p->results[i];
695         continue;
696       }
697 
698       res = coder->Code2(coder->p,
699           dest2, &destLen2,
700           src2, &srcLen2, srcFinished2,
701           finishMode,
702           // &encodingWasFinished,
703           &status2);
704 
705       if (res != SZ_OK)
706       {
707         p->results[i] = res;
708         if (resMain == SZ_OK)
709           resMain = res;
710       }
711 
712       encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
713 
714       if (!encodingWasFinished)
715       {
716         allFinished = False;
717         if (p->numCoders == 1 && res == SZ_OK)
718           p->status = status2;
719       }
720 
721       if (i == 0)
722       {
723         *srcLen += srcLen2;
724         src += srcLen2;
725       }
726       else
727         p->pos[(size_t)i - 1] += srcLen2;
728 
729       if (i == p->numCoders - 1)
730       {
731         *destLen += destLen2;
732         dest += destLen2;
733       }
734       else
735       {
736         p->size[i] = destLen2;
737         p->pos[i] = 0;
738         p->finished[i] = encodingWasFinished;
739       }
740 
741       if (destLen2 != 0 || srcLen2 != 0)
742         processed = True;
743     }
744 
745     if (!processed)
746     {
747       if (allFinished)
748         p->status = CODER_STATUS_FINISHED_WITH_MARK;
749       return resMain;
750     }
751   }
752 }
753 
754 
Xz_ParseHeader(CXzStreamFlags * p,const Byte * buf)755 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
756 {
757   *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
758   if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
759       GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
760     return SZ_ERROR_NO_ARCHIVE;
761   return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
762 }
763 
Xz_CheckFooter(CXzStreamFlags flags,UInt64 indexSize,const Byte * buf)764 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
765 {
766   return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
767       && GetUi32(buf) == CrcCalc(buf + 4, 6)
768       && flags == GetBe16(buf + 8)
769       && buf[10] == XZ_FOOTER_SIG_0
770       && buf[11] == XZ_FOOTER_SIG_1;
771 }
772 
773 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
774   { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
775   if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
776 
777 
XzBlock_AreSupportedFilters(const CXzBlock * p)778 static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)
779 {
780   unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
781   unsigned i;
782   {
783     const CXzFilter *f = &p->filters[numFilters];
784     if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
785       return False;
786   }
787 
788   for (i = 0; i < numFilters; i++)
789   {
790     const CXzFilter *f = &p->filters[i];
791     if (f->id == XZ_ID_Delta)
792     {
793       if (f->propsSize != 1)
794         return False;
795     }
796     else if (f->id < XZ_ID_Delta
797         || f->id > XZ_ID_SPARC
798         || (f->propsSize != 0 && f->propsSize != 4))
799       return False;
800   }
801   return True;
802 }
803 
804 
XzBlock_Parse(CXzBlock * p,const Byte * header)805 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
806 {
807   unsigned pos;
808   unsigned numFilters, i;
809   unsigned headerSize = (unsigned)header[0] << 2;
810 
811   /* (headerSize != 0) : another code checks */
812 
813   if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
814     return SZ_ERROR_ARCHIVE;
815 
816   pos = 1;
817   p->flags = header[pos++];
818 
819   p->packSize = (UInt64)(Int64)-1;
820   if (XzBlock_HasPackSize(p))
821   {
822     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
823     if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
824       return SZ_ERROR_ARCHIVE;
825   }
826 
827   p->unpackSize = (UInt64)(Int64)-1;
828   if (XzBlock_HasUnpackSize(p))
829     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
830 
831   numFilters = XzBlock_GetNumFilters(p);
832   for (i = 0; i < numFilters; i++)
833   {
834     CXzFilter *filter = p->filters + i;
835     UInt64 size;
836     READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
837     READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
838     if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
839       return SZ_ERROR_ARCHIVE;
840     filter->propsSize = (UInt32)size;
841     memcpy(filter->props, header + pos, (size_t)size);
842     pos += (unsigned)size;
843 
844     #ifdef XZ_DUMP
845     printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
846     {
847       unsigned i;
848       for (i = 0; i < size; i++)
849         printf(" %2X", filter->props[i]);
850     }
851     #endif
852   }
853 
854   if (XzBlock_HasUnsupportedFlags(p))
855     return SZ_ERROR_UNSUPPORTED;
856 
857   while (pos < headerSize)
858     if (header[pos++] != 0)
859       return SZ_ERROR_ARCHIVE;
860   return SZ_OK;
861 }
862 
863 
864 
865 
XzDecMix_Init(CMixCoder * p,const CXzBlock * block,Byte * outBuf,size_t outBufSize)866 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
867 {
868   unsigned i;
869   Bool needReInit = True;
870   unsigned numFilters = XzBlock_GetNumFilters(block);
871 
872   if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
873   {
874     needReInit = False;
875     for (i = 0; i < numFilters; i++)
876       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
877       {
878         needReInit = True;
879         break;
880       }
881   }
882 
883   // p->SingleBufMode = (outBuf != NULL);
884   p->outBuf = outBuf;
885   p->outBufSize = outBufSize;
886 
887   // p->SingleBufMode = False;
888   // outBuf = NULL;
889 
890   if (needReInit)
891   {
892     MixCoder_Free(p);
893     for (i = 0; i < numFilters; i++)
894     {
895       RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
896     }
897     p->numCoders = numFilters;
898   }
899   else
900   {
901     RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
902   }
903 
904   for (i = 0; i < numFilters; i++)
905   {
906     const CXzFilter *f = &block->filters[numFilters - 1 - i];
907     IStateCoder *sc = &p->coders[i];
908     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
909   }
910 
911   MixCoder_Init(p);
912   return SZ_OK;
913 }
914 
915 
916 
XzUnpacker_Init(CXzUnpacker * p)917 void XzUnpacker_Init(CXzUnpacker *p)
918 {
919   p->state = XZ_STATE_STREAM_HEADER;
920   p->pos = 0;
921   p->numStartedStreams = 0;
922   p->numFinishedStreams = 0;
923   p->numTotalBlocks = 0;
924   p->padSize = 0;
925   p->decodeOnlyOneBlock = 0;
926 
927   p->parseMode = False;
928   p->decodeToStreamSignature = False;
929 
930   // p->outBuf = NULL;
931   // p->outBufSize = 0;
932   p->outDataWritten = 0;
933 }
934 
935 
XzUnpacker_SetOutBuf(CXzUnpacker * p,Byte * outBuf,size_t outBufSize)936 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
937 {
938   p->outBuf = outBuf;
939   p->outBufSize = outBufSize;
940 }
941 
942 
XzUnpacker_Construct(CXzUnpacker * p,ISzAllocPtr alloc)943 void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
944 {
945   MixCoder_Construct(&p->decoder, alloc);
946   p->outBuf = NULL;
947   p->outBufSize = 0;
948   XzUnpacker_Init(p);
949 }
950 
951 
XzUnpacker_Free(CXzUnpacker * p)952 void XzUnpacker_Free(CXzUnpacker *p)
953 {
954   MixCoder_Free(&p->decoder);
955 }
956 
957 
XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker * p)958 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
959 {
960   p->indexSize = 0;
961   p->numBlocks = 0;
962   Sha256_Init(&p->sha);
963   p->state = XZ_STATE_BLOCK_HEADER;
964   p->pos = 0;
965   p->decodeOnlyOneBlock = 1;
966 }
967 
968 
XzUnpacker_UpdateIndex(CXzUnpacker * p,UInt64 packSize,UInt64 unpackSize)969 static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
970 {
971   Byte temp[32];
972   unsigned num = Xz_WriteVarInt(temp, packSize);
973   num += Xz_WriteVarInt(temp + num, unpackSize);
974   Sha256_Update(&p->sha, temp, num);
975   p->indexSize += num;
976   p->numBlocks++;
977 }
978 
979 
980 
XzUnpacker_Code(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcFinished,ECoderFinishMode finishMode,ECoderStatus * status)981 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
982     const Byte *src, SizeT *srcLen, int srcFinished,
983     ECoderFinishMode finishMode, ECoderStatus *status)
984 {
985   SizeT destLenOrig = *destLen;
986   SizeT srcLenOrig = *srcLen;
987   *destLen = 0;
988   *srcLen = 0;
989   *status = CODER_STATUS_NOT_SPECIFIED;
990 
991   for (;;)
992   {
993     SizeT srcRem;
994 
995     if (p->state == XZ_STATE_BLOCK)
996     {
997       SizeT destLen2 = destLenOrig - *destLen;
998       SizeT srcLen2 = srcLenOrig - *srcLen;
999       SRes res;
1000 
1001       ECoderFinishMode finishMode2 = finishMode;
1002       Bool srcFinished2 = srcFinished;
1003       Bool destFinish = False;
1004 
1005       if (p->block.packSize != (UInt64)(Int64)-1)
1006       {
1007         UInt64 rem = p->block.packSize - p->packSize;
1008         if (srcLen2 >= rem)
1009         {
1010           srcFinished2 = True;
1011           srcLen2 = (SizeT)rem;
1012         }
1013         if (rem == 0 && p->block.unpackSize == p->unpackSize)
1014           return SZ_ERROR_DATA;
1015       }
1016 
1017       if (p->block.unpackSize != (UInt64)(Int64)-1)
1018       {
1019         UInt64 rem = p->block.unpackSize - p->unpackSize;
1020         if (destLen2 >= rem)
1021         {
1022           destFinish = True;
1023           finishMode2 = CODER_FINISH_END;
1024           destLen2 = (SizeT)rem;
1025         }
1026       }
1027 
1028       /*
1029       if (srcLen2 == 0 && destLen2 == 0)
1030       {
1031         *status = CODER_STATUS_NOT_FINISHED;
1032         return SZ_OK;
1033       }
1034       */
1035 
1036       {
1037         res = MixCoder_Code(&p->decoder,
1038             (p->outBuf ? NULL : dest), &destLen2, destFinish,
1039             src, &srcLen2, srcFinished2,
1040             finishMode2);
1041 
1042         *status = p->decoder.status;
1043         XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1044         if (!p->outBuf)
1045           dest += destLen2;
1046         p->outDataWritten += destLen2;
1047       }
1048 
1049       (*srcLen) += srcLen2;
1050       src += srcLen2;
1051       p->packSize += srcLen2;
1052       (*destLen) += destLen2;
1053       p->unpackSize += destLen2;
1054 
1055       RINOK(res);
1056 
1057       if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1058       {
1059         if (p->block.packSize == p->packSize
1060             && *status == CODER_STATUS_NEEDS_MORE_INPUT)
1061         {
1062           PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
1063           *status = CODER_STATUS_NOT_SPECIFIED;
1064           return SZ_ERROR_DATA;
1065         }
1066 
1067         return SZ_OK;
1068       }
1069       {
1070         XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1071         p->state = XZ_STATE_BLOCK_FOOTER;
1072         p->pos = 0;
1073         p->alignPos = 0;
1074         *status = CODER_STATUS_NOT_SPECIFIED;
1075 
1076         if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1077            || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1078         {
1079           PRF_STR("ERROR: block.size mismatch");
1080           return SZ_ERROR_DATA;
1081         }
1082       }
1083       // continue;
1084     }
1085 
1086     srcRem = srcLenOrig - *srcLen;
1087 
1088     // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1089     if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1090     {
1091       *status = CODER_STATUS_NEEDS_MORE_INPUT;
1092       return SZ_OK;
1093     }
1094 
1095     switch (p->state)
1096     {
1097       case XZ_STATE_STREAM_HEADER:
1098       {
1099         if (p->pos < XZ_STREAM_HEADER_SIZE)
1100         {
1101           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1102             return SZ_ERROR_NO_ARCHIVE;
1103           if (p->decodeToStreamSignature)
1104             return SZ_OK;
1105           p->buf[p->pos++] = *src++;
1106           (*srcLen)++;
1107         }
1108         else
1109         {
1110           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
1111           p->numStartedStreams++;
1112           p->indexSize = 0;
1113           p->numBlocks = 0;
1114           Sha256_Init(&p->sha);
1115           p->state = XZ_STATE_BLOCK_HEADER;
1116           p->pos = 0;
1117         }
1118         break;
1119       }
1120 
1121       case XZ_STATE_BLOCK_HEADER:
1122       {
1123         if (p->pos == 0)
1124         {
1125           p->buf[p->pos++] = *src++;
1126           (*srcLen)++;
1127           if (p->buf[0] == 0)
1128           {
1129             if (p->decodeOnlyOneBlock)
1130               return SZ_ERROR_DATA;
1131             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1132             p->indexPos = p->indexPreSize;
1133             p->indexSize += p->indexPreSize;
1134             Sha256_Final(&p->sha, p->shaDigest);
1135             Sha256_Init(&p->sha);
1136             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1137             p->state = XZ_STATE_STREAM_INDEX;
1138             break;
1139           }
1140           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
1141           break;
1142         }
1143 
1144         if (p->pos != p->blockHeaderSize)
1145         {
1146           UInt32 cur = p->blockHeaderSize - p->pos;
1147           if (cur > srcRem)
1148             cur = (UInt32)srcRem;
1149           memcpy(p->buf + p->pos, src, cur);
1150           p->pos += cur;
1151           (*srcLen) += cur;
1152           src += cur;
1153         }
1154         else
1155         {
1156           RINOK(XzBlock_Parse(&p->block, p->buf));
1157           if (!XzBlock_AreSupportedFilters(&p->block))
1158             return SZ_ERROR_UNSUPPORTED;
1159           p->numTotalBlocks++;
1160           p->state = XZ_STATE_BLOCK;
1161           p->packSize = 0;
1162           p->unpackSize = 0;
1163           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1164           if (p->parseMode)
1165           {
1166             p->headerParsedOk = True;
1167             return SZ_OK;
1168           }
1169           RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
1170         }
1171         break;
1172       }
1173 
1174       case XZ_STATE_BLOCK_FOOTER:
1175       {
1176         if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1177         {
1178           if (srcRem == 0)
1179           {
1180             *status = CODER_STATUS_NEEDS_MORE_INPUT;
1181             return SZ_OK;
1182           }
1183           (*srcLen)++;
1184           p->alignPos++;
1185           if (*src++ != 0)
1186             return SZ_ERROR_CRC;
1187         }
1188         else
1189         {
1190           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
1191           UInt32 cur = checkSize - p->pos;
1192           if (cur != 0)
1193           {
1194             if (srcRem == 0)
1195             {
1196               *status = CODER_STATUS_NEEDS_MORE_INPUT;
1197               return SZ_OK;
1198             }
1199             if (cur > srcRem)
1200               cur = (UInt32)srcRem;
1201             memcpy(p->buf + p->pos, src, cur);
1202             p->pos += cur;
1203             (*srcLen) += cur;
1204             src += cur;
1205             if (checkSize != p->pos)
1206               break;
1207           }
1208           {
1209             Byte digest[XZ_CHECK_SIZE_MAX];
1210             p->state = XZ_STATE_BLOCK_HEADER;
1211             p->pos = 0;
1212             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1213               return SZ_ERROR_CRC;
1214             if (p->decodeOnlyOneBlock)
1215             {
1216               *status = CODER_STATUS_FINISHED_WITH_MARK;
1217               return SZ_OK;
1218             }
1219           }
1220         }
1221         break;
1222       }
1223 
1224       case XZ_STATE_STREAM_INDEX:
1225       {
1226         if (p->pos < p->indexPreSize)
1227         {
1228           (*srcLen)++;
1229           if (*src++ != p->buf[p->pos++])
1230             return SZ_ERROR_CRC;
1231         }
1232         else
1233         {
1234           if (p->indexPos < p->indexSize)
1235           {
1236             UInt64 cur = p->indexSize - p->indexPos;
1237             if (srcRem > cur)
1238               srcRem = (SizeT)cur;
1239             p->crc = CrcUpdate(p->crc, src, srcRem);
1240             Sha256_Update(&p->sha, src, srcRem);
1241             (*srcLen) += srcRem;
1242             src += srcRem;
1243             p->indexPos += srcRem;
1244           }
1245           else if ((p->indexPos & 3) != 0)
1246           {
1247             Byte b = *src++;
1248             p->crc = CRC_UPDATE_BYTE(p->crc, b);
1249             (*srcLen)++;
1250             p->indexPos++;
1251             p->indexSize++;
1252             if (b != 0)
1253               return SZ_ERROR_CRC;
1254           }
1255           else
1256           {
1257             Byte digest[SHA256_DIGEST_SIZE];
1258             p->state = XZ_STATE_STREAM_INDEX_CRC;
1259             p->indexSize += 4;
1260             p->pos = 0;
1261             Sha256_Final(&p->sha, digest);
1262             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1263               return SZ_ERROR_CRC;
1264           }
1265         }
1266         break;
1267       }
1268 
1269       case XZ_STATE_STREAM_INDEX_CRC:
1270       {
1271         if (p->pos < 4)
1272         {
1273           (*srcLen)++;
1274           p->buf[p->pos++] = *src++;
1275         }
1276         else
1277         {
1278           p->state = XZ_STATE_STREAM_FOOTER;
1279           p->pos = 0;
1280           if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
1281             return SZ_ERROR_CRC;
1282         }
1283         break;
1284       }
1285 
1286       case XZ_STATE_STREAM_FOOTER:
1287       {
1288         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1289         if (cur > srcRem)
1290           cur = (UInt32)srcRem;
1291         memcpy(p->buf + p->pos, src, cur);
1292         p->pos += cur;
1293         (*srcLen) += cur;
1294         src += cur;
1295         if (p->pos == XZ_STREAM_FOOTER_SIZE)
1296         {
1297           p->state = XZ_STATE_STREAM_PADDING;
1298           p->numFinishedStreams++;
1299           p->padSize = 0;
1300           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1301             return SZ_ERROR_CRC;
1302         }
1303         break;
1304       }
1305 
1306       case XZ_STATE_STREAM_PADDING:
1307       {
1308         if (*src != 0)
1309         {
1310           if (((UInt32)p->padSize & 3) != 0)
1311             return SZ_ERROR_NO_ARCHIVE;
1312           p->pos = 0;
1313           p->state = XZ_STATE_STREAM_HEADER;
1314         }
1315         else
1316         {
1317           (*srcLen)++;
1318           src++;
1319           p->padSize++;
1320         }
1321         break;
1322       }
1323 
1324       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1325     }
1326   }
1327   /*
1328   if (p->state == XZ_STATE_FINISHED)
1329     *status = CODER_STATUS_FINISHED_WITH_MARK;
1330   return SZ_OK;
1331   */
1332 }
1333 
1334 
XzUnpacker_CodeFull(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ECoderFinishMode finishMode,ECoderStatus * status)1335 SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1336     const Byte *src, SizeT *srcLen,
1337     ECoderFinishMode finishMode, ECoderStatus *status)
1338 {
1339   XzUnpacker_Init(p);
1340   XzUnpacker_SetOutBuf(p, dest, *destLen);
1341 
1342   return XzUnpacker_Code(p,
1343       NULL, destLen,
1344       src, srcLen, True,
1345       finishMode, status);
1346 }
1347 
1348 
XzUnpacker_IsBlockFinished(const CXzUnpacker * p)1349 Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1350 {
1351   return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1352 }
1353 
XzUnpacker_IsStreamWasFinished(const CXzUnpacker * p)1354 Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1355 {
1356   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1357 }
1358 
XzUnpacker_GetExtraSize(const CXzUnpacker * p)1359 UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1360 {
1361   UInt64 num = 0;
1362   if (p->state == XZ_STATE_STREAM_PADDING)
1363     num = p->padSize;
1364   else if (p->state == XZ_STATE_STREAM_HEADER)
1365     num = p->padSize + p->pos;
1366   return num;
1367 }
1368 
1369 
1370 
1371 
1372 
1373 
1374 
1375 
1376 
1377 
1378 
1379 
1380 
1381 
1382 
1383 
1384 
1385 
1386 
1387 
1388 
1389 #ifndef _7ZIP_ST
1390 #include "MtDec.h"
1391 #endif
1392 
1393 
XzDecMtProps_Init(CXzDecMtProps * p)1394 void XzDecMtProps_Init(CXzDecMtProps *p)
1395 {
1396   p->inBufSize_ST = 1 << 18;
1397   p->outStep_ST = 1 << 20;
1398   p->ignoreErrors = False;
1399 
1400   #ifndef _7ZIP_ST
1401   p->numThreads = 1;
1402   p->inBufSize_MT = 1 << 18;
1403   p->memUseMax = sizeof(size_t) << 28;
1404   #endif
1405 }
1406 
1407 
1408 
1409 #ifndef _7ZIP_ST
1410 
1411 /* ---------- CXzDecMtThread ---------- */
1412 
1413 typedef struct
1414 {
1415   Byte *outBuf;
1416   size_t outBufSize;
1417   size_t outPreSize;
1418   size_t inPreSize;
1419   size_t inPreHeaderSize;
1420   size_t blockPackSize_for_Index;  // including block header and checksum.
1421   size_t blockPackTotal;  // including stream header, block header and checksum.
1422   size_t inCodeSize;
1423   size_t outCodeSize;
1424   ECoderStatus status;
1425   SRes codeRes;
1426   Bool skipMode;
1427   // Bool finishedWithMark;
1428   EMtDecParseState parseState;
1429   Bool parsing_Truncated;
1430   Bool atBlockHeader;
1431   CXzStreamFlags streamFlags;
1432   // UInt64 numFinishedStreams
1433   UInt64 numStreams;
1434   UInt64 numTotalBlocks;
1435   UInt64 numBlocks;
1436 
1437   Bool dec_created;
1438   CXzUnpacker dec;
1439 
1440   Byte mtPad[1 << 7];
1441 } CXzDecMtThread;
1442 
1443 #endif
1444 
1445 
1446 /* ---------- CXzDecMt ---------- */
1447 
1448 typedef struct
1449 {
1450   CAlignOffsetAlloc alignOffsetAlloc;
1451   ISzAllocPtr allocMid;
1452 
1453   CXzDecMtProps props;
1454   size_t unpackBlockMaxSize;
1455 
1456   ISeqInStream *inStream;
1457   ISeqOutStream *outStream;
1458   ICompressProgress *progress;
1459   // CXzStatInfo *stat;
1460 
1461   Bool finishMode;
1462   Bool outSize_Defined;
1463   UInt64 outSize;
1464 
1465   UInt64 outProcessed;
1466   UInt64 inProcessed;
1467   UInt64 readProcessed;
1468   Bool readWasFinished;
1469   SRes readRes;
1470   SRes writeRes;
1471 
1472   Byte *outBuf;
1473   size_t outBufSize;
1474   Byte *inBuf;
1475   size_t inBufSize;
1476   Bool dec_created;
1477   CXzUnpacker dec;
1478 
1479   ECoderStatus status;
1480   SRes codeRes;
1481 
1482   #ifndef _7ZIP_ST
1483   Bool mainDecoderWasCalled;
1484   // int statErrorDefined;
1485   int finishedDecoderIndex;
1486 
1487   // global values that are used in Parse stage
1488   CXzStreamFlags streamFlags;
1489   // UInt64 numFinishedStreams
1490   UInt64 numStreams;
1491   UInt64 numTotalBlocks;
1492   UInt64 numBlocks;
1493 
1494   // UInt64 numBadBlocks;
1495   SRes mainErrorCode;
1496 
1497   Bool isBlockHeaderState_Parse;
1498   Bool isBlockHeaderState_Write;
1499   UInt64 outProcessed_Parse;
1500   Bool parsing_Truncated;
1501 
1502   Bool mtc_WasConstructed;
1503   CMtDec mtc;
1504   CXzDecMtThread coders[MTDEC__THREADS_MAX];
1505   #endif
1506 
1507 } CXzDecMt;
1508 
1509 
1510 
XzDecMt_Create(ISzAllocPtr alloc,ISzAllocPtr allocMid)1511 CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1512 {
1513   CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1514   if (!p)
1515     return NULL;
1516 
1517   AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1518   p->alignOffsetAlloc.baseAlloc = alloc;
1519   p->alignOffsetAlloc.numAlignBits = 7;
1520   p->alignOffsetAlloc.offset = 0;
1521 
1522   p->allocMid = allocMid;
1523 
1524   p->outBuf = NULL;
1525   p->outBufSize = 0;
1526   p->inBuf = NULL;
1527   p->inBufSize = 0;
1528   p->dec_created = False;
1529 
1530   p->unpackBlockMaxSize = 0;
1531 
1532   XzDecMtProps_Init(&p->props);
1533 
1534   #ifndef _7ZIP_ST
1535   p->mtc_WasConstructed = False;
1536   {
1537     unsigned i;
1538     for (i = 0; i < MTDEC__THREADS_MAX; i++)
1539     {
1540       CXzDecMtThread *coder = &p->coders[i];
1541       coder->dec_created = False;
1542       coder->outBuf = NULL;
1543       coder->outBufSize = 0;
1544     }
1545   }
1546   #endif
1547 
1548   return p;
1549 }
1550 
1551 
1552 #ifndef _7ZIP_ST
1553 
XzDecMt_FreeOutBufs(CXzDecMt * p)1554 static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1555 {
1556   unsigned i;
1557   for (i = 0; i < MTDEC__THREADS_MAX; i++)
1558   {
1559     CXzDecMtThread *coder = &p->coders[i];
1560     if (coder->outBuf)
1561     {
1562       ISzAlloc_Free(p->allocMid, coder->outBuf);
1563       coder->outBuf = NULL;
1564       coder->outBufSize = 0;
1565     }
1566   }
1567   p->unpackBlockMaxSize = 0;
1568 }
1569 
1570 #endif
1571 
1572 
1573 
XzDecMt_FreeSt(CXzDecMt * p)1574 static void XzDecMt_FreeSt(CXzDecMt *p)
1575 {
1576   if (p->dec_created)
1577   {
1578     XzUnpacker_Free(&p->dec);
1579     p->dec_created = False;
1580   }
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 S_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 (coder->inCodeSize < coder->inPreHeaderSize)
1905   {
1906     UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
1907     size_t step = srcSize;
1908     if (step > rem)
1909       step = (size_t)rem;
1910     src += step;
1911     srcSize -= step;
1912     coder->inCodeSize += step;
1913     if (coder->inCodeSize < coder->inPreHeaderSize)
1914     {
1915       *stop = False;
1916       return SZ_OK;
1917     }
1918   }
1919 
1920   if (!coder->dec.headerParsedOk)
1921     return SZ_OK;
1922   if (!coder->outBuf)
1923     return SZ_OK;
1924 
1925   if (coder->codeRes == SZ_OK)
1926   {
1927     ECoderStatus status;
1928     SRes res;
1929     size_t srcProcessed = srcSize;
1930     size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1931 
1932     // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1933 
1934     res = XzUnpacker_Code(&coder->dec,
1935         NULL, &outSizeCur,
1936         src, &srcProcessed, srcFinished,
1937         // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1938         CODER_FINISH_END,
1939         &status);
1940 
1941     // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1942 
1943     coder->codeRes = res;
1944     coder->status = status;
1945     coder->inCodeSize += srcProcessed;
1946     coder->outCodeSize = coder->dec.outDataWritten;
1947     *inCodePos = coder->inCodeSize;
1948     *outCodePos = coder->outCodeSize;
1949 
1950     if (res == SZ_OK)
1951     {
1952       if (srcProcessed == srcSize)
1953         *stop = False;
1954       return SZ_OK;
1955     }
1956   }
1957 
1958   if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1959   {
1960     *inCodePos = coder->inPreSize;
1961     *outCodePos = coder->outPreSize;
1962     return S_OK;
1963   }
1964   return coder->codeRes;
1965 }
1966 
1967 
1968 #define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1969 
XzDecMt_Callback_Write(void * pp,unsigned coderIndex,Bool needWriteToStream,const Byte * src,size_t srcSize,Bool * needContinue,Bool * canRecode)1970 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1971     Bool needWriteToStream,
1972     const Byte *src, size_t srcSize,
1973     // int srcFinished,
1974     Bool *needContinue,
1975     Bool *canRecode)
1976 {
1977   CXzDecMt *me = (CXzDecMt *)pp;
1978   const CXzDecMtThread *coder = &me->coders[coderIndex];
1979 
1980   // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1981 
1982   *needContinue = False;
1983   *canRecode = True;
1984 
1985   if (!needWriteToStream)
1986     return SZ_OK;
1987 
1988   if (!coder->dec.headerParsedOk || !coder->outBuf)
1989   {
1990     if (me->finishedDecoderIndex < 0)
1991       me->finishedDecoderIndex = coderIndex;
1992     return SZ_OK;
1993   }
1994 
1995   if (me->finishedDecoderIndex >= 0)
1996     return SZ_OK;
1997 
1998   me->mtc.inProcessed += coder->inCodeSize;
1999 
2000   *canRecode = False;
2001 
2002   {
2003     SRes res;
2004     size_t size = coder->outCodeSize;
2005     Byte *data = coder->outBuf;
2006 
2007     // we use in me->dec: sha, numBlocks, indexSize
2008 
2009     if (!me->isBlockHeaderState_Write)
2010     {
2011       XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2012       me->dec.decodeOnlyOneBlock = False;
2013       me->dec.numStartedStreams = coder->dec.numStartedStreams;
2014       me->dec.streamFlags = coder->streamFlags;
2015 
2016       me->isBlockHeaderState_Write = True;
2017     }
2018 
2019     me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2020     XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2021 
2022     if (coder->outPreSize != size)
2023     {
2024       if (me->props.ignoreErrors)
2025       {
2026         memset(data + size, 0, coder->outPreSize - size);
2027         size = coder->outPreSize;
2028       }
2029       // me->numBadBlocks++;
2030       if (me->mainErrorCode == SZ_OK)
2031       {
2032         if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2033           me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2034         else
2035           me->mainErrorCode = SZ_ERROR_DATA;
2036       }
2037     }
2038 
2039     if (me->writeRes != SZ_OK)
2040       return me->writeRes;
2041 
2042     res = SZ_OK;
2043     {
2044       if (me->outSize_Defined)
2045       {
2046         const UInt64 rem = me->outSize - me->outProcessed;
2047         if (size > rem)
2048           size = (SizeT)rem;
2049       }
2050 
2051       for (;;)
2052       {
2053         size_t cur = size;
2054         size_t written;
2055         if (cur > XZDECMT_STREAM_WRITE_STEP)
2056           cur = XZDECMT_STREAM_WRITE_STEP;
2057 
2058         written = ISeqOutStream_Write(me->outStream, data, cur);
2059 
2060         // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2061 
2062         me->outProcessed += written;
2063         if (written != cur)
2064         {
2065           me->writeRes = SZ_ERROR_WRITE;
2066           res = me->writeRes;
2067           break;
2068         }
2069         data += cur;
2070         size -= cur;
2071         // PRF_STR_INT("Written size =", size);
2072         if (size == 0)
2073           break;
2074         res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2075         if (res != SZ_OK)
2076           break;
2077       }
2078     }
2079 
2080     if (coder->codeRes != SZ_OK)
2081       if (!me->props.ignoreErrors)
2082       {
2083         me->finishedDecoderIndex = coderIndex;
2084         return res;
2085       }
2086 
2087     RINOK(res);
2088 
2089     if (coder->inPreSize != coder->inCodeSize
2090         || coder->blockPackTotal != coder->inCodeSize)
2091     {
2092       me->finishedDecoderIndex = coderIndex;
2093       return SZ_OK;
2094     }
2095 
2096     if (coder->parseState != MTDEC_PARSE_END)
2097     {
2098       *needContinue = True;
2099       return SZ_OK;
2100     }
2101   }
2102 
2103   // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2104   // so we can use mtc variables without lock
2105 
2106   PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2107 
2108   me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2109   {
2110     CXzUnpacker *dec = &me->dec;
2111 
2112     PRF_STR_INT("PostSingle", srcSize);
2113 
2114     {
2115       size_t srcProcessed = srcSize;
2116       ECoderStatus status;
2117       size_t outSizeCur = 0;
2118       SRes res;
2119 
2120       // dec->decodeOnlyOneBlock = False;
2121       dec->decodeToStreamSignature = True;
2122 
2123       me->mainDecoderWasCalled = True;
2124 
2125       if (coder->parsing_Truncated)
2126       {
2127         me->parsing_Truncated = True;
2128         return SZ_OK;
2129       }
2130 
2131       res = XzUnpacker_Code(dec,
2132           NULL, &outSizeCur,
2133           src, &srcProcessed,
2134           me->mtc.readWasFinished, // srcFinished
2135           CODER_FINISH_END, // CODER_FINISH_ANY,
2136           &status);
2137 
2138       me->status = status;
2139       me->codeRes = res;
2140 
2141       me->mtc.inProcessed += srcProcessed;
2142       me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2143 
2144       if (res != SZ_OK)
2145       {
2146         return S_OK;
2147         // return res;
2148       }
2149 
2150       if (dec->state == XZ_STATE_STREAM_HEADER)
2151       {
2152         *needContinue = True;
2153         me->isBlockHeaderState_Parse = False;
2154         me->isBlockHeaderState_Write = False;
2155         {
2156           Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2157           if (!crossBuf)
2158             return SZ_ERROR_MEM;
2159           memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
2160         }
2161         me->mtc.crossStart = 0;
2162         me->mtc.crossEnd = srcSize - srcProcessed;
2163         return SZ_OK;
2164       }
2165 
2166       if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2167       {
2168         return E_FAIL;
2169       }
2170 
2171       if (me->mtc.readWasFinished)
2172       {
2173         return SZ_OK;
2174       }
2175     }
2176 
2177     {
2178       size_t inPos;
2179       size_t inLim;
2180       const Byte *inData;
2181       UInt64 inProgressPrev = me->mtc.inProcessed;
2182 
2183       // XzDecMt_Prepare_InBuf_ST(p);
2184       Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2185       if (!crossBuf)
2186         return SZ_ERROR_MEM;
2187 
2188       inPos = 0;
2189       inLim = 0;
2190       // outProcessed = 0;
2191 
2192       inData = crossBuf;
2193 
2194       for (;;)
2195       {
2196         SizeT inProcessed;
2197         SizeT outProcessed;
2198         ECoderStatus status;
2199         SRes res;
2200 
2201         if (inPos == inLim)
2202         {
2203           if (!me->mtc.readWasFinished)
2204           {
2205             inPos = 0;
2206             inLim = me->mtc.inBufSize;
2207             me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
2208             me->mtc.readProcessed += inLim;
2209             if (inLim == 0 || me->mtc.readRes != SZ_OK)
2210               me->mtc.readWasFinished = True;
2211           }
2212         }
2213 
2214         inProcessed = inLim - inPos;
2215         outProcessed = 0;
2216 
2217         res = XzUnpacker_Code(dec,
2218             NULL, &outProcessed,
2219             inData + inPos, &inProcessed,
2220             (inProcessed == 0), // srcFinished
2221             CODER_FINISH_END, &status);
2222 
2223         me->codeRes = res;
2224         me->status = status;
2225         inPos += inProcessed;
2226         me->mtc.inProcessed += inProcessed;
2227         me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2228 
2229         if (res != SZ_OK)
2230         {
2231           return S_OK;
2232           // return res;
2233         }
2234 
2235         if (dec->state == XZ_STATE_STREAM_HEADER)
2236         {
2237           *needContinue = True;
2238           me->mtc.crossStart = inPos;
2239           me->mtc.crossEnd = inLim;
2240           me->isBlockHeaderState_Parse = False;
2241           me->isBlockHeaderState_Write = False;
2242           return SZ_OK;
2243         }
2244 
2245         if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2246           return E_FAIL;
2247 
2248         if (me->mtc.progress)
2249         {
2250           UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2251           if (inDelta >= (1 << 22))
2252           {
2253             RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2254             inProgressPrev = me->mtc.inProcessed;
2255           }
2256         }
2257         if (me->mtc.readWasFinished)
2258           return SZ_OK;
2259       }
2260     }
2261   }
2262 }
2263 
2264 
2265 #endif
2266 
2267 
2268 
XzStatInfo_Clear(CXzStatInfo * p)2269 void XzStatInfo_Clear(CXzStatInfo *p)
2270 {
2271   p->InSize = 0;
2272   p->OutSize = 0;
2273 
2274   p->NumStreams = 0;
2275   p->NumBlocks = 0;
2276 
2277   p->UnpackSize_Defined = False;
2278 
2279   p->NumStreams_Defined = False;
2280   p->NumBlocks_Defined = False;
2281 
2282   // p->IsArc = False;
2283   // p->UnexpectedEnd = False;
2284   // p->Unsupported = False;
2285   // p->HeadersError = False;
2286   // p->DataError = False;
2287   // p->CrcError = False;
2288 
2289   p->DataAfterEnd = False;
2290   p->DecodingTruncated = False;
2291 
2292   p->DecodeRes = SZ_OK;
2293   p->ReadRes = SZ_OK;
2294   p->ProgressRes = SZ_OK;
2295 
2296   p->CombinedRes = SZ_OK;
2297   p->CombinedRes_Type = SZ_OK;
2298 }
2299 
2300 
2301 
2302 
XzDecMt_Decode_ST(CXzDecMt * p,Bool tMode,CXzStatInfo * stat)2303 static SRes XzDecMt_Decode_ST(CXzDecMt *p
2304     #ifndef _7ZIP_ST
2305     , Bool tMode
2306     #endif
2307     , CXzStatInfo *stat)
2308 {
2309   size_t outPos;
2310   size_t inPos, inLim;
2311   const Byte *inData;
2312   UInt64 inPrev, outPrev;
2313 
2314   CXzUnpacker *dec;
2315 
2316   #ifndef _7ZIP_ST
2317   if (tMode)
2318   {
2319     XzDecMt_FreeOutBufs(p);
2320     tMode = MtDec_PrepareRead(&p->mtc);
2321   }
2322   #endif
2323 
2324   if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2325   {
2326     ISzAlloc_Free(p->allocMid, p->outBuf);
2327     p->outBufSize = 0;
2328     p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2329     if (!p->outBuf)
2330       return SZ_ERROR_MEM;
2331     p->outBufSize = p->props.outStep_ST;
2332   }
2333 
2334   if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2335   {
2336     ISzAlloc_Free(p->allocMid, p->inBuf);
2337     p->inBufSize = 0;
2338     p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2339     if (!p->inBuf)
2340       return SZ_ERROR_MEM;
2341     p->inBufSize = p->props.inBufSize_ST;
2342   }
2343 
2344   dec = &p->dec;
2345   dec->decodeToStreamSignature = False;
2346   // dec->decodeOnlyOneBlock = False;
2347 
2348   XzUnpacker_SetOutBuf(dec, NULL, 0);
2349 
2350   inPrev = p->inProcessed;
2351   outPrev = p->outProcessed;
2352 
2353   inPos = 0;
2354   inLim = 0;
2355   inData = NULL;
2356   outPos = 0;
2357 
2358   for (;;)
2359   {
2360     SizeT outSize;
2361     Bool finished;
2362     ECoderFinishMode finishMode;
2363     SizeT inProcessed;
2364     ECoderStatus status;
2365     SRes res;
2366 
2367     SizeT outProcessed;
2368 
2369 
2370 
2371     if (inPos == inLim)
2372     {
2373       #ifndef _7ZIP_ST
2374       if (tMode)
2375       {
2376         inData = MtDec_Read(&p->mtc, &inLim);
2377         inPos = 0;
2378         if (inData)
2379           continue;
2380         tMode = False;
2381         inLim = 0;
2382       }
2383       #endif
2384 
2385       if (!p->readWasFinished)
2386       {
2387         inPos = 0;
2388         inLim = p->inBufSize;
2389         inData = p->inBuf;
2390         p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2391         p->readProcessed += inLim;
2392         if (inLim == 0 || p->readRes != SZ_OK)
2393           p->readWasFinished = True;
2394       }
2395     }
2396 
2397     outSize = p->props.outStep_ST - outPos;
2398 
2399     finishMode = CODER_FINISH_ANY;
2400     if (p->outSize_Defined)
2401     {
2402       const UInt64 rem = p->outSize - p->outProcessed;
2403       if (outSize >= rem)
2404       {
2405         outSize = (SizeT)rem;
2406         if (p->finishMode)
2407           finishMode = CODER_FINISH_END;
2408       }
2409     }
2410 
2411     inProcessed = inLim - inPos;
2412     outProcessed = outSize;
2413 
2414     res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2415         inData + inPos, &inProcessed,
2416         (inPos == inLim), // srcFinished
2417         finishMode, &status);
2418 
2419     p->codeRes = res;
2420     p->status = status;
2421 
2422     inPos += inProcessed;
2423     outPos += outProcessed;
2424     p->inProcessed += inProcessed;
2425     p->outProcessed += outProcessed;
2426 
2427     finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2428 
2429     if (finished || outProcessed >= outSize)
2430       if (outPos != 0)
2431       {
2432         size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2433         p->outProcessed += written;
2434         if (written != outPos)
2435         {
2436           stat->CombinedRes_Type = SZ_ERROR_WRITE;
2437           return SZ_ERROR_WRITE;
2438         }
2439         outPos = 0;
2440       }
2441 
2442     if (p->progress && res == SZ_OK)
2443     {
2444       UInt64 inDelta = p->inProcessed - inPrev;
2445       UInt64 outDelta = p->outProcessed - outPrev;
2446       if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
2447       {
2448         res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2449         if (res != SZ_OK)
2450         {
2451           stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2452           stat->ProgressRes = res;
2453           return res;
2454         }
2455         inPrev = p->inProcessed;
2456         outPrev = p->outProcessed;
2457       }
2458     }
2459 
2460     if (finished)
2461       return res;
2462   }
2463 }
2464 
XzStatInfo_SetStat(const CXzUnpacker * dec,int finishMode,UInt64 readProcessed,UInt64 inProcessed,SRes res,ECoderStatus status,Bool decodingTruncated,CXzStatInfo * stat)2465 static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
2466     int finishMode,
2467     UInt64 readProcessed, UInt64 inProcessed,
2468     SRes res, ECoderStatus status,
2469     Bool decodingTruncated,
2470     CXzStatInfo *stat)
2471 {
2472   UInt64 extraSize;
2473 
2474   stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2475   stat->InSize = inProcessed;
2476   stat->NumStreams = dec->numStartedStreams;
2477   stat->NumBlocks = dec->numTotalBlocks;
2478 
2479   stat->UnpackSize_Defined = True;
2480   stat->NumStreams_Defined = True;
2481   stat->NumBlocks_Defined = True;
2482 
2483   extraSize = XzUnpacker_GetExtraSize(dec);
2484 
2485   if (res == SZ_OK)
2486   {
2487     if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2488     {
2489       // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2490       extraSize = 0;
2491       if (!XzUnpacker_IsStreamWasFinished(dec))
2492         res = SZ_ERROR_INPUT_EOF;
2493     }
2494     else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2495       res = SZ_ERROR_DATA;
2496   }
2497   else if (res == SZ_ERROR_NO_ARCHIVE)
2498   {
2499     /*
2500     SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2501       XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC
2502       XZ_STATE_STREAM_PADDING - if non-zero padding data
2503     extraSize / inProcessed don't include "bad" byte
2504     */
2505     if (inProcessed != extraSize) // if good streams before error
2506       if (extraSize != 0 || readProcessed != inProcessed)
2507       {
2508         stat->DataAfterEnd = True;
2509         // there is some good xz stream before. So we set SZ_OK
2510         res = SZ_OK;
2511       }
2512   }
2513 
2514   stat->DecodeRes = res;
2515 
2516   stat->InSize -= extraSize;
2517   return res;
2518 }
2519 
2520 
XzDecMt_Decode(CXzDecMtHandle pp,const CXzDecMtProps * props,const UInt64 * outDataSize,int finishMode,ISeqOutStream * outStream,ISeqInStream * inStream,CXzStatInfo * stat,int * isMT,ICompressProgress * progress)2521 SRes XzDecMt_Decode(CXzDecMtHandle pp,
2522     const CXzDecMtProps *props,
2523     const UInt64 *outDataSize, int finishMode,
2524     ISeqOutStream *outStream,
2525     // Byte *outBuf, size_t *outBufSize,
2526     ISeqInStream *inStream,
2527     // const Byte *inData, size_t inDataSize,
2528     CXzStatInfo *stat,
2529     int *isMT,
2530     ICompressProgress *progress)
2531 {
2532   CXzDecMt *p = (CXzDecMt *)pp;
2533   #ifndef _7ZIP_ST
2534   Bool tMode;
2535   #endif
2536 
2537   XzStatInfo_Clear(stat);
2538 
2539   p->props = *props;
2540 
2541   p->inStream = inStream;
2542   p->outStream = outStream;
2543   p->progress = progress;
2544   // p->stat = stat;
2545 
2546   p->outSize = 0;
2547   p->outSize_Defined = False;
2548   if (outDataSize)
2549   {
2550     p->outSize_Defined = True;
2551     p->outSize = *outDataSize;
2552   }
2553 
2554   p->finishMode = finishMode;
2555 
2556   // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2557 
2558   p->writeRes = SZ_OK;
2559   p->outProcessed = 0;
2560   p->inProcessed = 0;
2561   p->readProcessed = 0;
2562   p->readWasFinished = False;
2563 
2564   p->codeRes = 0;
2565   p->status = CODER_STATUS_NOT_SPECIFIED;
2566 
2567   if (!p->dec_created)
2568   {
2569     XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
2570     p->dec_created = True;
2571   }
2572   XzUnpacker_Init(&p->dec);
2573 
2574 
2575   *isMT = False;
2576 
2577     /*
2578     p->outBuf = NULL;
2579     p->outBufSize = 0;
2580     if (!outStream)
2581     {
2582       p->outBuf = outBuf;
2583       p->outBufSize = *outBufSize;
2584       *outBufSize = 0;
2585     }
2586     */
2587 
2588 
2589   #ifndef _7ZIP_ST
2590 
2591   p->isBlockHeaderState_Parse = False;
2592   p->isBlockHeaderState_Write = False;
2593   // p->numBadBlocks = 0;
2594   p->mainErrorCode = SZ_OK;
2595   p->mainDecoderWasCalled = False;
2596 
2597   tMode = False;
2598 
2599   if (p->props.numThreads > 1)
2600   {
2601     IMtDecCallback vt;
2602 
2603     XzDecMt_FreeSt(p);
2604 
2605     p->outProcessed_Parse = 0;
2606     p->parsing_Truncated = False;
2607 
2608     p->numStreams = 0;
2609     p->numTotalBlocks = 0;
2610     p->numBlocks = 0;
2611     p->finishedDecoderIndex = -1;
2612 
2613     if (!p->mtc_WasConstructed)
2614     {
2615       p->mtc_WasConstructed = True;
2616       MtDec_Construct(&p->mtc);
2617     }
2618 
2619     p->mtc.mtCallback = &vt;
2620     p->mtc.mtCallbackObject = p;
2621 
2622     p->mtc.progress = progress;
2623     p->mtc.inStream = inStream;
2624     p->mtc.alloc = &p->alignOffsetAlloc.vt;
2625     // p->mtc.inData = inData;
2626     // p->mtc.inDataSize = inDataSize;
2627     p->mtc.inBufSize = p->props.inBufSize_MT;
2628     // p->mtc.inBlockMax = p->props.inBlockMax;
2629     p->mtc.numThreadsMax = p->props.numThreads;
2630 
2631     *isMT = True;
2632 
2633     vt.Parse = XzDecMt_Callback_Parse;
2634     vt.PreCode = XzDecMt_Callback_PreCode;
2635     vt.Code = XzDecMt_Callback_Code;
2636     vt.Write = XzDecMt_Callback_Write;
2637 
2638     {
2639       Bool needContinue;
2640 
2641       SRes res = MtDec_Code(&p->mtc);
2642 
2643       stat->InSize = p->mtc.inProcessed;
2644 
2645       p->inProcessed = p->mtc.inProcessed;
2646       p->readRes = p->mtc.readRes;
2647       p->readWasFinished = p->mtc.readWasFinished;
2648       p->readProcessed = p->mtc.readProcessed;
2649 
2650       tMode = True;
2651       needContinue = False;
2652 
2653       if (res == SZ_OK)
2654       {
2655         if (p->mtc.mtProgress.res != SZ_OK)
2656         {
2657           res = p->mtc.mtProgress.res;
2658           stat->ProgressRes = res;
2659           stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2660         }
2661         else
2662           needContinue = p->mtc.needContinue;
2663       }
2664 
2665       if (!needContinue)
2666       {
2667         SRes codeRes;
2668         Bool truncated = False;
2669         ECoderStatus status;
2670         CXzUnpacker *dec;
2671 
2672         stat->OutSize = p->outProcessed;
2673 
2674         if (p->finishedDecoderIndex >= 0)
2675         {
2676           CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2677           codeRes = coder->codeRes;
2678           dec = &coder->dec;
2679           status = coder->status;
2680         }
2681         else if (p->mainDecoderWasCalled)
2682         {
2683           codeRes = p->codeRes;
2684           dec = &p->dec;
2685           status = p->status;
2686           truncated = p->parsing_Truncated;
2687         }
2688         else
2689           return E_FAIL;
2690 
2691         XzStatInfo_SetStat(dec, p->finishMode,
2692             p->mtc.readProcessed, p->mtc.inProcessed,
2693             codeRes, status,
2694             truncated,
2695             stat);
2696 
2697         if (res == SZ_OK)
2698         {
2699           if (p->writeRes != SZ_OK)
2700           {
2701             res = p->writeRes;
2702             stat->CombinedRes_Type = SZ_ERROR_WRITE;
2703           }
2704           else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
2705           {
2706             res = p->mtc.readRes;
2707             stat->ReadRes = res;
2708             stat->CombinedRes_Type = SZ_ERROR_READ;
2709           }
2710           else if (p->mainErrorCode != SZ_OK)
2711           {
2712             res = p->mainErrorCode;
2713           }
2714         }
2715 
2716         stat->CombinedRes = res;
2717         if (stat->CombinedRes_Type == SZ_OK)
2718           stat->CombinedRes_Type = res;
2719         return res;
2720       }
2721 
2722       PRF_STR("----- decoding ST -----");
2723     }
2724   }
2725 
2726   #endif
2727 
2728 
2729   *isMT = False;
2730 
2731   {
2732     SRes res = XzDecMt_Decode_ST(p
2733         #ifndef _7ZIP_ST
2734         , tMode
2735         #endif
2736         , stat
2737         );
2738 
2739     XzStatInfo_SetStat(&p->dec,
2740         p->finishMode,
2741         p->readProcessed, p->inProcessed,
2742         p->codeRes, p->status,
2743         False, // truncated
2744         stat);
2745 
2746     if (res == SZ_OK)
2747     {
2748       /*
2749       if (p->writeRes != SZ_OK)
2750       {
2751         res = p->writeRes;
2752         stat->CombinedRes_Type = SZ_ERROR_WRITE;
2753       }
2754       else
2755       */
2756       if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
2757       {
2758         res = p->readRes;
2759         stat->ReadRes = res;
2760         stat->CombinedRes_Type = SZ_ERROR_READ;
2761       }
2762       #ifndef _7ZIP_ST
2763       else if (p->mainErrorCode != SZ_OK)
2764         res = p->mainErrorCode;
2765       #endif
2766     }
2767 
2768     stat->CombinedRes = res;
2769     if (stat->CombinedRes_Type == SZ_OK)
2770       stat->CombinedRes_Type = res;
2771     return res;
2772   }
2773 }
2774