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