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