src/third-party/lzma/XzDec.c (view raw)
1/* XzDec.c -- Xz Decode
22019-02-02 : 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
54unsigned 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
74typedef 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
91static void BraState_Free(void *pp, ISzAllocPtr alloc)
92{
93 ISzAlloc_Free(alloc, pp);
94}
95
96static 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
137static 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
149static 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
174static 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
243SRes 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 = (CBraState *)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
272static void SbState_Free(void *pp, ISzAllocPtr alloc)
273{
274 CSbDec *p = (CSbDec *)pp;
275 SbDec_Free(p);
276 ISzAlloc_Free(alloc, pp);
277}
278
279static 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
287static void SbState_Init(void *pp)
288{
289 SbDec_Init((CSbDec *)pp);
290}
291
292static 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
315static 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
341typedef struct
342{
343 CLzma2Dec decoder;
344 BoolInt outBufMode;
345} CLzma2Dec_Spec;
346
347
348static 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
358static 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
371static 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
382static 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 = (ECoderStatus)status2;
404 return res;
405}
406
407
408static 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
435static 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
450static 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
466static 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
486static 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
508static 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
525static 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
541output (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
547static 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 BoolInt processed = False;
641 BoolInt 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
755SRes 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
764static BoolInt 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
778static BoolInt 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
805SRes 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
866static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
867{
868 unsigned i;
869 BoolInt 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
917void 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
936void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
937{
938 p->outBuf = outBuf;
939 p->outBufSize = outBufSize;
940}
941
942
943void 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
952void XzUnpacker_Free(CXzUnpacker *p)
953{
954 MixCoder_Free(&p->decoder);
955}
956
957
958void 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
969static 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
981SRes 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 BoolInt srcFinished2 = srcFinished;
1003 BoolInt 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
1335SRes 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
1349BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1350{
1351 return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1352}
1353
1354BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1355{
1356 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1357}
1358
1359UInt64 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
1394void 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
1413typedef 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 BoolInt skipMode;
1427 // BoolInt finishedWithMark;
1428 EMtDecParseState parseState;
1429 BoolInt parsing_Truncated;
1430 BoolInt atBlockHeader;
1431 CXzStreamFlags streamFlags;
1432 // UInt64 numFinishedStreams
1433 UInt64 numStreams;
1434 UInt64 numTotalBlocks;
1435 UInt64 numBlocks;
1436
1437 BoolInt dec_created;
1438 CXzUnpacker dec;
1439
1440 Byte mtPad[1 << 7];
1441} CXzDecMtThread;
1442
1443#endif
1444
1445
1446/* ---------- CXzDecMt ---------- */
1447
1448typedef 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 BoolInt finishMode;
1462 BoolInt outSize_Defined;
1463 UInt64 outSize;
1464
1465 UInt64 outProcessed;
1466 UInt64 inProcessed;
1467 UInt64 readProcessed;
1468 BoolInt readWasFinished;
1469 SRes readRes;
1470 SRes writeRes;
1471
1472 Byte *outBuf;
1473 size_t outBufSize;
1474 Byte *inBuf;
1475 size_t inBufSize;
1476
1477 CXzUnpacker dec;
1478
1479 ECoderStatus status;
1480 SRes codeRes;
1481
1482 #ifndef _7ZIP_ST
1483 BoolInt 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 BoolInt isBlockHeaderState_Parse;
1498 BoolInt isBlockHeaderState_Write;
1499 UInt64 outProcessed_Parse;
1500 BoolInt parsing_Truncated;
1501
1502 BoolInt mtc_WasConstructed;
1503 CMtDec mtc;
1504 CXzDecMtThread coders[MTDEC__THREADS_MAX];
1505 #endif
1506
1507} CXzDecMt;
1508
1509
1510
1511CXzDecMtHandle 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
1529 XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1530
1531 p->unpackBlockMaxSize = 0;
1532
1533 XzDecMtProps_Init(&p->props);
1534
1535 #ifndef _7ZIP_ST
1536 p->mtc_WasConstructed = False;
1537 {
1538 unsigned i;
1539 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1540 {
1541 CXzDecMtThread *coder = &p->coders[i];
1542 coder->dec_created = False;
1543 coder->outBuf = NULL;
1544 coder->outBufSize = 0;
1545 }
1546 }
1547 #endif
1548
1549 return p;
1550}
1551
1552
1553#ifndef _7ZIP_ST
1554
1555static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1556{
1557 unsigned i;
1558 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1559 {
1560 CXzDecMtThread *coder = &p->coders[i];
1561 if (coder->outBuf)
1562 {
1563 ISzAlloc_Free(p->allocMid, coder->outBuf);
1564 coder->outBuf = NULL;
1565 coder->outBufSize = 0;
1566 }
1567 }
1568 p->unpackBlockMaxSize = 0;
1569}
1570
1571#endif
1572
1573
1574
1575static void XzDecMt_FreeSt(CXzDecMt *p)
1576{
1577 XzUnpacker_Free(&p->dec);
1578
1579 if (p->outBuf)
1580 {
1581 ISzAlloc_Free(p->allocMid, p->outBuf);
1582 p->outBuf = NULL;
1583 }
1584 p->outBufSize = 0;
1585
1586 if (p->inBuf)
1587 {
1588 ISzAlloc_Free(p->allocMid, p->inBuf);
1589 p->inBuf = NULL;
1590 }
1591 p->inBufSize = 0;
1592}
1593
1594
1595void XzDecMt_Destroy(CXzDecMtHandle pp)
1596{
1597 CXzDecMt *p = (CXzDecMt *)pp;
1598
1599 XzDecMt_FreeSt(p);
1600
1601 #ifndef _7ZIP_ST
1602
1603 if (p->mtc_WasConstructed)
1604 {
1605 MtDec_Destruct(&p->mtc);
1606 p->mtc_WasConstructed = False;
1607 }
1608 {
1609 unsigned i;
1610 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1611 {
1612 CXzDecMtThread *t = &p->coders[i];
1613 if (t->dec_created)
1614 {
1615 // we don't need to free dict here
1616 XzUnpacker_Free(&t->dec);
1617 t->dec_created = False;
1618 }
1619 }
1620 }
1621 XzDecMt_FreeOutBufs(p);
1622
1623 #endif
1624
1625 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1626}
1627
1628
1629
1630#ifndef _7ZIP_ST
1631
1632static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1633{
1634 CXzDecMt *me = (CXzDecMt *)obj;
1635 CXzDecMtThread *coder = &me->coders[coderIndex];
1636 size_t srcSize = cc->srcSize;
1637
1638 cc->srcSize = 0;
1639 cc->outPos = 0;
1640 cc->state = MTDEC_PARSE_CONTINUE;
1641
1642 cc->canCreateNewThread = True;
1643
1644 if (cc->startCall)
1645 {
1646 coder->outPreSize = 0;
1647 coder->inPreSize = 0;
1648 coder->inPreHeaderSize = 0;
1649 coder->parseState = MTDEC_PARSE_CONTINUE;
1650 coder->parsing_Truncated = False;
1651 coder->skipMode = False;
1652 coder->codeRes = SZ_OK;
1653 coder->status = CODER_STATUS_NOT_SPECIFIED;
1654 coder->inCodeSize = 0;
1655 coder->outCodeSize = 0;
1656
1657 coder->numStreams = me->numStreams;
1658 coder->numTotalBlocks = me->numTotalBlocks;
1659 coder->numBlocks = me->numBlocks;
1660
1661 if (!coder->dec_created)
1662 {
1663 XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1664 coder->dec_created = True;
1665 }
1666
1667 XzUnpacker_Init(&coder->dec);
1668
1669 if (me->isBlockHeaderState_Parse)
1670 {
1671 coder->dec.streamFlags = me->streamFlags;
1672 coder->atBlockHeader = True;
1673 XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1674 }
1675 else
1676 {
1677 coder->atBlockHeader = False;
1678 me->isBlockHeaderState_Parse = True;
1679 }
1680
1681 coder->dec.numStartedStreams = me->numStreams;
1682 coder->dec.numTotalBlocks = me->numTotalBlocks;
1683 coder->dec.numBlocks = me->numBlocks;
1684 }
1685
1686 while (!coder->skipMode)
1687 {
1688 ECoderStatus status;
1689 SRes res;
1690 size_t srcSize2 = srcSize;
1691 size_t destSize = (size_t)0 - 1;
1692
1693 coder->dec.parseMode = True;
1694 coder->dec.headerParsedOk = False;
1695
1696 PRF_STR_INT("Parse", srcSize2);
1697
1698 res = XzUnpacker_Code(&coder->dec,
1699 NULL, &destSize,
1700 cc->src, &srcSize2, cc->srcFinished,
1701 CODER_FINISH_END, &status);
1702
1703 // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1704
1705 coder->codeRes = res;
1706 coder->status = status;
1707 cc->srcSize += srcSize2;
1708 srcSize -= srcSize2;
1709 coder->inPreHeaderSize += srcSize2;
1710 coder->inPreSize = coder->inPreHeaderSize;
1711
1712 if (res != SZ_OK)
1713 {
1714 cc->state =
1715 coder->parseState = MTDEC_PARSE_END;
1716 /*
1717 if (res == SZ_ERROR_MEM)
1718 return res;
1719 return SZ_OK;
1720 */
1721 return; // res;
1722 }
1723
1724 if (coder->dec.headerParsedOk)
1725 {
1726 const CXzBlock *block = &coder->dec.block;
1727 if (XzBlock_HasUnpackSize(block)
1728 // && block->unpackSize <= me->props.outBlockMax
1729 && XzBlock_HasPackSize(block))
1730 {
1731 {
1732 if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1733 {
1734 cc->state = MTDEC_PARSE_OVERFLOW;
1735 return; // SZ_OK;
1736 }
1737 }
1738 {
1739 UInt64 packSize = block->packSize;
1740 UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1741 UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1742 UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1743 // if (blockPackSum <= me->props.inBlockMax)
1744 // unpackBlockMaxSize
1745 {
1746 coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1747 coder->blockPackTotal = (size_t)blockPackSum;
1748 coder->outPreSize = (size_t)block->unpackSize;
1749 coder->streamFlags = coder->dec.streamFlags;
1750 me->streamFlags = coder->dec.streamFlags;
1751 coder->skipMode = True;
1752 break;
1753 }
1754 }
1755 }
1756 }
1757 else
1758 // if (coder->inPreSize <= me->props.inBlockMax)
1759 {
1760 if (!cc->srcFinished)
1761 return; // SZ_OK;
1762 cc->state =
1763 coder->parseState = MTDEC_PARSE_END;
1764 return; // SZ_OK;
1765 }
1766 cc->state = MTDEC_PARSE_OVERFLOW;
1767 return; // SZ_OK;
1768 }
1769
1770 // ---------- skipMode ----------
1771 {
1772 UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1773 size_t cur = srcSize;
1774 if (cur > rem)
1775 cur = (size_t)rem;
1776 cc->srcSize += cur;
1777 coder->inPreSize += cur;
1778 srcSize -= cur;
1779
1780 if (coder->inPreSize == coder->blockPackTotal)
1781 {
1782 if (srcSize == 0)
1783 {
1784 if (!cc->srcFinished)
1785 return; // SZ_OK;
1786 cc->state = MTDEC_PARSE_END;
1787 }
1788 else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1789 cc->state = MTDEC_PARSE_END;
1790 else
1791 {
1792 cc->state = MTDEC_PARSE_NEW;
1793
1794 {
1795 size_t blockMax = me->unpackBlockMaxSize;
1796 if (blockMax < coder->outPreSize)
1797 blockMax = coder->outPreSize;
1798 {
1799 UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1800 if (me->props.memUseMax < required)
1801 cc->canCreateNewThread = False;
1802 }
1803 }
1804
1805 if (me->outSize_Defined)
1806 {
1807 // next block can be zero size
1808 const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1809 if (rem2 < coder->outPreSize)
1810 {
1811 coder->parsing_Truncated = True;
1812 cc->state = MTDEC_PARSE_END;
1813 }
1814 me->outProcessed_Parse += coder->outPreSize;
1815 }
1816 }
1817 }
1818 else if (cc->srcFinished)
1819 cc->state = MTDEC_PARSE_END;
1820 else
1821 return; // SZ_OK;
1822
1823 coder->parseState = cc->state;
1824 cc->outPos = coder->outPreSize;
1825
1826 me->numStreams = coder->dec.numStartedStreams;
1827 me->numTotalBlocks = coder->dec.numTotalBlocks;
1828 me->numBlocks = coder->dec.numBlocks + 1;
1829 return; // SZ_OK;
1830 }
1831}
1832
1833
1834static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1835{
1836 CXzDecMt *me = (CXzDecMt *)pp;
1837 CXzDecMtThread *coder = &me->coders[coderIndex];
1838 Byte *dest;
1839
1840 if (!coder->dec.headerParsedOk)
1841 return SZ_OK;
1842
1843 dest = coder->outBuf;
1844
1845 if (!dest || coder->outBufSize < coder->outPreSize)
1846 {
1847 if (dest)
1848 {
1849 ISzAlloc_Free(me->allocMid, dest);
1850 coder->outBuf = NULL;
1851 coder->outBufSize = 0;
1852 }
1853 {
1854 size_t outPreSize = coder->outPreSize;
1855 if (outPreSize == 0)
1856 outPreSize = 1;
1857 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1858 }
1859 if (!dest)
1860 return SZ_ERROR_MEM;
1861 coder->outBuf = dest;
1862 coder->outBufSize = coder->outPreSize;
1863
1864 if (coder->outBufSize > me->unpackBlockMaxSize)
1865 me->unpackBlockMaxSize = coder->outBufSize;
1866 }
1867
1868 // return SZ_ERROR_MEM;
1869
1870 XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1871
1872 {
1873 SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1874 // res = SZ_ERROR_UNSUPPORTED; // to test
1875 coder->codeRes = res;
1876 if (res != SZ_OK)
1877 {
1878 // if (res == SZ_ERROR_MEM) return res;
1879 if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1880 return S_OK;
1881 return res;
1882 }
1883 }
1884
1885 return SZ_OK;
1886}
1887
1888
1889static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1890 const Byte *src, size_t srcSize, int srcFinished,
1891 // int finished, int blockFinished,
1892 UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1893{
1894 CXzDecMt *me = (CXzDecMt *)pp;
1895 CXzDecMtThread *coder = &me->coders[coderIndex];
1896
1897 *inCodePos = coder->inCodeSize;
1898 *outCodePos = coder->outCodeSize;
1899 *stop = True;
1900
1901 if (coder->inCodeSize < coder->inPreHeaderSize)
1902 {
1903 UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
1904 size_t step = srcSize;
1905 if (step > rem)
1906 step = (size_t)rem;
1907 src += step;
1908 srcSize -= step;
1909 coder->inCodeSize += step;
1910 if (coder->inCodeSize < coder->inPreHeaderSize)
1911 {
1912 *stop = False;
1913 return SZ_OK;
1914 }
1915 }
1916
1917 if (!coder->dec.headerParsedOk)
1918 return SZ_OK;
1919 if (!coder->outBuf)
1920 return SZ_OK;
1921
1922 if (coder->codeRes == SZ_OK)
1923 {
1924 ECoderStatus status;
1925 SRes res;
1926 size_t srcProcessed = srcSize;
1927 size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1928
1929 // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1930
1931 res = XzUnpacker_Code(&coder->dec,
1932 NULL, &outSizeCur,
1933 src, &srcProcessed, srcFinished,
1934 // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1935 CODER_FINISH_END,
1936 &status);
1937
1938 // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1939
1940 coder->codeRes = res;
1941 coder->status = status;
1942 coder->inCodeSize += srcProcessed;
1943 coder->outCodeSize = coder->dec.outDataWritten;
1944 *inCodePos = coder->inCodeSize;
1945 *outCodePos = coder->outCodeSize;
1946
1947 if (res == SZ_OK)
1948 {
1949 if (srcProcessed == srcSize)
1950 *stop = False;
1951 return SZ_OK;
1952 }
1953 }
1954
1955 if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1956 {
1957 *inCodePos = coder->inPreSize;
1958 *outCodePos = coder->outPreSize;
1959 return S_OK;
1960 }
1961 return coder->codeRes;
1962}
1963
1964
1965#define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1966
1967static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1968 BoolInt needWriteToStream,
1969 const Byte *src, size_t srcSize,
1970 // int srcFinished,
1971 BoolInt *needContinue,
1972 BoolInt *canRecode)
1973{
1974 CXzDecMt *me = (CXzDecMt *)pp;
1975 const CXzDecMtThread *coder = &me->coders[coderIndex];
1976
1977 // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1978
1979 *needContinue = False;
1980 *canRecode = True;
1981
1982 if (!needWriteToStream)
1983 return SZ_OK;
1984
1985 if (!coder->dec.headerParsedOk || !coder->outBuf)
1986 {
1987 if (me->finishedDecoderIndex < 0)
1988 me->finishedDecoderIndex = coderIndex;
1989 return SZ_OK;
1990 }
1991
1992 if (me->finishedDecoderIndex >= 0)
1993 return SZ_OK;
1994
1995 me->mtc.inProcessed += coder->inCodeSize;
1996
1997 *canRecode = False;
1998
1999 {
2000 SRes res;
2001 size_t size = coder->outCodeSize;
2002 Byte *data = coder->outBuf;
2003
2004 // we use in me->dec: sha, numBlocks, indexSize
2005
2006 if (!me->isBlockHeaderState_Write)
2007 {
2008 XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2009 me->dec.decodeOnlyOneBlock = False;
2010 me->dec.numStartedStreams = coder->dec.numStartedStreams;
2011 me->dec.streamFlags = coder->streamFlags;
2012
2013 me->isBlockHeaderState_Write = True;
2014 }
2015
2016 me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2017 XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2018
2019 if (coder->outPreSize != size)
2020 {
2021 if (me->props.ignoreErrors)
2022 {
2023 memset(data + size, 0, coder->outPreSize - size);
2024 size = coder->outPreSize;
2025 }
2026 // me->numBadBlocks++;
2027 if (me->mainErrorCode == SZ_OK)
2028 {
2029 if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2030 me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2031 else
2032 me->mainErrorCode = SZ_ERROR_DATA;
2033 }
2034 }
2035
2036 if (me->writeRes != SZ_OK)
2037 return me->writeRes;
2038
2039 res = SZ_OK;
2040 {
2041 if (me->outSize_Defined)
2042 {
2043 const UInt64 rem = me->outSize - me->outProcessed;
2044 if (size > rem)
2045 size = (SizeT)rem;
2046 }
2047
2048 for (;;)
2049 {
2050 size_t cur = size;
2051 size_t written;
2052 if (cur > XZDECMT_STREAM_WRITE_STEP)
2053 cur = XZDECMT_STREAM_WRITE_STEP;
2054
2055 written = ISeqOutStream_Write(me->outStream, data, cur);
2056
2057 // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2058
2059 me->outProcessed += written;
2060 if (written != cur)
2061 {
2062 me->writeRes = SZ_ERROR_WRITE;
2063 res = me->writeRes;
2064 break;
2065 }
2066 data += cur;
2067 size -= cur;
2068 // PRF_STR_INT("Written size =", size);
2069 if (size == 0)
2070 break;
2071 res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2072 if (res != SZ_OK)
2073 break;
2074 }
2075 }
2076
2077 if (coder->codeRes != SZ_OK)
2078 if (!me->props.ignoreErrors)
2079 {
2080 me->finishedDecoderIndex = coderIndex;
2081 return res;
2082 }
2083
2084 RINOK(res);
2085
2086 if (coder->inPreSize != coder->inCodeSize
2087 || coder->blockPackTotal != coder->inCodeSize)
2088 {
2089 me->finishedDecoderIndex = coderIndex;
2090 return SZ_OK;
2091 }
2092
2093 if (coder->parseState != MTDEC_PARSE_END)
2094 {
2095 *needContinue = True;
2096 return SZ_OK;
2097 }
2098 }
2099
2100 // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2101 // so we can use mtc variables without lock
2102
2103 PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2104
2105 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2106 {
2107 CXzUnpacker *dec = &me->dec;
2108
2109 PRF_STR_INT("PostSingle", srcSize);
2110
2111 {
2112 size_t srcProcessed = srcSize;
2113 ECoderStatus status;
2114 size_t outSizeCur = 0;
2115 SRes res;
2116
2117 // dec->decodeOnlyOneBlock = False;
2118 dec->decodeToStreamSignature = True;
2119
2120 me->mainDecoderWasCalled = True;
2121
2122 if (coder->parsing_Truncated)
2123 {
2124 me->parsing_Truncated = True;
2125 return SZ_OK;
2126 }
2127
2128 res = XzUnpacker_Code(dec,
2129 NULL, &outSizeCur,
2130 src, &srcProcessed,
2131 me->mtc.readWasFinished, // srcFinished
2132 CODER_FINISH_END, // CODER_FINISH_ANY,
2133 &status);
2134
2135 me->status = status;
2136 me->codeRes = res;
2137
2138 me->mtc.inProcessed += srcProcessed;
2139 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2140
2141 if (res != SZ_OK)
2142 {
2143 return S_OK;
2144 // return res;
2145 }
2146
2147 if (dec->state == XZ_STATE_STREAM_HEADER)
2148 {
2149 *needContinue = True;
2150 me->isBlockHeaderState_Parse = False;
2151 me->isBlockHeaderState_Write = False;
2152 {
2153 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2154 if (!crossBuf)
2155 return SZ_ERROR_MEM;
2156 memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
2157 }
2158 me->mtc.crossStart = 0;
2159 me->mtc.crossEnd = srcSize - srcProcessed;
2160 return SZ_OK;
2161 }
2162
2163 if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2164 {
2165 return E_FAIL;
2166 }
2167
2168 if (me->mtc.readWasFinished)
2169 {
2170 return SZ_OK;
2171 }
2172 }
2173
2174 {
2175 size_t inPos;
2176 size_t inLim;
2177 const Byte *inData;
2178 UInt64 inProgressPrev = me->mtc.inProcessed;
2179
2180 // XzDecMt_Prepare_InBuf_ST(p);
2181 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2182 if (!crossBuf)
2183 return SZ_ERROR_MEM;
2184
2185 inPos = 0;
2186 inLim = 0;
2187 // outProcessed = 0;
2188
2189 inData = crossBuf;
2190
2191 for (;;)
2192 {
2193 SizeT inProcessed;
2194 SizeT outProcessed;
2195 ECoderStatus status;
2196 SRes res;
2197
2198 if (inPos == inLim)
2199 {
2200 if (!me->mtc.readWasFinished)
2201 {
2202 inPos = 0;
2203 inLim = me->mtc.inBufSize;
2204 me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
2205 me->mtc.readProcessed += inLim;
2206 if (inLim == 0 || me->mtc.readRes != SZ_OK)
2207 me->mtc.readWasFinished = True;
2208 }
2209 }
2210
2211 inProcessed = inLim - inPos;
2212 outProcessed = 0;
2213
2214 res = XzUnpacker_Code(dec,
2215 NULL, &outProcessed,
2216 inData + inPos, &inProcessed,
2217 (inProcessed == 0), // srcFinished
2218 CODER_FINISH_END, &status);
2219
2220 me->codeRes = res;
2221 me->status = status;
2222 inPos += inProcessed;
2223 me->mtc.inProcessed += inProcessed;
2224 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2225
2226 if (res != SZ_OK)
2227 {
2228 return S_OK;
2229 // return res;
2230 }
2231
2232 if (dec->state == XZ_STATE_STREAM_HEADER)
2233 {
2234 *needContinue = True;
2235 me->mtc.crossStart = inPos;
2236 me->mtc.crossEnd = inLim;
2237 me->isBlockHeaderState_Parse = False;
2238 me->isBlockHeaderState_Write = False;
2239 return SZ_OK;
2240 }
2241
2242 if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2243 return E_FAIL;
2244
2245 if (me->mtc.progress)
2246 {
2247 UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2248 if (inDelta >= (1 << 22))
2249 {
2250 RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2251 inProgressPrev = me->mtc.inProcessed;
2252 }
2253 }
2254 if (me->mtc.readWasFinished)
2255 return SZ_OK;
2256 }
2257 }
2258 }
2259}
2260
2261
2262#endif
2263
2264
2265
2266void XzStatInfo_Clear(CXzStatInfo *p)
2267{
2268 p->InSize = 0;
2269 p->OutSize = 0;
2270
2271 p->NumStreams = 0;
2272 p->NumBlocks = 0;
2273
2274 p->UnpackSize_Defined = False;
2275
2276 p->NumStreams_Defined = False;
2277 p->NumBlocks_Defined = False;
2278
2279 // p->IsArc = False;
2280 // p->UnexpectedEnd = False;
2281 // p->Unsupported = False;
2282 // p->HeadersError = False;
2283 // p->DataError = False;
2284 // p->CrcError = False;
2285
2286 p->DataAfterEnd = False;
2287 p->DecodingTruncated = False;
2288
2289 p->DecodeRes = SZ_OK;
2290 p->ReadRes = SZ_OK;
2291 p->ProgressRes = SZ_OK;
2292
2293 p->CombinedRes = SZ_OK;
2294 p->CombinedRes_Type = SZ_OK;
2295}
2296
2297
2298
2299
2300static SRes XzDecMt_Decode_ST(CXzDecMt *p
2301 #ifndef _7ZIP_ST
2302 , BoolInt tMode
2303 #endif
2304 , CXzStatInfo *stat)
2305{
2306 size_t outPos;
2307 size_t inPos, inLim;
2308 const Byte *inData;
2309 UInt64 inPrev, outPrev;
2310
2311 CXzUnpacker *dec;
2312
2313 #ifndef _7ZIP_ST
2314 if (tMode)
2315 {
2316 XzDecMt_FreeOutBufs(p);
2317 tMode = MtDec_PrepareRead(&p->mtc);
2318 }
2319 #endif
2320
2321 if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2322 {
2323 ISzAlloc_Free(p->allocMid, p->outBuf);
2324 p->outBufSize = 0;
2325 p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2326 if (!p->outBuf)
2327 return SZ_ERROR_MEM;
2328 p->outBufSize = p->props.outStep_ST;
2329 }
2330
2331 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2332 {
2333 ISzAlloc_Free(p->allocMid, p->inBuf);
2334 p->inBufSize = 0;
2335 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2336 if (!p->inBuf)
2337 return SZ_ERROR_MEM;
2338 p->inBufSize = p->props.inBufSize_ST;
2339 }
2340
2341 dec = &p->dec;
2342 dec->decodeToStreamSignature = False;
2343 // dec->decodeOnlyOneBlock = False;
2344
2345 XzUnpacker_SetOutBuf(dec, NULL, 0);
2346
2347 inPrev = p->inProcessed;
2348 outPrev = p->outProcessed;
2349
2350 inPos = 0;
2351 inLim = 0;
2352 inData = NULL;
2353 outPos = 0;
2354
2355 for (;;)
2356 {
2357 SizeT outSize;
2358 BoolInt finished;
2359 ECoderFinishMode finishMode;
2360 SizeT inProcessed;
2361 ECoderStatus status;
2362 SRes res;
2363
2364 SizeT outProcessed;
2365
2366
2367
2368 if (inPos == inLim)
2369 {
2370 #ifndef _7ZIP_ST
2371 if (tMode)
2372 {
2373 inData = MtDec_Read(&p->mtc, &inLim);
2374 inPos = 0;
2375 if (inData)
2376 continue;
2377 tMode = False;
2378 inLim = 0;
2379 }
2380 #endif
2381
2382 if (!p->readWasFinished)
2383 {
2384 inPos = 0;
2385 inLim = p->inBufSize;
2386 inData = p->inBuf;
2387 p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2388 p->readProcessed += inLim;
2389 if (inLim == 0 || p->readRes != SZ_OK)
2390 p->readWasFinished = True;
2391 }
2392 }
2393
2394 outSize = p->props.outStep_ST - outPos;
2395
2396 finishMode = CODER_FINISH_ANY;
2397 if (p->outSize_Defined)
2398 {
2399 const UInt64 rem = p->outSize - p->outProcessed;
2400 if (outSize >= rem)
2401 {
2402 outSize = (SizeT)rem;
2403 if (p->finishMode)
2404 finishMode = CODER_FINISH_END;
2405 }
2406 }
2407
2408 inProcessed = inLim - inPos;
2409 outProcessed = outSize;
2410
2411 res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2412 inData + inPos, &inProcessed,
2413 (inPos == inLim), // srcFinished
2414 finishMode, &status);
2415
2416 p->codeRes = res;
2417 p->status = status;
2418
2419 inPos += inProcessed;
2420 outPos += outProcessed;
2421 p->inProcessed += inProcessed;
2422 p->outProcessed += outProcessed;
2423
2424 finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2425
2426 if (finished || outProcessed >= outSize)
2427 if (outPos != 0)
2428 {
2429 size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2430 p->outProcessed += written;
2431 if (written != outPos)
2432 {
2433 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2434 return SZ_ERROR_WRITE;
2435 }
2436 outPos = 0;
2437 }
2438
2439 if (p->progress && res == SZ_OK)
2440 {
2441 UInt64 inDelta = p->inProcessed - inPrev;
2442 UInt64 outDelta = p->outProcessed - outPrev;
2443 if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
2444 {
2445 res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2446 if (res != SZ_OK)
2447 {
2448 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2449 stat->ProgressRes = res;
2450 return res;
2451 }
2452 inPrev = p->inProcessed;
2453 outPrev = p->outProcessed;
2454 }
2455 }
2456
2457 if (finished)
2458 return res;
2459 }
2460}
2461
2462static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
2463 int finishMode,
2464 UInt64 readProcessed, UInt64 inProcessed,
2465 SRes res, ECoderStatus status,
2466 BoolInt decodingTruncated,
2467 CXzStatInfo *stat)
2468{
2469 UInt64 extraSize;
2470
2471 stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2472 stat->InSize = inProcessed;
2473 stat->NumStreams = dec->numStartedStreams;
2474 stat->NumBlocks = dec->numTotalBlocks;
2475
2476 stat->UnpackSize_Defined = True;
2477 stat->NumStreams_Defined = True;
2478 stat->NumBlocks_Defined = True;
2479
2480 extraSize = XzUnpacker_GetExtraSize(dec);
2481
2482 if (res == SZ_OK)
2483 {
2484 if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2485 {
2486 // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2487 extraSize = 0;
2488 if (!XzUnpacker_IsStreamWasFinished(dec))
2489 res = SZ_ERROR_INPUT_EOF;
2490 }
2491 else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2492 res = SZ_ERROR_DATA;
2493 }
2494 else if (res == SZ_ERROR_NO_ARCHIVE)
2495 {
2496 /*
2497 SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2498 XZ_STATE_STREAM_HEADER - if bad signature or bad CRC
2499 XZ_STATE_STREAM_PADDING - if non-zero padding data
2500 extraSize / inProcessed don't include "bad" byte
2501 */
2502 if (inProcessed != extraSize) // if good streams before error
2503 if (extraSize != 0 || readProcessed != inProcessed)
2504 {
2505 stat->DataAfterEnd = True;
2506 // there is some good xz stream before. So we set SZ_OK
2507 res = SZ_OK;
2508 }
2509 }
2510
2511 stat->DecodeRes = res;
2512
2513 stat->InSize -= extraSize;
2514 return res;
2515}
2516
2517
2518SRes XzDecMt_Decode(CXzDecMtHandle pp,
2519 const CXzDecMtProps *props,
2520 const UInt64 *outDataSize, int finishMode,
2521 ISeqOutStream *outStream,
2522 // Byte *outBuf, size_t *outBufSize,
2523 ISeqInStream *inStream,
2524 // const Byte *inData, size_t inDataSize,
2525 CXzStatInfo *stat,
2526 int *isMT,
2527 ICompressProgress *progress)
2528{
2529 CXzDecMt *p = (CXzDecMt *)pp;
2530 #ifndef _7ZIP_ST
2531 BoolInt tMode;
2532 #endif
2533
2534 XzStatInfo_Clear(stat);
2535
2536 p->props = *props;
2537
2538 p->inStream = inStream;
2539 p->outStream = outStream;
2540 p->progress = progress;
2541 // p->stat = stat;
2542
2543 p->outSize = 0;
2544 p->outSize_Defined = False;
2545 if (outDataSize)
2546 {
2547 p->outSize_Defined = True;
2548 p->outSize = *outDataSize;
2549 }
2550
2551 p->finishMode = finishMode;
2552
2553 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2554
2555 p->writeRes = SZ_OK;
2556 p->outProcessed = 0;
2557 p->inProcessed = 0;
2558 p->readProcessed = 0;
2559 p->readWasFinished = False;
2560
2561 p->codeRes = 0;
2562 p->status = CODER_STATUS_NOT_SPECIFIED;
2563
2564 XzUnpacker_Init(&p->dec);
2565
2566 *isMT = False;
2567
2568 /*
2569 p->outBuf = NULL;
2570 p->outBufSize = 0;
2571 if (!outStream)
2572 {
2573 p->outBuf = outBuf;
2574 p->outBufSize = *outBufSize;
2575 *outBufSize = 0;
2576 }
2577 */
2578
2579
2580 #ifndef _7ZIP_ST
2581
2582 p->isBlockHeaderState_Parse = False;
2583 p->isBlockHeaderState_Write = False;
2584 // p->numBadBlocks = 0;
2585 p->mainErrorCode = SZ_OK;
2586 p->mainDecoderWasCalled = False;
2587
2588 tMode = False;
2589
2590 if (p->props.numThreads > 1)
2591 {
2592 IMtDecCallback vt;
2593
2594 // we just free ST buffers here
2595 // but we still keep state variables, that was set in XzUnpacker_Init()
2596 XzDecMt_FreeSt(p);
2597
2598 p->outProcessed_Parse = 0;
2599 p->parsing_Truncated = False;
2600
2601 p->numStreams = 0;
2602 p->numTotalBlocks = 0;
2603 p->numBlocks = 0;
2604 p->finishedDecoderIndex = -1;
2605
2606 if (!p->mtc_WasConstructed)
2607 {
2608 p->mtc_WasConstructed = True;
2609 MtDec_Construct(&p->mtc);
2610 }
2611
2612 p->mtc.mtCallback = &vt;
2613 p->mtc.mtCallbackObject = p;
2614
2615 p->mtc.progress = progress;
2616 p->mtc.inStream = inStream;
2617 p->mtc.alloc = &p->alignOffsetAlloc.vt;
2618 // p->mtc.inData = inData;
2619 // p->mtc.inDataSize = inDataSize;
2620 p->mtc.inBufSize = p->props.inBufSize_MT;
2621 // p->mtc.inBlockMax = p->props.inBlockMax;
2622 p->mtc.numThreadsMax = p->props.numThreads;
2623
2624 *isMT = True;
2625
2626 vt.Parse = XzDecMt_Callback_Parse;
2627 vt.PreCode = XzDecMt_Callback_PreCode;
2628 vt.Code = XzDecMt_Callback_Code;
2629 vt.Write = XzDecMt_Callback_Write;
2630
2631 {
2632 BoolInt needContinue;
2633
2634 SRes res = MtDec_Code(&p->mtc);
2635
2636 stat->InSize = p->mtc.inProcessed;
2637
2638 p->inProcessed = p->mtc.inProcessed;
2639 p->readRes = p->mtc.readRes;
2640 p->readWasFinished = p->mtc.readWasFinished;
2641 p->readProcessed = p->mtc.readProcessed;
2642
2643 tMode = True;
2644 needContinue = False;
2645
2646 if (res == SZ_OK)
2647 {
2648 if (p->mtc.mtProgress.res != SZ_OK)
2649 {
2650 res = p->mtc.mtProgress.res;
2651 stat->ProgressRes = res;
2652 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2653 }
2654 else
2655 needContinue = p->mtc.needContinue;
2656 }
2657
2658 if (!needContinue)
2659 {
2660 SRes codeRes;
2661 BoolInt truncated = False;
2662 ECoderStatus status;
2663 CXzUnpacker *dec;
2664
2665 stat->OutSize = p->outProcessed;
2666
2667 if (p->finishedDecoderIndex >= 0)
2668 {
2669 CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2670 codeRes = coder->codeRes;
2671 dec = &coder->dec;
2672 status = coder->status;
2673 }
2674 else if (p->mainDecoderWasCalled)
2675 {
2676 codeRes = p->codeRes;
2677 dec = &p->dec;
2678 status = p->status;
2679 truncated = p->parsing_Truncated;
2680 }
2681 else
2682 return E_FAIL;
2683
2684 XzStatInfo_SetStat(dec, p->finishMode,
2685 p->mtc.readProcessed, p->mtc.inProcessed,
2686 codeRes, status,
2687 truncated,
2688 stat);
2689
2690 if (res == SZ_OK)
2691 {
2692 if (p->writeRes != SZ_OK)
2693 {
2694 res = p->writeRes;
2695 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2696 }
2697 else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
2698 {
2699 res = p->mtc.readRes;
2700 stat->ReadRes = res;
2701 stat->CombinedRes_Type = SZ_ERROR_READ;
2702 }
2703 else if (p->mainErrorCode != SZ_OK)
2704 {
2705 res = p->mainErrorCode;
2706 }
2707 }
2708
2709 stat->CombinedRes = res;
2710 if (stat->CombinedRes_Type == SZ_OK)
2711 stat->CombinedRes_Type = res;
2712 return res;
2713 }
2714
2715 PRF_STR("----- decoding ST -----");
2716 }
2717 }
2718
2719 #endif
2720
2721
2722 *isMT = False;
2723
2724 {
2725 SRes res = XzDecMt_Decode_ST(p
2726 #ifndef _7ZIP_ST
2727 , tMode
2728 #endif
2729 , stat
2730 );
2731
2732 XzStatInfo_SetStat(&p->dec,
2733 p->finishMode,
2734 p->readProcessed, p->inProcessed,
2735 p->codeRes, p->status,
2736 False, // truncated
2737 stat);
2738
2739 if (res == SZ_OK)
2740 {
2741 /*
2742 if (p->writeRes != SZ_OK)
2743 {
2744 res = p->writeRes;
2745 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2746 }
2747 else
2748 */
2749 if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
2750 {
2751 res = p->readRes;
2752 stat->ReadRes = res;
2753 stat->CombinedRes_Type = SZ_ERROR_READ;
2754 }
2755 #ifndef _7ZIP_ST
2756 else if (p->mainErrorCode != SZ_OK)
2757 res = p->mainErrorCode;
2758 #endif
2759 }
2760
2761 stat->CombinedRes = res;
2762 if (stat->CombinedRes_Type == SZ_OK)
2763 stat->CombinedRes_Type = res;
2764 return res;
2765 }
2766}