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