1 /* XzDec.c -- Xz Decode 2 2018-12-29 : 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 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 91 static void BraState_Free(void *pp, ISzAllocPtr alloc) 92 { 93 ISzAlloc_Free(alloc, pp); 94 } 95 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 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 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 174 static SRes BraState_Code2(void *pp, 175 Byte *dest, SizeT *destLen, 176 const Byte *src, SizeT *srcLen, int srcWasFinished, 177 ECoderFinishMode finishMode, 178 // int *wasFinished 179 ECoderStatus *status) 180 { 181 CBraState *p = ((CBraState *)pp); 182 SizeT destRem = *destLen; 183 SizeT srcRem = *srcLen; 184 UNUSED_VAR(finishMode); 185 186 *destLen = 0; 187 *srcLen = 0; 188 // *wasFinished = False; 189 *status = CODER_STATUS_NOT_FINISHED; 190 191 while (destRem > 0) 192 { 193 if (p->bufPos != p->bufConv) 194 { 195 size_t size = p->bufConv - p->bufPos; 196 if (size > destRem) 197 size = destRem; 198 memcpy(dest, p->buf + p->bufPos, size); 199 p->bufPos += size; 200 *destLen += size; 201 dest += size; 202 destRem -= size; 203 continue; 204 } 205 206 p->bufTotal -= p->bufPos; 207 memmove(p->buf, p->buf + p->bufPos, p->bufTotal); 208 p->bufPos = 0; 209 p->bufConv = 0; 210 { 211 size_t size = BRA_BUF_SIZE - p->bufTotal; 212 if (size > srcRem) 213 size = srcRem; 214 memcpy(p->buf + p->bufTotal, src, size); 215 *srcLen += size; 216 src += size; 217 srcRem -= size; 218 p->bufTotal += size; 219 } 220 if (p->bufTotal == 0) 221 break; 222 223 p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal); 224 225 if (p->bufConv == 0) 226 { 227 if (!srcWasFinished) 228 break; 229 p->bufConv = p->bufTotal; 230 } 231 } 232 233 if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) 234 { 235 *status = CODER_STATUS_FINISHED_WITH_MARK; 236 // *wasFinished = 1; 237 } 238 239 return SZ_OK; 240 } 241 242 243 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc) 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 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 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 287 static void SbState_Init(void *pp) 288 { 289 SbDec_Init((CSbDec *)pp); 290 } 291 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 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 BoolInt outBufMode; 345 } CLzma2Dec_Spec; 346 347 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 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 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 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 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 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 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 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 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 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 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 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 BoolInt processed = False; 641 BoolInt allFinished = True; 642 SRes resMain = SZ_OK; 643 unsigned i; 644 645 p->status = CODER_STATUS_NOT_FINISHED; 646 /* 647 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) 648 break; 649 */ 650 651 for (i = 0; i < p->numCoders; i++) 652 { 653 SRes res; 654 IStateCoder *coder = &p->coders[i]; 655 Byte *dest2; 656 SizeT destLen2, srcLen2; // destLen2_Orig; 657 const Byte *src2; 658 int srcFinished2; 659 int encodingWasFinished; 660 ECoderStatus status2; 661 662 if (i == 0) 663 { 664 src2 = src; 665 srcLen2 = srcLenOrig - *srcLen; 666 srcFinished2 = srcWasFinished; 667 } 668 else 669 { 670 size_t k = i - 1; 671 src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; 672 srcLen2 = p->size[k] - p->pos[k]; 673 srcFinished2 = p->finished[k]; 674 } 675 676 if (i == p->numCoders - 1) 677 { 678 dest2 = dest; 679 destLen2 = destLenOrig - *destLen; 680 } 681 else 682 { 683 if (p->pos[i] != p->size[i]) 684 continue; 685 dest2 = p->buf + (CODER_BUF_SIZE * i); 686 destLen2 = CODER_BUF_SIZE; 687 } 688 689 // destLen2_Orig = destLen2; 690 691 if (p->results[i] != SZ_OK) 692 { 693 if (resMain == SZ_OK) 694 resMain = p->results[i]; 695 continue; 696 } 697 698 res = coder->Code2(coder->p, 699 dest2, &destLen2, 700 src2, &srcLen2, srcFinished2, 701 finishMode, 702 // &encodingWasFinished, 703 &status2); 704 705 if (res != SZ_OK) 706 { 707 p->results[i] = res; 708 if (resMain == SZ_OK) 709 resMain = res; 710 } 711 712 encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); 713 714 if (!encodingWasFinished) 715 { 716 allFinished = False; 717 if (p->numCoders == 1 && res == SZ_OK) 718 p->status = status2; 719 } 720 721 if (i == 0) 722 { 723 *srcLen += srcLen2; 724 src += srcLen2; 725 } 726 else 727 p->pos[(size_t)i - 1] += srcLen2; 728 729 if (i == p->numCoders - 1) 730 { 731 *destLen += destLen2; 732 dest += destLen2; 733 } 734 else 735 { 736 p->size[i] = destLen2; 737 p->pos[i] = 0; 738 p->finished[i] = encodingWasFinished; 739 } 740 741 if (destLen2 != 0 || srcLen2 != 0) 742 processed = True; 743 } 744 745 if (!processed) 746 { 747 if (allFinished) 748 p->status = CODER_STATUS_FINISHED_WITH_MARK; 749 return resMain; 750 } 751 } 752 } 753 754 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 764 static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) 765 { 766 return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) 767 && GetUi32(buf) == CrcCalc(buf + 4, 6) 768 && flags == GetBe16(buf + 8) 769 && buf[10] == XZ_FOOTER_SIG_0 770 && buf[11] == XZ_FOOTER_SIG_1; 771 } 772 773 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ 774 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ 775 if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } 776 777 778 static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p) 779 { 780 unsigned numFilters = XzBlock_GetNumFilters(p) - 1; 781 unsigned i; 782 { 783 const CXzFilter *f = &p->filters[numFilters]; 784 if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) 785 return False; 786 } 787 788 for (i = 0; i < numFilters; i++) 789 { 790 const CXzFilter *f = &p->filters[i]; 791 if (f->id == XZ_ID_Delta) 792 { 793 if (f->propsSize != 1) 794 return False; 795 } 796 else if (f->id < XZ_ID_Delta 797 || f->id > XZ_ID_SPARC 798 || (f->propsSize != 0 && f->propsSize != 4)) 799 return False; 800 } 801 return True; 802 } 803 804 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 866 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) 867 { 868 unsigned i; 869 BoolInt needReInit = True; 870 unsigned numFilters = XzBlock_GetNumFilters(block); 871 872 if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) 873 { 874 needReInit = False; 875 for (i = 0; i < numFilters; i++) 876 if (p->ids[i] != block->filters[numFilters - 1 - i].id) 877 { 878 needReInit = True; 879 break; 880 } 881 } 882 883 // p->SingleBufMode = (outBuf != NULL); 884 p->outBuf = outBuf; 885 p->outBufSize = outBufSize; 886 887 // p->SingleBufMode = False; 888 // outBuf = NULL; 889 890 if (needReInit) 891 { 892 MixCoder_Free(p); 893 for (i = 0; i < numFilters; i++) 894 { 895 RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)); 896 } 897 p->numCoders = numFilters; 898 } 899 else 900 { 901 RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)); 902 } 903 904 for (i = 0; i < numFilters; i++) 905 { 906 const CXzFilter *f = &block->filters[numFilters - 1 - i]; 907 IStateCoder *sc = &p->coders[i]; 908 RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); 909 } 910 911 MixCoder_Init(p); 912 return SZ_OK; 913 } 914 915 916 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 936 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) 937 { 938 p->outBuf = outBuf; 939 p->outBufSize = outBufSize; 940 } 941 942 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 952 void XzUnpacker_Free(CXzUnpacker *p) 953 { 954 MixCoder_Free(&p->decoder); 955 } 956 957 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 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 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 BoolInt srcFinished2 = srcFinished; 1003 BoolInt destFinish = False; 1004 1005 if (p->block.packSize != (UInt64)(Int64)-1) 1006 { 1007 UInt64 rem = p->block.packSize - p->packSize; 1008 if (srcLen2 >= rem) 1009 { 1010 srcFinished2 = True; 1011 srcLen2 = (SizeT)rem; 1012 } 1013 if (rem == 0 && p->block.unpackSize == p->unpackSize) 1014 return SZ_ERROR_DATA; 1015 } 1016 1017 if (p->block.unpackSize != (UInt64)(Int64)-1) 1018 { 1019 UInt64 rem = p->block.unpackSize - p->unpackSize; 1020 if (destLen2 >= rem) 1021 { 1022 destFinish = True; 1023 finishMode2 = CODER_FINISH_END; 1024 destLen2 = (SizeT)rem; 1025 } 1026 } 1027 1028 /* 1029 if (srcLen2 == 0 && destLen2 == 0) 1030 { 1031 *status = CODER_STATUS_NOT_FINISHED; 1032 return SZ_OK; 1033 } 1034 */ 1035 1036 { 1037 res = MixCoder_Code(&p->decoder, 1038 (p->outBuf ? NULL : dest), &destLen2, destFinish, 1039 src, &srcLen2, srcFinished2, 1040 finishMode2); 1041 1042 *status = p->decoder.status; 1043 XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); 1044 if (!p->outBuf) 1045 dest += destLen2; 1046 p->outDataWritten += destLen2; 1047 } 1048 1049 (*srcLen) += srcLen2; 1050 src += srcLen2; 1051 p->packSize += srcLen2; 1052 (*destLen) += destLen2; 1053 p->unpackSize += destLen2; 1054 1055 RINOK(res); 1056 1057 if (*status != CODER_STATUS_FINISHED_WITH_MARK) 1058 { 1059 if (p->block.packSize == p->packSize 1060 && *status == CODER_STATUS_NEEDS_MORE_INPUT) 1061 { 1062 PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT"); 1063 *status = CODER_STATUS_NOT_SPECIFIED; 1064 return SZ_ERROR_DATA; 1065 } 1066 1067 return SZ_OK; 1068 } 1069 { 1070 XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); 1071 p->state = XZ_STATE_BLOCK_FOOTER; 1072 p->pos = 0; 1073 p->alignPos = 0; 1074 *status = CODER_STATUS_NOT_SPECIFIED; 1075 1076 if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) 1077 || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) 1078 { 1079 PRF_STR("ERROR: block.size mismatch"); 1080 return SZ_ERROR_DATA; 1081 } 1082 } 1083 // continue; 1084 } 1085 1086 srcRem = srcLenOrig - *srcLen; 1087 1088 // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes 1089 if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) 1090 { 1091 *status = CODER_STATUS_NEEDS_MORE_INPUT; 1092 return SZ_OK; 1093 } 1094 1095 switch (p->state) 1096 { 1097 case XZ_STATE_STREAM_HEADER: 1098 { 1099 if (p->pos < XZ_STREAM_HEADER_SIZE) 1100 { 1101 if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) 1102 return SZ_ERROR_NO_ARCHIVE; 1103 if (p->decodeToStreamSignature) 1104 return SZ_OK; 1105 p->buf[p->pos++] = *src++; 1106 (*srcLen)++; 1107 } 1108 else 1109 { 1110 RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); 1111 p->numStartedStreams++; 1112 p->indexSize = 0; 1113 p->numBlocks = 0; 1114 Sha256_Init(&p->sha); 1115 p->state = XZ_STATE_BLOCK_HEADER; 1116 p->pos = 0; 1117 } 1118 break; 1119 } 1120 1121 case XZ_STATE_BLOCK_HEADER: 1122 { 1123 if (p->pos == 0) 1124 { 1125 p->buf[p->pos++] = *src++; 1126 (*srcLen)++; 1127 if (p->buf[0] == 0) 1128 { 1129 if (p->decodeOnlyOneBlock) 1130 return SZ_ERROR_DATA; 1131 p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); 1132 p->indexPos = p->indexPreSize; 1133 p->indexSize += p->indexPreSize; 1134 Sha256_Final(&p->sha, p->shaDigest); 1135 Sha256_Init(&p->sha); 1136 p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); 1137 p->state = XZ_STATE_STREAM_INDEX; 1138 break; 1139 } 1140 p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; 1141 break; 1142 } 1143 1144 if (p->pos != p->blockHeaderSize) 1145 { 1146 UInt32 cur = p->blockHeaderSize - p->pos; 1147 if (cur > srcRem) 1148 cur = (UInt32)srcRem; 1149 memcpy(p->buf + p->pos, src, cur); 1150 p->pos += cur; 1151 (*srcLen) += cur; 1152 src += cur; 1153 } 1154 else 1155 { 1156 RINOK(XzBlock_Parse(&p->block, p->buf)); 1157 if (!XzBlock_AreSupportedFilters(&p->block)) 1158 return SZ_ERROR_UNSUPPORTED; 1159 p->numTotalBlocks++; 1160 p->state = XZ_STATE_BLOCK; 1161 p->packSize = 0; 1162 p->unpackSize = 0; 1163 XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); 1164 if (p->parseMode) 1165 { 1166 p->headerParsedOk = True; 1167 return SZ_OK; 1168 } 1169 RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)); 1170 } 1171 break; 1172 } 1173 1174 case XZ_STATE_BLOCK_FOOTER: 1175 { 1176 if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) 1177 { 1178 if (srcRem == 0) 1179 { 1180 *status = CODER_STATUS_NEEDS_MORE_INPUT; 1181 return SZ_OK; 1182 } 1183 (*srcLen)++; 1184 p->alignPos++; 1185 if (*src++ != 0) 1186 return SZ_ERROR_CRC; 1187 } 1188 else 1189 { 1190 UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); 1191 UInt32 cur = checkSize - p->pos; 1192 if (cur != 0) 1193 { 1194 if (srcRem == 0) 1195 { 1196 *status = CODER_STATUS_NEEDS_MORE_INPUT; 1197 return SZ_OK; 1198 } 1199 if (cur > srcRem) 1200 cur = (UInt32)srcRem; 1201 memcpy(p->buf + p->pos, src, cur); 1202 p->pos += cur; 1203 (*srcLen) += cur; 1204 src += cur; 1205 if (checkSize != p->pos) 1206 break; 1207 } 1208 { 1209 Byte digest[XZ_CHECK_SIZE_MAX]; 1210 p->state = XZ_STATE_BLOCK_HEADER; 1211 p->pos = 0; 1212 if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) 1213 return SZ_ERROR_CRC; 1214 if (p->decodeOnlyOneBlock) 1215 { 1216 *status = CODER_STATUS_FINISHED_WITH_MARK; 1217 return SZ_OK; 1218 } 1219 } 1220 } 1221 break; 1222 } 1223 1224 case XZ_STATE_STREAM_INDEX: 1225 { 1226 if (p->pos < p->indexPreSize) 1227 { 1228 (*srcLen)++; 1229 if (*src++ != p->buf[p->pos++]) 1230 return SZ_ERROR_CRC; 1231 } 1232 else 1233 { 1234 if (p->indexPos < p->indexSize) 1235 { 1236 UInt64 cur = p->indexSize - p->indexPos; 1237 if (srcRem > cur) 1238 srcRem = (SizeT)cur; 1239 p->crc = CrcUpdate(p->crc, src, srcRem); 1240 Sha256_Update(&p->sha, src, srcRem); 1241 (*srcLen) += srcRem; 1242 src += srcRem; 1243 p->indexPos += srcRem; 1244 } 1245 else if ((p->indexPos & 3) != 0) 1246 { 1247 Byte b = *src++; 1248 p->crc = CRC_UPDATE_BYTE(p->crc, b); 1249 (*srcLen)++; 1250 p->indexPos++; 1251 p->indexSize++; 1252 if (b != 0) 1253 return SZ_ERROR_CRC; 1254 } 1255 else 1256 { 1257 Byte digest[SHA256_DIGEST_SIZE]; 1258 p->state = XZ_STATE_STREAM_INDEX_CRC; 1259 p->indexSize += 4; 1260 p->pos = 0; 1261 Sha256_Final(&p->sha, digest); 1262 if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) 1263 return SZ_ERROR_CRC; 1264 } 1265 } 1266 break; 1267 } 1268 1269 case XZ_STATE_STREAM_INDEX_CRC: 1270 { 1271 if (p->pos < 4) 1272 { 1273 (*srcLen)++; 1274 p->buf[p->pos++] = *src++; 1275 } 1276 else 1277 { 1278 p->state = XZ_STATE_STREAM_FOOTER; 1279 p->pos = 0; 1280 if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf)) 1281 return SZ_ERROR_CRC; 1282 } 1283 break; 1284 } 1285 1286 case XZ_STATE_STREAM_FOOTER: 1287 { 1288 UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; 1289 if (cur > srcRem) 1290 cur = (UInt32)srcRem; 1291 memcpy(p->buf + p->pos, src, cur); 1292 p->pos += cur; 1293 (*srcLen) += cur; 1294 src += cur; 1295 if (p->pos == XZ_STREAM_FOOTER_SIZE) 1296 { 1297 p->state = XZ_STATE_STREAM_PADDING; 1298 p->numFinishedStreams++; 1299 p->padSize = 0; 1300 if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) 1301 return SZ_ERROR_CRC; 1302 } 1303 break; 1304 } 1305 1306 case XZ_STATE_STREAM_PADDING: 1307 { 1308 if (*src != 0) 1309 { 1310 if (((UInt32)p->padSize & 3) != 0) 1311 return SZ_ERROR_NO_ARCHIVE; 1312 p->pos = 0; 1313 p->state = XZ_STATE_STREAM_HEADER; 1314 } 1315 else 1316 { 1317 (*srcLen)++; 1318 src++; 1319 p->padSize++; 1320 } 1321 break; 1322 } 1323 1324 case XZ_STATE_BLOCK: break; /* to disable GCC warning */ 1325 } 1326 } 1327 /* 1328 if (p->state == XZ_STATE_FINISHED) 1329 *status = CODER_STATUS_FINISHED_WITH_MARK; 1330 return SZ_OK; 1331 */ 1332 } 1333 1334 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 1349 BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p) 1350 { 1351 return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); 1352 } 1353 1354 BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) 1355 { 1356 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); 1357 } 1358 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 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 BoolInt skipMode; 1427 // BoolInt finishedWithMark; 1428 EMtDecParseState parseState; 1429 BoolInt parsing_Truncated; 1430 BoolInt atBlockHeader; 1431 CXzStreamFlags streamFlags; 1432 // UInt64 numFinishedStreams 1433 UInt64 numStreams; 1434 UInt64 numTotalBlocks; 1435 UInt64 numBlocks; 1436 1437 BoolInt dec_created; 1438 CXzUnpacker dec; 1439 1440 Byte mtPad[1 << 7]; 1441 } CXzDecMtThread; 1442 1443 #endif 1444 1445 1446 /* ---------- CXzDecMt ---------- */ 1447 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 BoolInt finishMode; 1462 BoolInt outSize_Defined; 1463 UInt64 outSize; 1464 1465 UInt64 outProcessed; 1466 UInt64 inProcessed; 1467 UInt64 readProcessed; 1468 BoolInt readWasFinished; 1469 SRes readRes; 1470 SRes writeRes; 1471 1472 Byte *outBuf; 1473 size_t outBufSize; 1474 Byte *inBuf; 1475 size_t inBufSize; 1476 1477 CXzUnpacker dec; 1478 1479 ECoderStatus status; 1480 SRes codeRes; 1481 1482 #ifndef _7ZIP_ST 1483 BoolInt mainDecoderWasCalled; 1484 // int statErrorDefined; 1485 int finishedDecoderIndex; 1486 1487 // global values that are used in Parse stage 1488 CXzStreamFlags streamFlags; 1489 // UInt64 numFinishedStreams 1490 UInt64 numStreams; 1491 UInt64 numTotalBlocks; 1492 UInt64 numBlocks; 1493 1494 // UInt64 numBadBlocks; 1495 SRes mainErrorCode; 1496 1497 BoolInt isBlockHeaderState_Parse; 1498 BoolInt isBlockHeaderState_Write; 1499 UInt64 outProcessed_Parse; 1500 BoolInt parsing_Truncated; 1501 1502 BoolInt mtc_WasConstructed; 1503 CMtDec mtc; 1504 CXzDecMtThread coders[MTDEC__THREADS_MAX]; 1505 #endif 1506 1507 } CXzDecMt; 1508 1509 1510 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 1529 XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); 1530 1531 p->unpackBlockMaxSize = 0; 1532 1533 XzDecMtProps_Init(&p->props); 1534 1535 #ifndef _7ZIP_ST 1536 p->mtc_WasConstructed = False; 1537 { 1538 unsigned i; 1539 for (i = 0; i < MTDEC__THREADS_MAX; i++) 1540 { 1541 CXzDecMtThread *coder = &p->coders[i]; 1542 coder->dec_created = False; 1543 coder->outBuf = NULL; 1544 coder->outBufSize = 0; 1545 } 1546 } 1547 #endif 1548 1549 return p; 1550 } 1551 1552 1553 #ifndef _7ZIP_ST 1554 1555 static void XzDecMt_FreeOutBufs(CXzDecMt *p) 1556 { 1557 unsigned i; 1558 for (i = 0; i < MTDEC__THREADS_MAX; i++) 1559 { 1560 CXzDecMtThread *coder = &p->coders[i]; 1561 if (coder->outBuf) 1562 { 1563 ISzAlloc_Free(p->allocMid, coder->outBuf); 1564 coder->outBuf = NULL; 1565 coder->outBufSize = 0; 1566 } 1567 } 1568 p->unpackBlockMaxSize = 0; 1569 } 1570 1571 #endif 1572 1573 1574 1575 static void XzDecMt_FreeSt(CXzDecMt *p) 1576 { 1577 XzUnpacker_Free(&p->dec); 1578 1579 if (p->outBuf) 1580 { 1581 ISzAlloc_Free(p->allocMid, p->outBuf); 1582 p->outBuf = NULL; 1583 } 1584 p->outBufSize = 0; 1585 1586 if (p->inBuf) 1587 { 1588 ISzAlloc_Free(p->allocMid, p->inBuf); 1589 p->inBuf = NULL; 1590 } 1591 p->inBufSize = 0; 1592 } 1593 1594 1595 void XzDecMt_Destroy(CXzDecMtHandle pp) 1596 { 1597 CXzDecMt *p = (CXzDecMt *)pp; 1598 1599 XzDecMt_FreeSt(p); 1600 1601 #ifndef _7ZIP_ST 1602 1603 if (p->mtc_WasConstructed) 1604 { 1605 MtDec_Destruct(&p->mtc); 1606 p->mtc_WasConstructed = False; 1607 } 1608 { 1609 unsigned i; 1610 for (i = 0; i < MTDEC__THREADS_MAX; i++) 1611 { 1612 CXzDecMtThread *t = &p->coders[i]; 1613 if (t->dec_created) 1614 { 1615 // we don't need to free dict here 1616 XzUnpacker_Free(&t->dec); 1617 t->dec_created = False; 1618 } 1619 } 1620 } 1621 XzDecMt_FreeOutBufs(p); 1622 1623 #endif 1624 1625 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); 1626 } 1627 1628 1629 1630 #ifndef _7ZIP_ST 1631 1632 static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) 1633 { 1634 CXzDecMt *me = (CXzDecMt *)obj; 1635 CXzDecMtThread *coder = &me->coders[coderIndex]; 1636 size_t srcSize = cc->srcSize; 1637 1638 cc->srcSize = 0; 1639 cc->outPos = 0; 1640 cc->state = MTDEC_PARSE_CONTINUE; 1641 1642 cc->canCreateNewThread = True; 1643 1644 if (cc->startCall) 1645 { 1646 coder->outPreSize = 0; 1647 coder->inPreSize = 0; 1648 coder->inPreHeaderSize = 0; 1649 coder->parseState = MTDEC_PARSE_CONTINUE; 1650 coder->parsing_Truncated = False; 1651 coder->skipMode = False; 1652 coder->codeRes = SZ_OK; 1653 coder->status = CODER_STATUS_NOT_SPECIFIED; 1654 coder->inCodeSize = 0; 1655 coder->outCodeSize = 0; 1656 1657 coder->numStreams = me->numStreams; 1658 coder->numTotalBlocks = me->numTotalBlocks; 1659 coder->numBlocks = me->numBlocks; 1660 1661 if (!coder->dec_created) 1662 { 1663 XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); 1664 coder->dec_created = True; 1665 } 1666 1667 XzUnpacker_Init(&coder->dec); 1668 1669 if (me->isBlockHeaderState_Parse) 1670 { 1671 coder->dec.streamFlags = me->streamFlags; 1672 coder->atBlockHeader = True; 1673 XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); 1674 } 1675 else 1676 { 1677 coder->atBlockHeader = False; 1678 me->isBlockHeaderState_Parse = True; 1679 } 1680 1681 coder->dec.numStartedStreams = me->numStreams; 1682 coder->dec.numTotalBlocks = me->numTotalBlocks; 1683 coder->dec.numBlocks = me->numBlocks; 1684 } 1685 1686 while (!coder->skipMode) 1687 { 1688 ECoderStatus status; 1689 SRes res; 1690 size_t srcSize2 = srcSize; 1691 size_t destSize = (size_t)0 - 1; 1692 1693 coder->dec.parseMode = True; 1694 coder->dec.headerParsedOk = False; 1695 1696 PRF_STR_INT("Parse", srcSize2); 1697 1698 res = XzUnpacker_Code(&coder->dec, 1699 NULL, &destSize, 1700 cc->src, &srcSize2, cc->srcFinished, 1701 CODER_FINISH_END, &status); 1702 1703 // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); 1704 1705 coder->codeRes = res; 1706 coder->status = status; 1707 cc->srcSize += srcSize2; 1708 srcSize -= srcSize2; 1709 coder->inPreHeaderSize += srcSize2; 1710 coder->inPreSize = coder->inPreHeaderSize; 1711 1712 if (res != SZ_OK) 1713 { 1714 cc->state = 1715 coder->parseState = MTDEC_PARSE_END; 1716 /* 1717 if (res == SZ_ERROR_MEM) 1718 return res; 1719 return SZ_OK; 1720 */ 1721 return; // res; 1722 } 1723 1724 if (coder->dec.headerParsedOk) 1725 { 1726 const CXzBlock *block = &coder->dec.block; 1727 if (XzBlock_HasUnpackSize(block) 1728 // && block->unpackSize <= me->props.outBlockMax 1729 && XzBlock_HasPackSize(block)) 1730 { 1731 { 1732 if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) 1733 { 1734 cc->state = MTDEC_PARSE_OVERFLOW; 1735 return; // SZ_OK; 1736 } 1737 } 1738 { 1739 UInt64 packSize = block->packSize; 1740 UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); 1741 UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); 1742 UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; 1743 // if (blockPackSum <= me->props.inBlockMax) 1744 // unpackBlockMaxSize 1745 { 1746 coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); 1747 coder->blockPackTotal = (size_t)blockPackSum; 1748 coder->outPreSize = (size_t)block->unpackSize; 1749 coder->streamFlags = coder->dec.streamFlags; 1750 me->streamFlags = coder->dec.streamFlags; 1751 coder->skipMode = True; 1752 break; 1753 } 1754 } 1755 } 1756 } 1757 else 1758 // if (coder->inPreSize <= me->props.inBlockMax) 1759 { 1760 if (!cc->srcFinished) 1761 return; // SZ_OK; 1762 cc->state = 1763 coder->parseState = MTDEC_PARSE_END; 1764 return; // SZ_OK; 1765 } 1766 cc->state = MTDEC_PARSE_OVERFLOW; 1767 return; // SZ_OK; 1768 } 1769 1770 // ---------- skipMode ---------- 1771 { 1772 UInt64 rem = coder->blockPackTotal - coder->inPreSize; 1773 size_t cur = srcSize; 1774 if (cur > rem) 1775 cur = (size_t)rem; 1776 cc->srcSize += cur; 1777 coder->inPreSize += cur; 1778 srcSize -= cur; 1779 1780 if (coder->inPreSize == coder->blockPackTotal) 1781 { 1782 if (srcSize == 0) 1783 { 1784 if (!cc->srcFinished) 1785 return; // SZ_OK; 1786 cc->state = MTDEC_PARSE_END; 1787 } 1788 else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block 1789 cc->state = MTDEC_PARSE_END; 1790 else 1791 { 1792 cc->state = MTDEC_PARSE_NEW; 1793 1794 { 1795 size_t blockMax = me->unpackBlockMaxSize; 1796 if (blockMax < coder->outPreSize) 1797 blockMax = coder->outPreSize; 1798 { 1799 UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; 1800 if (me->props.memUseMax < required) 1801 cc->canCreateNewThread = False; 1802 } 1803 } 1804 1805 if (me->outSize_Defined) 1806 { 1807 // next block can be zero size 1808 const UInt64 rem2 = me->outSize - me->outProcessed_Parse; 1809 if (rem2 < coder->outPreSize) 1810 { 1811 coder->parsing_Truncated = True; 1812 cc->state = MTDEC_PARSE_END; 1813 } 1814 me->outProcessed_Parse += coder->outPreSize; 1815 } 1816 } 1817 } 1818 else if (cc->srcFinished) 1819 cc->state = MTDEC_PARSE_END; 1820 else 1821 return; // SZ_OK; 1822 1823 coder->parseState = cc->state; 1824 cc->outPos = coder->outPreSize; 1825 1826 me->numStreams = coder->dec.numStartedStreams; 1827 me->numTotalBlocks = coder->dec.numTotalBlocks; 1828 me->numBlocks = coder->dec.numBlocks + 1; 1829 return; // SZ_OK; 1830 } 1831 } 1832 1833 1834 static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) 1835 { 1836 CXzDecMt *me = (CXzDecMt *)pp; 1837 CXzDecMtThread *coder = &me->coders[coderIndex]; 1838 Byte *dest; 1839 1840 if (!coder->dec.headerParsedOk) 1841 return SZ_OK; 1842 1843 dest = coder->outBuf; 1844 1845 if (!dest || coder->outBufSize < coder->outPreSize) 1846 { 1847 if (dest) 1848 { 1849 ISzAlloc_Free(me->allocMid, dest); 1850 coder->outBuf = NULL; 1851 coder->outBufSize = 0; 1852 } 1853 { 1854 size_t outPreSize = coder->outPreSize; 1855 if (outPreSize == 0) 1856 outPreSize = 1; 1857 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); 1858 } 1859 if (!dest) 1860 return SZ_ERROR_MEM; 1861 coder->outBuf = dest; 1862 coder->outBufSize = coder->outPreSize; 1863 1864 if (coder->outBufSize > me->unpackBlockMaxSize) 1865 me->unpackBlockMaxSize = coder->outBufSize; 1866 } 1867 1868 // return SZ_ERROR_MEM; 1869 1870 XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); 1871 1872 { 1873 SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); 1874 // res = SZ_ERROR_UNSUPPORTED; // to test 1875 coder->codeRes = res; 1876 if (res != SZ_OK) 1877 { 1878 // if (res == SZ_ERROR_MEM) return res; 1879 if (me->props.ignoreErrors && res != SZ_ERROR_MEM) 1880 return S_OK; 1881 return res; 1882 } 1883 } 1884 1885 return SZ_OK; 1886 } 1887 1888 1889 static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, 1890 const Byte *src, size_t srcSize, int srcFinished, 1891 // int finished, int blockFinished, 1892 UInt64 *inCodePos, UInt64 *outCodePos, int *stop) 1893 { 1894 CXzDecMt *me = (CXzDecMt *)pp; 1895 CXzDecMtThread *coder = &me->coders[coderIndex]; 1896 1897 *inCodePos = coder->inCodeSize; 1898 *outCodePos = coder->outCodeSize; 1899 *stop = True; 1900 1901 if (coder->inCodeSize < coder->inPreHeaderSize) 1902 { 1903 UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize; 1904 size_t step = srcSize; 1905 if (step > rem) 1906 step = (size_t)rem; 1907 src += step; 1908 srcSize -= step; 1909 coder->inCodeSize += step; 1910 if (coder->inCodeSize < coder->inPreHeaderSize) 1911 { 1912 *stop = False; 1913 return SZ_OK; 1914 } 1915 } 1916 1917 if (!coder->dec.headerParsedOk) 1918 return SZ_OK; 1919 if (!coder->outBuf) 1920 return SZ_OK; 1921 1922 if (coder->codeRes == SZ_OK) 1923 { 1924 ECoderStatus status; 1925 SRes res; 1926 size_t srcProcessed = srcSize; 1927 size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; 1928 1929 // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); 1930 1931 res = XzUnpacker_Code(&coder->dec, 1932 NULL, &outSizeCur, 1933 src, &srcProcessed, srcFinished, 1934 // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, 1935 CODER_FINISH_END, 1936 &status); 1937 1938 // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); 1939 1940 coder->codeRes = res; 1941 coder->status = status; 1942 coder->inCodeSize += srcProcessed; 1943 coder->outCodeSize = coder->dec.outDataWritten; 1944 *inCodePos = coder->inCodeSize; 1945 *outCodePos = coder->outCodeSize; 1946 1947 if (res == SZ_OK) 1948 { 1949 if (srcProcessed == srcSize) 1950 *stop = False; 1951 return SZ_OK; 1952 } 1953 } 1954 1955 if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) 1956 { 1957 *inCodePos = coder->inPreSize; 1958 *outCodePos = coder->outPreSize; 1959 return S_OK; 1960 } 1961 return coder->codeRes; 1962 } 1963 1964 1965 #define XZDECMT_STREAM_WRITE_STEP (1 << 24) 1966 1967 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, 1968 BoolInt needWriteToStream, 1969 const Byte *src, size_t srcSize, 1970 // int srcFinished, 1971 BoolInt *needContinue, 1972 BoolInt *canRecode) 1973 { 1974 CXzDecMt *me = (CXzDecMt *)pp; 1975 const CXzDecMtThread *coder = &me->coders[coderIndex]; 1976 1977 // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); 1978 1979 *needContinue = False; 1980 *canRecode = True; 1981 1982 if (!needWriteToStream) 1983 return SZ_OK; 1984 1985 if (!coder->dec.headerParsedOk || !coder->outBuf) 1986 { 1987 if (me->finishedDecoderIndex < 0) 1988 me->finishedDecoderIndex = coderIndex; 1989 return SZ_OK; 1990 } 1991 1992 if (me->finishedDecoderIndex >= 0) 1993 return SZ_OK; 1994 1995 me->mtc.inProcessed += coder->inCodeSize; 1996 1997 *canRecode = False; 1998 1999 { 2000 SRes res; 2001 size_t size = coder->outCodeSize; 2002 Byte *data = coder->outBuf; 2003 2004 // we use in me->dec: sha, numBlocks, indexSize 2005 2006 if (!me->isBlockHeaderState_Write) 2007 { 2008 XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); 2009 me->dec.decodeOnlyOneBlock = False; 2010 me->dec.numStartedStreams = coder->dec.numStartedStreams; 2011 me->dec.streamFlags = coder->streamFlags; 2012 2013 me->isBlockHeaderState_Write = True; 2014 } 2015 2016 me->dec.numTotalBlocks = coder->dec.numTotalBlocks; 2017 XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); 2018 2019 if (coder->outPreSize != size) 2020 { 2021 if (me->props.ignoreErrors) 2022 { 2023 memset(data + size, 0, coder->outPreSize - size); 2024 size = coder->outPreSize; 2025 } 2026 // me->numBadBlocks++; 2027 if (me->mainErrorCode == SZ_OK) 2028 { 2029 if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) 2030 me->mainErrorCode = SZ_ERROR_INPUT_EOF; 2031 else 2032 me->mainErrorCode = SZ_ERROR_DATA; 2033 } 2034 } 2035 2036 if (me->writeRes != SZ_OK) 2037 return me->writeRes; 2038 2039 res = SZ_OK; 2040 { 2041 if (me->outSize_Defined) 2042 { 2043 const UInt64 rem = me->outSize - me->outProcessed; 2044 if (size > rem) 2045 size = (SizeT)rem; 2046 } 2047 2048 for (;;) 2049 { 2050 size_t cur = size; 2051 size_t written; 2052 if (cur > XZDECMT_STREAM_WRITE_STEP) 2053 cur = XZDECMT_STREAM_WRITE_STEP; 2054 2055 written = ISeqOutStream_Write(me->outStream, data, cur); 2056 2057 // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); 2058 2059 me->outProcessed += written; 2060 if (written != cur) 2061 { 2062 me->writeRes = SZ_ERROR_WRITE; 2063 res = me->writeRes; 2064 break; 2065 } 2066 data += cur; 2067 size -= cur; 2068 // PRF_STR_INT("Written size =", size); 2069 if (size == 0) 2070 break; 2071 res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); 2072 if (res != SZ_OK) 2073 break; 2074 } 2075 } 2076 2077 if (coder->codeRes != SZ_OK) 2078 if (!me->props.ignoreErrors) 2079 { 2080 me->finishedDecoderIndex = coderIndex; 2081 return res; 2082 } 2083 2084 RINOK(res); 2085 2086 if (coder->inPreSize != coder->inCodeSize 2087 || coder->blockPackTotal != coder->inCodeSize) 2088 { 2089 me->finishedDecoderIndex = coderIndex; 2090 return SZ_OK; 2091 } 2092 2093 if (coder->parseState != MTDEC_PARSE_END) 2094 { 2095 *needContinue = True; 2096 return SZ_OK; 2097 } 2098 } 2099 2100 // (coder->state == MTDEC_PARSE_END) means that there are no other working threads 2101 // so we can use mtc variables without lock 2102 2103 PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed); 2104 2105 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; 2106 { 2107 CXzUnpacker *dec = &me->dec; 2108 2109 PRF_STR_INT("PostSingle", srcSize); 2110 2111 { 2112 size_t srcProcessed = srcSize; 2113 ECoderStatus status; 2114 size_t outSizeCur = 0; 2115 SRes res; 2116 2117 // dec->decodeOnlyOneBlock = False; 2118 dec->decodeToStreamSignature = True; 2119 2120 me->mainDecoderWasCalled = True; 2121 2122 if (coder->parsing_Truncated) 2123 { 2124 me->parsing_Truncated = True; 2125 return SZ_OK; 2126 } 2127 2128 res = XzUnpacker_Code(dec, 2129 NULL, &outSizeCur, 2130 src, &srcProcessed, 2131 me->mtc.readWasFinished, // srcFinished 2132 CODER_FINISH_END, // CODER_FINISH_ANY, 2133 &status); 2134 2135 me->status = status; 2136 me->codeRes = res; 2137 2138 me->mtc.inProcessed += srcProcessed; 2139 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; 2140 2141 if (res != SZ_OK) 2142 { 2143 return S_OK; 2144 // return res; 2145 } 2146 2147 if (dec->state == XZ_STATE_STREAM_HEADER) 2148 { 2149 *needContinue = True; 2150 me->isBlockHeaderState_Parse = False; 2151 me->isBlockHeaderState_Write = False; 2152 { 2153 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); 2154 if (!crossBuf) 2155 return SZ_ERROR_MEM; 2156 memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed); 2157 } 2158 me->mtc.crossStart = 0; 2159 me->mtc.crossEnd = srcSize - srcProcessed; 2160 return SZ_OK; 2161 } 2162 2163 if (status != CODER_STATUS_NEEDS_MORE_INPUT) 2164 { 2165 return E_FAIL; 2166 } 2167 2168 if (me->mtc.readWasFinished) 2169 { 2170 return SZ_OK; 2171 } 2172 } 2173 2174 { 2175 size_t inPos; 2176 size_t inLim; 2177 const Byte *inData; 2178 UInt64 inProgressPrev = me->mtc.inProcessed; 2179 2180 // XzDecMt_Prepare_InBuf_ST(p); 2181 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); 2182 if (!crossBuf) 2183 return SZ_ERROR_MEM; 2184 2185 inPos = 0; 2186 inLim = 0; 2187 // outProcessed = 0; 2188 2189 inData = crossBuf; 2190 2191 for (;;) 2192 { 2193 SizeT inProcessed; 2194 SizeT outProcessed; 2195 ECoderStatus status; 2196 SRes res; 2197 2198 if (inPos == inLim) 2199 { 2200 if (!me->mtc.readWasFinished) 2201 { 2202 inPos = 0; 2203 inLim = me->mtc.inBufSize; 2204 me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim); 2205 me->mtc.readProcessed += inLim; 2206 if (inLim == 0 || me->mtc.readRes != SZ_OK) 2207 me->mtc.readWasFinished = True; 2208 } 2209 } 2210 2211 inProcessed = inLim - inPos; 2212 outProcessed = 0; 2213 2214 res = XzUnpacker_Code(dec, 2215 NULL, &outProcessed, 2216 inData + inPos, &inProcessed, 2217 (inProcessed == 0), // srcFinished 2218 CODER_FINISH_END, &status); 2219 2220 me->codeRes = res; 2221 me->status = status; 2222 inPos += inProcessed; 2223 me->mtc.inProcessed += inProcessed; 2224 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; 2225 2226 if (res != SZ_OK) 2227 { 2228 return S_OK; 2229 // return res; 2230 } 2231 2232 if (dec->state == XZ_STATE_STREAM_HEADER) 2233 { 2234 *needContinue = True; 2235 me->mtc.crossStart = inPos; 2236 me->mtc.crossEnd = inLim; 2237 me->isBlockHeaderState_Parse = False; 2238 me->isBlockHeaderState_Write = False; 2239 return SZ_OK; 2240 } 2241 2242 if (status != CODER_STATUS_NEEDS_MORE_INPUT) 2243 return E_FAIL; 2244 2245 if (me->mtc.progress) 2246 { 2247 UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; 2248 if (inDelta >= (1 << 22)) 2249 { 2250 RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)); 2251 inProgressPrev = me->mtc.inProcessed; 2252 } 2253 } 2254 if (me->mtc.readWasFinished) 2255 return SZ_OK; 2256 } 2257 } 2258 } 2259 } 2260 2261 2262 #endif 2263 2264 2265 2266 void XzStatInfo_Clear(CXzStatInfo *p) 2267 { 2268 p->InSize = 0; 2269 p->OutSize = 0; 2270 2271 p->NumStreams = 0; 2272 p->NumBlocks = 0; 2273 2274 p->UnpackSize_Defined = False; 2275 2276 p->NumStreams_Defined = False; 2277 p->NumBlocks_Defined = False; 2278 2279 // p->IsArc = False; 2280 // p->UnexpectedEnd = False; 2281 // p->Unsupported = False; 2282 // p->HeadersError = False; 2283 // p->DataError = False; 2284 // p->CrcError = False; 2285 2286 p->DataAfterEnd = False; 2287 p->DecodingTruncated = False; 2288 2289 p->DecodeRes = SZ_OK; 2290 p->ReadRes = SZ_OK; 2291 p->ProgressRes = SZ_OK; 2292 2293 p->CombinedRes = SZ_OK; 2294 p->CombinedRes_Type = SZ_OK; 2295 } 2296 2297 2298 2299 2300 static SRes XzDecMt_Decode_ST(CXzDecMt *p 2301 #ifndef _7ZIP_ST 2302 , BoolInt tMode 2303 #endif 2304 , CXzStatInfo *stat) 2305 { 2306 size_t outPos; 2307 size_t inPos, inLim; 2308 const Byte *inData; 2309 UInt64 inPrev, outPrev; 2310 2311 CXzUnpacker *dec; 2312 2313 #ifndef _7ZIP_ST 2314 if (tMode) 2315 { 2316 XzDecMt_FreeOutBufs(p); 2317 tMode = MtDec_PrepareRead(&p->mtc); 2318 } 2319 #endif 2320 2321 if (!p->outBuf || p->outBufSize != p->props.outStep_ST) 2322 { 2323 ISzAlloc_Free(p->allocMid, p->outBuf); 2324 p->outBufSize = 0; 2325 p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); 2326 if (!p->outBuf) 2327 return SZ_ERROR_MEM; 2328 p->outBufSize = p->props.outStep_ST; 2329 } 2330 2331 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) 2332 { 2333 ISzAlloc_Free(p->allocMid, p->inBuf); 2334 p->inBufSize = 0; 2335 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); 2336 if (!p->inBuf) 2337 return SZ_ERROR_MEM; 2338 p->inBufSize = p->props.inBufSize_ST; 2339 } 2340 2341 dec = &p->dec; 2342 dec->decodeToStreamSignature = False; 2343 // dec->decodeOnlyOneBlock = False; 2344 2345 XzUnpacker_SetOutBuf(dec, NULL, 0); 2346 2347 inPrev = p->inProcessed; 2348 outPrev = p->outProcessed; 2349 2350 inPos = 0; 2351 inLim = 0; 2352 inData = NULL; 2353 outPos = 0; 2354 2355 for (;;) 2356 { 2357 SizeT outSize; 2358 BoolInt finished; 2359 ECoderFinishMode finishMode; 2360 SizeT inProcessed; 2361 ECoderStatus status; 2362 SRes res; 2363 2364 SizeT outProcessed; 2365 2366 2367 2368 if (inPos == inLim) 2369 { 2370 #ifndef _7ZIP_ST 2371 if (tMode) 2372 { 2373 inData = MtDec_Read(&p->mtc, &inLim); 2374 inPos = 0; 2375 if (inData) 2376 continue; 2377 tMode = False; 2378 inLim = 0; 2379 } 2380 #endif 2381 2382 if (!p->readWasFinished) 2383 { 2384 inPos = 0; 2385 inLim = p->inBufSize; 2386 inData = p->inBuf; 2387 p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim); 2388 p->readProcessed += inLim; 2389 if (inLim == 0 || p->readRes != SZ_OK) 2390 p->readWasFinished = True; 2391 } 2392 } 2393 2394 outSize = p->props.outStep_ST - outPos; 2395 2396 finishMode = CODER_FINISH_ANY; 2397 if (p->outSize_Defined) 2398 { 2399 const UInt64 rem = p->outSize - p->outProcessed; 2400 if (outSize >= rem) 2401 { 2402 outSize = (SizeT)rem; 2403 if (p->finishMode) 2404 finishMode = CODER_FINISH_END; 2405 } 2406 } 2407 2408 inProcessed = inLim - inPos; 2409 outProcessed = outSize; 2410 2411 res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, 2412 inData + inPos, &inProcessed, 2413 (inPos == inLim), // srcFinished 2414 finishMode, &status); 2415 2416 p->codeRes = res; 2417 p->status = status; 2418 2419 inPos += inProcessed; 2420 outPos += outProcessed; 2421 p->inProcessed += inProcessed; 2422 p->outProcessed += outProcessed; 2423 2424 finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); 2425 2426 if (finished || outProcessed >= outSize) 2427 if (outPos != 0) 2428 { 2429 size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); 2430 p->outProcessed += written; 2431 if (written != outPos) 2432 { 2433 stat->CombinedRes_Type = SZ_ERROR_WRITE; 2434 return SZ_ERROR_WRITE; 2435 } 2436 outPos = 0; 2437 } 2438 2439 if (p->progress && res == SZ_OK) 2440 { 2441 UInt64 inDelta = p->inProcessed - inPrev; 2442 UInt64 outDelta = p->outProcessed - outPrev; 2443 if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) 2444 { 2445 res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); 2446 if (res != SZ_OK) 2447 { 2448 stat->CombinedRes_Type = SZ_ERROR_PROGRESS; 2449 stat->ProgressRes = res; 2450 return res; 2451 } 2452 inPrev = p->inProcessed; 2453 outPrev = p->outProcessed; 2454 } 2455 } 2456 2457 if (finished) 2458 return res; 2459 } 2460 } 2461 2462 static SRes XzStatInfo_SetStat(const CXzUnpacker *dec, 2463 int finishMode, 2464 UInt64 readProcessed, UInt64 inProcessed, 2465 SRes res, ECoderStatus status, 2466 BoolInt decodingTruncated, 2467 CXzStatInfo *stat) 2468 { 2469 UInt64 extraSize; 2470 2471 stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); 2472 stat->InSize = inProcessed; 2473 stat->NumStreams = dec->numStartedStreams; 2474 stat->NumBlocks = dec->numTotalBlocks; 2475 2476 stat->UnpackSize_Defined = True; 2477 stat->NumStreams_Defined = True; 2478 stat->NumBlocks_Defined = True; 2479 2480 extraSize = XzUnpacker_GetExtraSize(dec); 2481 2482 if (res == SZ_OK) 2483 { 2484 if (status == CODER_STATUS_NEEDS_MORE_INPUT) 2485 { 2486 // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams 2487 extraSize = 0; 2488 if (!XzUnpacker_IsStreamWasFinished(dec)) 2489 res = SZ_ERROR_INPUT_EOF; 2490 } 2491 else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED) 2492 res = SZ_ERROR_DATA; 2493 } 2494 else if (res == SZ_ERROR_NO_ARCHIVE) 2495 { 2496 /* 2497 SZ_ERROR_NO_ARCHIVE is possible for 2 states: 2498 XZ_STATE_STREAM_HEADER - if bad signature or bad CRC 2499 XZ_STATE_STREAM_PADDING - if non-zero padding data 2500 extraSize / inProcessed don't include "bad" byte 2501 */ 2502 if (inProcessed != extraSize) // if good streams before error 2503 if (extraSize != 0 || readProcessed != inProcessed) 2504 { 2505 stat->DataAfterEnd = True; 2506 // there is some good xz stream before. So we set SZ_OK 2507 res = SZ_OK; 2508 } 2509 } 2510 2511 stat->DecodeRes = res; 2512 2513 stat->InSize -= extraSize; 2514 return res; 2515 } 2516 2517 2518 SRes XzDecMt_Decode(CXzDecMtHandle pp, 2519 const CXzDecMtProps *props, 2520 const UInt64 *outDataSize, int finishMode, 2521 ISeqOutStream *outStream, 2522 // Byte *outBuf, size_t *outBufSize, 2523 ISeqInStream *inStream, 2524 // const Byte *inData, size_t inDataSize, 2525 CXzStatInfo *stat, 2526 int *isMT, 2527 ICompressProgress *progress) 2528 { 2529 CXzDecMt *p = (CXzDecMt *)pp; 2530 #ifndef _7ZIP_ST 2531 BoolInt tMode; 2532 #endif 2533 2534 XzStatInfo_Clear(stat); 2535 2536 p->props = *props; 2537 2538 p->inStream = inStream; 2539 p->outStream = outStream; 2540 p->progress = progress; 2541 // p->stat = stat; 2542 2543 p->outSize = 0; 2544 p->outSize_Defined = False; 2545 if (outDataSize) 2546 { 2547 p->outSize_Defined = True; 2548 p->outSize = *outDataSize; 2549 } 2550 2551 p->finishMode = finishMode; 2552 2553 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test 2554 2555 p->writeRes = SZ_OK; 2556 p->outProcessed = 0; 2557 p->inProcessed = 0; 2558 p->readProcessed = 0; 2559 p->readWasFinished = False; 2560 2561 p->codeRes = 0; 2562 p->status = CODER_STATUS_NOT_SPECIFIED; 2563 2564 XzUnpacker_Init(&p->dec); 2565 2566 *isMT = False; 2567 2568 /* 2569 p->outBuf = NULL; 2570 p->outBufSize = 0; 2571 if (!outStream) 2572 { 2573 p->outBuf = outBuf; 2574 p->outBufSize = *outBufSize; 2575 *outBufSize = 0; 2576 } 2577 */ 2578 2579 2580 #ifndef _7ZIP_ST 2581 2582 p->isBlockHeaderState_Parse = False; 2583 p->isBlockHeaderState_Write = False; 2584 // p->numBadBlocks = 0; 2585 p->mainErrorCode = SZ_OK; 2586 p->mainDecoderWasCalled = False; 2587 2588 tMode = False; 2589 2590 if (p->props.numThreads > 1) 2591 { 2592 IMtDecCallback vt; 2593 2594 // we just free ST buffers here 2595 // but we still keep state variables, that was set in XzUnpacker_Init() 2596 XzDecMt_FreeSt(p); 2597 2598 p->outProcessed_Parse = 0; 2599 p->parsing_Truncated = False; 2600 2601 p->numStreams = 0; 2602 p->numTotalBlocks = 0; 2603 p->numBlocks = 0; 2604 p->finishedDecoderIndex = -1; 2605 2606 if (!p->mtc_WasConstructed) 2607 { 2608 p->mtc_WasConstructed = True; 2609 MtDec_Construct(&p->mtc); 2610 } 2611 2612 p->mtc.mtCallback = &vt; 2613 p->mtc.mtCallbackObject = p; 2614 2615 p->mtc.progress = progress; 2616 p->mtc.inStream = inStream; 2617 p->mtc.alloc = &p->alignOffsetAlloc.vt; 2618 // p->mtc.inData = inData; 2619 // p->mtc.inDataSize = inDataSize; 2620 p->mtc.inBufSize = p->props.inBufSize_MT; 2621 // p->mtc.inBlockMax = p->props.inBlockMax; 2622 p->mtc.numThreadsMax = p->props.numThreads; 2623 2624 *isMT = True; 2625 2626 vt.Parse = XzDecMt_Callback_Parse; 2627 vt.PreCode = XzDecMt_Callback_PreCode; 2628 vt.Code = XzDecMt_Callback_Code; 2629 vt.Write = XzDecMt_Callback_Write; 2630 2631 { 2632 BoolInt needContinue; 2633 2634 SRes res = MtDec_Code(&p->mtc); 2635 2636 stat->InSize = p->mtc.inProcessed; 2637 2638 p->inProcessed = p->mtc.inProcessed; 2639 p->readRes = p->mtc.readRes; 2640 p->readWasFinished = p->mtc.readWasFinished; 2641 p->readProcessed = p->mtc.readProcessed; 2642 2643 tMode = True; 2644 needContinue = False; 2645 2646 if (res == SZ_OK) 2647 { 2648 if (p->mtc.mtProgress.res != SZ_OK) 2649 { 2650 res = p->mtc.mtProgress.res; 2651 stat->ProgressRes = res; 2652 stat->CombinedRes_Type = SZ_ERROR_PROGRESS; 2653 } 2654 else 2655 needContinue = p->mtc.needContinue; 2656 } 2657 2658 if (!needContinue) 2659 { 2660 SRes codeRes; 2661 BoolInt truncated = False; 2662 ECoderStatus status; 2663 CXzUnpacker *dec; 2664 2665 stat->OutSize = p->outProcessed; 2666 2667 if (p->finishedDecoderIndex >= 0) 2668 { 2669 CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; 2670 codeRes = coder->codeRes; 2671 dec = &coder->dec; 2672 status = coder->status; 2673 } 2674 else if (p->mainDecoderWasCalled) 2675 { 2676 codeRes = p->codeRes; 2677 dec = &p->dec; 2678 status = p->status; 2679 truncated = p->parsing_Truncated; 2680 } 2681 else 2682 return E_FAIL; 2683 2684 XzStatInfo_SetStat(dec, p->finishMode, 2685 p->mtc.readProcessed, p->mtc.inProcessed, 2686 codeRes, status, 2687 truncated, 2688 stat); 2689 2690 if (res == SZ_OK) 2691 { 2692 if (p->writeRes != SZ_OK) 2693 { 2694 res = p->writeRes; 2695 stat->CombinedRes_Type = SZ_ERROR_WRITE; 2696 } 2697 else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed) 2698 { 2699 res = p->mtc.readRes; 2700 stat->ReadRes = res; 2701 stat->CombinedRes_Type = SZ_ERROR_READ; 2702 } 2703 else if (p->mainErrorCode != SZ_OK) 2704 { 2705 res = p->mainErrorCode; 2706 } 2707 } 2708 2709 stat->CombinedRes = res; 2710 if (stat->CombinedRes_Type == SZ_OK) 2711 stat->CombinedRes_Type = res; 2712 return res; 2713 } 2714 2715 PRF_STR("----- decoding ST -----"); 2716 } 2717 } 2718 2719 #endif 2720 2721 2722 *isMT = False; 2723 2724 { 2725 SRes res = XzDecMt_Decode_ST(p 2726 #ifndef _7ZIP_ST 2727 , tMode 2728 #endif 2729 , stat 2730 ); 2731 2732 XzStatInfo_SetStat(&p->dec, 2733 p->finishMode, 2734 p->readProcessed, p->inProcessed, 2735 p->codeRes, p->status, 2736 False, // truncated 2737 stat); 2738 2739 if (res == SZ_OK) 2740 { 2741 /* 2742 if (p->writeRes != SZ_OK) 2743 { 2744 res = p->writeRes; 2745 stat->CombinedRes_Type = SZ_ERROR_WRITE; 2746 } 2747 else 2748 */ 2749 if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed) 2750 { 2751 res = p->readRes; 2752 stat->ReadRes = res; 2753 stat->CombinedRes_Type = SZ_ERROR_READ; 2754 } 2755 #ifndef _7ZIP_ST 2756 else if (p->mainErrorCode != SZ_OK) 2757 res = p->mainErrorCode; 2758 #endif 2759 } 2760 2761 stat->CombinedRes = res; 2762 if (stat->CombinedRes_Type == SZ_OK) 2763 stat->CombinedRes_Type = res; 2764 return res; 2765 } 2766 } 2767