1 /* XzDec.c -- Xz Decode 2 2010-04-16 : Igor Pavlov : Public domain */ 3 4 /* #define XZ_DUMP */ 5 6 #ifdef XZ_DUMP 7 #include <stdio.h> 8 #endif 9 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "7zCrc.h" 14 #include "Alloc.h" 15 #include "Bra.h" 16 #include "CpuArch.h" 17 #include "Delta.h" 18 #include "Lzma2Dec.h" 19 20 #ifdef USE_SUBBLOCK 21 #include "SbDec.h" 22 #endif 23 24 #include "Xz.h" 25 26 #define XZ_CHECK_SIZE_MAX 64 27 28 #define CODER_BUF_SIZE (1 << 17) 29 30 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) 31 { 32 int i, limit; 33 *value = 0; 34 limit = (maxSize > 9) ? 9 : (int)maxSize; 35 36 for (i = 0; i < limit;) 37 { 38 Byte b = p[i]; 39 *value |= (UInt64)(b & 0x7F) << (7 * i++); 40 if ((b & 0x80) == 0) 41 return (b == 0 && i != 1) ? 0 : i; 42 } 43 return 0; 44 } 45 46 /* ---------- BraState ---------- */ 47 48 #define BRA_BUF_SIZE (1 << 14) 49 50 typedef struct 51 { 52 size_t bufPos; 53 size_t bufConv; 54 size_t bufTotal; 55 56 UInt32 methodId; 57 int encodeMode; 58 UInt32 delta; 59 UInt32 ip; 60 UInt32 x86State; 61 Byte deltaState[DELTA_STATE_SIZE]; 62 63 Byte buf[BRA_BUF_SIZE]; 64 } CBraState; 65 66 void BraState_Free(void *pp, ISzAlloc *alloc) 67 { 68 alloc->Free(alloc, pp); 69 } 70 71 SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) 72 { 73 CBraState *p = ((CBraState *)pp); 74 alloc = alloc; 75 p->encodeMode = 0; 76 p->ip = 0; 77 if (p->methodId == XZ_ID_Delta) 78 { 79 if (propSize != 1) 80 return SZ_ERROR_UNSUPPORTED; 81 p->delta = (unsigned)props[0] + 1; 82 } 83 else 84 { 85 if (propSize == 4) 86 { 87 UInt32 v = GetUi32(props); 88 switch(p->methodId) 89 { 90 case XZ_ID_PPC: 91 case XZ_ID_ARM: 92 case XZ_ID_SPARC: 93 if ((v & 3) != 0) 94 return SZ_ERROR_UNSUPPORTED; 95 break; 96 case XZ_ID_ARMT: 97 if ((v & 1) != 0) 98 return SZ_ERROR_UNSUPPORTED; 99 break; 100 case XZ_ID_IA64: 101 if ((v & 0xF) != 0) 102 return SZ_ERROR_UNSUPPORTED; 103 break; 104 } 105 p->ip = v; 106 } 107 else if (propSize != 0) 108 return SZ_ERROR_UNSUPPORTED; 109 } 110 return SZ_OK; 111 } 112 113 void BraState_Init(void *pp) 114 { 115 CBraState *p = ((CBraState *)pp); 116 p->bufPos = p->bufConv = p->bufTotal = 0; 117 x86_Convert_Init(p->x86State); 118 if (p->methodId == XZ_ID_Delta) 119 Delta_Init(p->deltaState); 120 } 121 122 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break; 123 124 static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 125 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) 126 { 127 CBraState *p = ((CBraState *)pp); 128 SizeT destLenOrig = *destLen; 129 SizeT srcLenOrig = *srcLen; 130 *destLen = 0; 131 *srcLen = 0; 132 finishMode = finishMode; 133 *wasFinished = 0; 134 while (destLenOrig > 0) 135 { 136 if (p->bufPos != p->bufConv) 137 { 138 size_t curSize = p->bufConv - p->bufPos; 139 if (curSize > destLenOrig) 140 curSize = destLenOrig; 141 memcpy(dest, p->buf + p->bufPos, curSize); 142 p->bufPos += curSize; 143 *destLen += curSize; 144 dest += curSize; 145 destLenOrig -= curSize; 146 continue; 147 } 148 p->bufTotal -= p->bufPos; 149 memmove(p->buf, p->buf + p->bufPos, p->bufTotal); 150 p->bufPos = 0; 151 p->bufConv = 0; 152 { 153 size_t curSize = BRA_BUF_SIZE - p->bufTotal; 154 if (curSize > srcLenOrig) 155 curSize = srcLenOrig; 156 memcpy(p->buf + p->bufTotal, src, curSize); 157 *srcLen += curSize; 158 src += curSize; 159 srcLenOrig -= curSize; 160 p->bufTotal += curSize; 161 } 162 if (p->bufTotal == 0) 163 break; 164 switch(p->methodId) 165 { 166 case XZ_ID_Delta: 167 if (p->encodeMode) 168 Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal); 169 else 170 Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal); 171 p->bufConv = p->bufTotal; 172 break; 173 case XZ_ID_X86: 174 p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode); 175 break; 176 CASE_BRA_CONV(PPC) 177 CASE_BRA_CONV(IA64) 178 CASE_BRA_CONV(ARM) 179 CASE_BRA_CONV(ARMT) 180 CASE_BRA_CONV(SPARC) 181 default: 182 return SZ_ERROR_UNSUPPORTED; 183 } 184 p->ip += (UInt32)p->bufConv; 185 186 if (p->bufConv == 0) 187 { 188 if (!srcWasFinished) 189 break; 190 p->bufConv = p->bufTotal; 191 } 192 } 193 if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished) 194 *wasFinished = 1; 195 return SZ_OK; 196 } 197 198 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) 199 { 200 CBraState *decoder; 201 if (id != XZ_ID_Delta && 202 id != XZ_ID_X86 && 203 id != XZ_ID_PPC && 204 id != XZ_ID_IA64 && 205 id != XZ_ID_ARM && 206 id != XZ_ID_ARMT && 207 id != XZ_ID_SPARC) 208 return SZ_ERROR_UNSUPPORTED; 209 p->p = 0; 210 decoder = alloc->Alloc(alloc, sizeof(CBraState)); 211 if (decoder == 0) 212 return SZ_ERROR_MEM; 213 decoder->methodId = (UInt32)id; 214 p->p = decoder; 215 p->Free = BraState_Free; 216 p->SetProps = BraState_SetProps; 217 p->Init = BraState_Init; 218 p->Code = BraState_Code; 219 return SZ_OK; 220 } 221 222 /* ---------- SbState ---------- */ 223 224 #ifdef USE_SUBBLOCK 225 226 static void SbState_Free(void *pp, ISzAlloc *alloc) 227 { 228 CSubblockDec *p = (CSubblockDec *)pp; 229 SubblockDec_Free(p, alloc); 230 alloc->Free(alloc, pp); 231 } 232 233 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) 234 { 235 pp = pp; 236 props = props; 237 alloc = alloc; 238 return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; 239 } 240 241 static void SbState_Init(void *pp) 242 { 243 SubblockDec_Init((CSubblockDec *)pp); 244 } 245 246 static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 247 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) 248 { 249 ECoderStatus status; 250 SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status); 251 srcWasFinished = srcWasFinished; 252 *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); 253 return res; 254 } 255 256 SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) 257 { 258 CSubblockDec *decoder; 259 p->p = 0; 260 decoder = alloc->Alloc(alloc, sizeof(CSubblockDec)); 261 if (decoder == 0) 262 return SZ_ERROR_MEM; 263 p->p = decoder; 264 p->Free = SbState_Free; 265 p->SetProps = SbState_SetProps; 266 p->Init = SbState_Init; 267 p->Code = SbState_Code; 268 SubblockDec_Construct(decoder); 269 return SZ_OK; 270 } 271 #endif 272 273 /* ---------- Lzma2State ---------- */ 274 275 static void Lzma2State_Free(void *pp, ISzAlloc *alloc) 276 { 277 Lzma2Dec_Free((CLzma2Dec *)pp, alloc); 278 alloc->Free(alloc, pp); 279 } 280 281 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) 282 { 283 if (propSize != 1) 284 return SZ_ERROR_UNSUPPORTED; 285 return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc); 286 } 287 288 static void Lzma2State_Init(void *pp) 289 { 290 Lzma2Dec_Init((CLzma2Dec *)pp); 291 } 292 293 static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 294 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) 295 { 296 ELzmaStatus status; 297 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ 298 SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status); 299 srcWasFinished = srcWasFinished; 300 *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); 301 return res; 302 } 303 304 static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) 305 { 306 CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec)); 307 p->p = decoder; 308 if (decoder == 0) 309 return SZ_ERROR_MEM; 310 p->Free = Lzma2State_Free; 311 p->SetProps = Lzma2State_SetProps; 312 p->Init = Lzma2State_Init; 313 p->Code = Lzma2State_Code; 314 Lzma2Dec_Construct(decoder); 315 return SZ_OK; 316 } 317 318 319 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc) 320 { 321 int i; 322 p->alloc = alloc; 323 p->buf = 0; 324 p->numCoders = 0; 325 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) 326 p->coders[i].p = NULL; 327 } 328 329 void MixCoder_Free(CMixCoder *p) 330 { 331 int i; 332 for (i = 0; i < p->numCoders; i++) 333 { 334 IStateCoder *sc = &p->coders[i]; 335 if (p->alloc && sc->p) 336 sc->Free(sc->p, p->alloc); 337 } 338 p->numCoders = 0; 339 if (p->buf) 340 p->alloc->Free(p->alloc, p->buf); 341 } 342 343 void MixCoder_Init(CMixCoder *p) 344 { 345 int i; 346 for (i = 0; i < p->numCoders - 1; i++) 347 { 348 p->size[i] = 0; 349 p->pos[i] = 0; 350 p->finished[i] = 0; 351 } 352 for (i = 0; i < p->numCoders; i++) 353 { 354 IStateCoder *coder = &p->coders[i]; 355 coder->Init(coder->p); 356 } 357 } 358 359 SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) 360 { 361 IStateCoder *sc = &p->coders[coderIndex]; 362 p->ids[coderIndex] = methodId; 363 switch(methodId) 364 { 365 case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc); 366 #ifdef USE_SUBBLOCK 367 case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); 368 #endif 369 } 370 if (coderIndex == 0) 371 return SZ_ERROR_UNSUPPORTED; 372 return BraState_SetFromMethod(sc, methodId, p->alloc); 373 } 374 375 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, 376 const Byte *src, SizeT *srcLen, int srcWasFinished, 377 ECoderFinishMode finishMode, ECoderStatus *status) 378 { 379 SizeT destLenOrig = *destLen; 380 SizeT srcLenOrig = *srcLen; 381 Bool allFinished = True; 382 *destLen = 0; 383 *srcLen = 0; 384 *status = CODER_STATUS_NOT_FINISHED; 385 386 if (p->buf == 0) 387 { 388 p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); 389 if (p->buf == 0) 390 return SZ_ERROR_MEM; 391 } 392 393 if (p->numCoders != 1) 394 finishMode = CODER_FINISH_ANY; 395 396 for (;;) 397 { 398 Bool processed = False; 399 int i; 400 /* 401 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) 402 break; 403 */ 404 405 for (i = 0; i < p->numCoders; i++) 406 { 407 SRes res; 408 IStateCoder *coder = &p->coders[i]; 409 Byte *destCur; 410 SizeT destLenCur, srcLenCur; 411 const Byte *srcCur; 412 int srcFinishedCur; 413 int encodingWasFinished; 414 415 if (i == 0) 416 { 417 srcCur = src; 418 srcLenCur = srcLenOrig - *srcLen; 419 srcFinishedCur = srcWasFinished; 420 } 421 else 422 { 423 srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1]; 424 srcLenCur = p->size[i - 1] - p->pos[i - 1]; 425 srcFinishedCur = p->finished[i - 1]; 426 } 427 428 if (i == p->numCoders - 1) 429 { 430 destCur = dest; 431 destLenCur = destLenOrig - *destLen; 432 } 433 else 434 { 435 if (p->pos[i] != p->size[i]) 436 continue; 437 destCur = p->buf + (CODER_BUF_SIZE * i); 438 destLenCur = CODER_BUF_SIZE; 439 } 440 441 res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished); 442 443 if (!encodingWasFinished) 444 allFinished = False; 445 446 if (i == 0) 447 { 448 *srcLen += srcLenCur; 449 src += srcLenCur; 450 } 451 else 452 { 453 p->pos[i - 1] += srcLenCur; 454 } 455 456 if (i == p->numCoders - 1) 457 { 458 *destLen += destLenCur; 459 dest += destLenCur; 460 } 461 else 462 { 463 p->size[i] = destLenCur; 464 p->pos[i] = 0; 465 p->finished[i] = encodingWasFinished; 466 } 467 468 if (res != SZ_OK) 469 return res; 470 471 if (destLenCur != 0 || srcLenCur != 0) 472 processed = True; 473 } 474 if (!processed) 475 break; 476 } 477 if (allFinished) 478 *status = CODER_STATUS_FINISHED_WITH_MARK; 479 return SZ_OK; 480 } 481 482 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) 483 { 484 *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); 485 if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != 486 GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) 487 return SZ_ERROR_NO_ARCHIVE; 488 return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; 489 } 490 491 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) 492 { 493 return 494 indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) && 495 (GetUi32(buf) == CrcCalc(buf + 4, 6) && 496 flags == GetBe16(buf + 8) && 497 memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0); 498 } 499 500 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ 501 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ 502 if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } 503 504 505 SRes XzBlock_Parse(CXzBlock *p, const Byte *header) 506 { 507 unsigned pos; 508 int numFilters, i; 509 UInt32 headerSize = (UInt32)header[0] << 2; 510 511 if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) 512 return SZ_ERROR_ARCHIVE; 513 514 pos = 1; 515 if (pos == headerSize) 516 return SZ_ERROR_ARCHIVE; 517 p->flags = header[pos++]; 518 519 if (XzBlock_HasPackSize(p)) 520 { 521 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize); 522 if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) 523 return SZ_ERROR_ARCHIVE; 524 } 525 526 if (XzBlock_HasUnpackSize(p)) 527 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize); 528 529 numFilters = XzBlock_GetNumFilters(p); 530 for (i = 0; i < numFilters; i++) 531 { 532 CXzFilter *filter = p->filters + i; 533 UInt64 size; 534 READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id); 535 READ_VARINT_AND_CHECK(header, pos, headerSize, &size); 536 if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) 537 return SZ_ERROR_ARCHIVE; 538 filter->propsSize = (UInt32)size; 539 memcpy(filter->props, header + pos, (size_t)size); 540 pos += (unsigned)size; 541 542 #ifdef XZ_DUMP 543 printf("\nf[%d] = %2X: ", i, filter->id); 544 { 545 int i; 546 for (i = 0; i < size; i++) 547 printf(" %2X", filter->props[i]); 548 } 549 #endif 550 } 551 552 while (pos < headerSize) 553 if (header[pos++] != 0) 554 return SZ_ERROR_ARCHIVE; 555 return SZ_OK; 556 } 557 558 SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) 559 { 560 int i; 561 Bool needReInit = True; 562 int numFilters = XzBlock_GetNumFilters(block); 563 if (numFilters == p->numCoders) 564 { 565 for (i = 0; i < numFilters; i++) 566 if (p->ids[i] != block->filters[numFilters - 1 - i].id) 567 break; 568 needReInit = (i != numFilters); 569 } 570 if (needReInit) 571 { 572 MixCoder_Free(p); 573 p->numCoders = numFilters; 574 for (i = 0; i < numFilters; i++) 575 { 576 const CXzFilter *f = &block->filters[numFilters - 1 - i]; 577 RINOK(MixCoder_SetFromMethod(p, i, f->id)); 578 } 579 } 580 for (i = 0; i < numFilters; i++) 581 { 582 const CXzFilter *f = &block->filters[numFilters - 1 - i]; 583 IStateCoder *sc = &p->coders[i]; 584 RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); 585 } 586 MixCoder_Init(p); 587 return SZ_OK; 588 } 589 590 SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc) 591 { 592 MixCoder_Construct(&p->decoder, alloc); 593 p->state = XZ_STATE_STREAM_HEADER; 594 p->pos = 0; 595 p->numStreams = 0; 596 return SZ_OK; 597 } 598 599 void XzUnpacker_Free(CXzUnpacker *p) 600 { 601 MixCoder_Free(&p->decoder); 602 } 603 604 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, 605 const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status) 606 { 607 SizeT destLenOrig = *destLen; 608 SizeT srcLenOrig = *srcLen; 609 *destLen = 0; 610 *srcLen = 0; 611 *status = CODER_STATUS_NOT_SPECIFIED; 612 for (;;) 613 { 614 SizeT srcRem = srcLenOrig - *srcLen; 615 616 if (p->state == XZ_STATE_BLOCK) 617 { 618 SizeT destLen2 = destLenOrig - *destLen; 619 SizeT srcLen2 = srcLenOrig - *srcLen; 620 SRes res; 621 if (srcLen2 == 0 && destLen2 == 0) 622 { 623 *status = CODER_STATUS_NOT_FINISHED; 624 return SZ_OK; 625 } 626 627 res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status); 628 XzCheck_Update(&p->check, dest, destLen2); 629 630 (*srcLen) += srcLen2; 631 src += srcLen2; 632 p->packSize += srcLen2; 633 634 (*destLen) += destLen2; 635 dest += destLen2; 636 p->unpackSize += destLen2; 637 638 RINOK(res); 639 640 if (*status == CODER_STATUS_FINISHED_WITH_MARK) 641 { 642 Byte temp[32]; 643 unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags)); 644 num += Xz_WriteVarInt(temp + num, p->unpackSize); 645 Sha256_Update(&p->sha, temp, num); 646 p->indexSize += num; 647 p->numBlocks++; 648 649 p->state = XZ_STATE_BLOCK_FOOTER; 650 p->pos = 0; 651 p->alignPos = 0; 652 } 653 else if (srcLen2 == 0 && destLen2 == 0) 654 return SZ_OK; 655 656 continue; 657 } 658 659 if (srcRem == 0) 660 { 661 *status = CODER_STATUS_NEEDS_MORE_INPUT; 662 return SZ_OK; 663 } 664 665 switch(p->state) 666 { 667 case XZ_STATE_STREAM_HEADER: 668 { 669 if (p->pos < XZ_STREAM_HEADER_SIZE) 670 { 671 if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) 672 return SZ_ERROR_NO_ARCHIVE; 673 p->buf[p->pos++] = *src++; 674 (*srcLen)++; 675 } 676 else 677 { 678 RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); 679 p->state = XZ_STATE_BLOCK_HEADER; 680 Sha256_Init(&p->sha); 681 p->indexSize = 0; 682 p->numBlocks = 0; 683 p->pos = 0; 684 } 685 break; 686 } 687 688 case XZ_STATE_BLOCK_HEADER: 689 { 690 if (p->pos == 0) 691 { 692 p->buf[p->pos++] = *src++; 693 (*srcLen)++; 694 if (p->buf[0] == 0) 695 { 696 p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); 697 p->indexPos = p->indexPreSize; 698 p->indexSize += p->indexPreSize; 699 Sha256_Final(&p->sha, p->shaDigest); 700 Sha256_Init(&p->sha); 701 p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); 702 p->state = XZ_STATE_STREAM_INDEX; 703 } 704 p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; 705 } 706 else if (p->pos != p->blockHeaderSize) 707 { 708 UInt32 cur = p->blockHeaderSize - p->pos; 709 if (cur > srcRem) 710 cur = (UInt32)srcRem; 711 memcpy(p->buf + p->pos, src, cur); 712 p->pos += cur; 713 (*srcLen) += cur; 714 src += cur; 715 } 716 else 717 { 718 RINOK(XzBlock_Parse(&p->block, p->buf)); 719 p->state = XZ_STATE_BLOCK; 720 p->packSize = 0; 721 p->unpackSize = 0; 722 XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); 723 RINOK(XzDec_Init(&p->decoder, &p->block)); 724 } 725 break; 726 } 727 728 case XZ_STATE_BLOCK_FOOTER: 729 { 730 if (((p->packSize + p->alignPos) & 3) != 0) 731 { 732 (*srcLen)++; 733 p->alignPos++; 734 if (*src++ != 0) 735 return SZ_ERROR_CRC; 736 } 737 else 738 { 739 UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); 740 UInt32 cur = checkSize - p->pos; 741 if (cur != 0) 742 { 743 if (cur > srcRem) 744 cur = (UInt32)srcRem; 745 memcpy(p->buf + p->pos, src, cur); 746 p->pos += cur; 747 (*srcLen) += cur; 748 src += cur; 749 } 750 else 751 { 752 Byte digest[XZ_CHECK_SIZE_MAX]; 753 p->state = XZ_STATE_BLOCK_HEADER; 754 p->pos = 0; 755 if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) 756 return SZ_ERROR_CRC; 757 } 758 } 759 break; 760 } 761 762 case XZ_STATE_STREAM_INDEX: 763 { 764 if (p->pos < p->indexPreSize) 765 { 766 (*srcLen)++; 767 if (*src++ != p->buf[p->pos++]) 768 return SZ_ERROR_CRC; 769 } 770 else 771 { 772 if (p->indexPos < p->indexSize) 773 { 774 UInt64 cur = p->indexSize - p->indexPos; 775 if (srcRem > cur) 776 srcRem = (SizeT)cur; 777 p->crc = CrcUpdate(p->crc, src, srcRem); 778 Sha256_Update(&p->sha, src, srcRem); 779 (*srcLen) += srcRem; 780 src += srcRem; 781 p->indexPos += srcRem; 782 } 783 else if ((p->indexPos & 3) != 0) 784 { 785 Byte b = *src++; 786 p->crc = CRC_UPDATE_BYTE(p->crc, b); 787 (*srcLen)++; 788 p->indexPos++; 789 p->indexSize++; 790 if (b != 0) 791 return SZ_ERROR_CRC; 792 } 793 else 794 { 795 Byte digest[SHA256_DIGEST_SIZE]; 796 p->state = XZ_STATE_STREAM_INDEX_CRC; 797 p->indexSize += 4; 798 p->pos = 0; 799 Sha256_Final(&p->sha, digest); 800 if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) 801 return SZ_ERROR_CRC; 802 } 803 } 804 break; 805 } 806 807 case XZ_STATE_STREAM_INDEX_CRC: 808 { 809 if (p->pos < 4) 810 { 811 (*srcLen)++; 812 p->buf[p->pos++] = *src++; 813 } 814 else 815 { 816 p->state = XZ_STATE_STREAM_FOOTER; 817 p->pos = 0; 818 if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf)) 819 return SZ_ERROR_CRC; 820 } 821 break; 822 } 823 824 case XZ_STATE_STREAM_FOOTER: 825 { 826 UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; 827 if (cur > srcRem) 828 cur = (UInt32)srcRem; 829 memcpy(p->buf + p->pos, src, cur); 830 p->pos += cur; 831 (*srcLen) += cur; 832 src += cur; 833 if (p->pos == XZ_STREAM_FOOTER_SIZE) 834 { 835 p->state = XZ_STATE_STREAM_PADDING; 836 p->numStreams++; 837 p->padSize = 0; 838 if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) 839 return SZ_ERROR_CRC; 840 } 841 break; 842 } 843 844 case XZ_STATE_STREAM_PADDING: 845 { 846 if (*src != 0) 847 { 848 if (((UInt32)p->padSize & 3) != 0) 849 return SZ_ERROR_NO_ARCHIVE; 850 p->pos = 0; 851 p->state = XZ_STATE_STREAM_HEADER; 852 } 853 else 854 { 855 (*srcLen)++; 856 src++; 857 p->padSize++; 858 } 859 break; 860 } 861 862 case XZ_STATE_BLOCK: break; /* to disable GCC warning */ 863 } 864 } 865 /* 866 if (p->state == XZ_STATE_FINISHED) 867 *status = CODER_STATUS_FINISHED_WITH_MARK; 868 return SZ_OK; 869 */ 870 } 871 872 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p) 873 { 874 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); 875 } 876