1/* 7zArcIn.c -- 7z Input functions 22014-06-16 : Igor Pavlov : Public domain */ 3 4#include "Precomp.h" 5 6#include <string.h> 7 8#include "7z.h" 9#include "7zBuf.h" 10#include "7zCrc.h" 11#include "CpuArch.h" 12 13#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ 14 if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } 15 16#define k7zMajorVersion 0 17 18enum EIdEnum 19{ 20 k7zIdEnd, 21 k7zIdHeader, 22 k7zIdArchiveProperties, 23 k7zIdAdditionalStreamsInfo, 24 k7zIdMainStreamsInfo, 25 k7zIdFilesInfo, 26 k7zIdPackInfo, 27 k7zIdUnpackInfo, 28 k7zIdSubStreamsInfo, 29 k7zIdSize, 30 k7zIdCRC, 31 k7zIdFolder, 32 k7zIdCodersUnpackSize, 33 k7zIdNumUnpackStream, 34 k7zIdEmptyStream, 35 k7zIdEmptyFile, 36 k7zIdAnti, 37 k7zIdName, 38 k7zIdCTime, 39 k7zIdATime, 40 k7zIdMTime, 41 k7zIdWinAttrib, 42 k7zIdComment, 43 k7zIdEncodedHeader, 44 k7zIdStartPos, 45 k7zIdDummy 46 // k7zNtSecure, 47 // k7zParent, 48 // k7zIsReal 49}; 50 51Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; 52 53#define NUM_FOLDER_CODERS_MAX 32 54#define NUM_CODER_STREAMS_MAX 32 55 56/* 57static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex) 58{ 59 UInt32 i; 60 for (i = 0; i < p->NumBindPairs; i++) 61 if (p->BindPairs[i].InIndex == inStreamIndex) 62 return i; 63 return -1; 64} 65*/ 66 67#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } 68 69static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc) 70{ 71 MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); 72 MY_ALLOC(UInt32, p->Vals, num, alloc); 73 return SZ_OK; 74} 75 76void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc) 77{ 78 IAlloc_Free(alloc, p->Defs); p->Defs = 0; 79 IAlloc_Free(alloc, p->Vals); p->Vals = 0; 80} 81 82#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } 83 84void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) 85{ 86 IAlloc_Free(alloc, p->Defs); p->Defs = 0; 87 IAlloc_Free(alloc, p->Vals); p->Vals = 0; 88} 89 90static void SzAr_Init(CSzAr *p) 91{ 92 p->NumPackStreams = 0; 93 p->NumFolders = 0; 94 p->PackPositions = 0; 95 SzBitUi32s_Init(&p->FolderCRCs); 96 // p->Folders = 0; 97 p->FoCodersOffsets = 0; 98 p->FoSizesOffsets = 0; 99 p->FoStartPackStreamIndex = 0; 100 101 p->CodersData = 0; 102 // p->CoderUnpackSizes = 0; 103 p->UnpackSizesData = 0; 104} 105 106static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) 107{ 108 IAlloc_Free(alloc, p->UnpackSizesData); 109 IAlloc_Free(alloc, p->CodersData); 110 // IAlloc_Free(alloc, p->CoderUnpackSizes); 111 112 IAlloc_Free(alloc, p->PackPositions); 113 114 // IAlloc_Free(alloc, p->Folders); 115 IAlloc_Free(alloc, p->FoCodersOffsets); 116 IAlloc_Free(alloc, p->FoSizesOffsets); 117 IAlloc_Free(alloc, p->FoStartPackStreamIndex); 118 119 SzBitUi32s_Free(&p->FolderCRCs, alloc); 120 121 SzAr_Init(p); 122} 123 124 125void SzArEx_Init(CSzArEx *p) 126{ 127 SzAr_Init(&p->db); 128 p->NumFiles = 0; 129 p->dataPos = 0; 130 // p->Files = 0; 131 p->UnpackPositions = 0; 132 // p->IsEmptyFiles = 0; 133 p->IsDirs = 0; 134 // p->FolderStartPackStreamIndex = 0; 135 // p->PackStreamStartPositions = 0; 136 p->FolderStartFileIndex = 0; 137 p->FileIndexToFolderIndexMap = 0; 138 p->FileNameOffsets = 0; 139 p->FileNames = 0; 140 SzBitUi32s_Init(&p->CRCs); 141 SzBitUi32s_Init(&p->Attribs); 142 // SzBitUi32s_Init(&p->Parents); 143 SzBitUi64s_Init(&p->MTime); 144 SzBitUi64s_Init(&p->CTime); 145} 146 147void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) 148{ 149 // IAlloc_Free(alloc, p->FolderStartPackStreamIndex); 150 // IAlloc_Free(alloc, p->PackStreamStartPositions); 151 IAlloc_Free(alloc, p->FolderStartFileIndex); 152 IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); 153 154 IAlloc_Free(alloc, p->FileNameOffsets); 155 IAlloc_Free(alloc, p->FileNames); 156 157 SzBitUi64s_Free(&p->CTime, alloc); 158 SzBitUi64s_Free(&p->MTime, alloc); 159 SzBitUi32s_Free(&p->CRCs, alloc); 160 // SzBitUi32s_Free(&p->Parents, alloc); 161 SzBitUi32s_Free(&p->Attribs, alloc); 162 IAlloc_Free(alloc, p->IsDirs); 163 // IAlloc_Free(alloc, p->IsEmptyFiles); 164 IAlloc_Free(alloc, p->UnpackPositions); 165 // IAlloc_Free(alloc, p->Files); 166 167 SzAr_Free(&p->db, alloc); 168 SzArEx_Init(p); 169} 170 171static int TestSignatureCandidate(Byte *testBytes) 172{ 173 size_t i; 174 for (i = 0; i < k7zSignatureSize; i++) 175 if (testBytes[i] != k7zSignature[i]) 176 return 0; 177 return 1; 178} 179 180#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; } 181 182static SRes SzReadByte(CSzData *sd, Byte *b) 183{ 184 if (sd->Size == 0) 185 return SZ_ERROR_ARCHIVE; 186 sd->Size--; 187 *b = *sd->Data++; 188 return SZ_OK; 189} 190 191#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; 192#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) 193#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; 194 195#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } 196#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } 197 198#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ 199 dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); 200 201static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) 202{ 203 Byte firstByte, mask; 204 unsigned i; 205 UInt32 v; 206 207 SZ_READ_BYTE(firstByte); 208 if ((firstByte & 0x80) == 0) 209 { 210 *value = firstByte; 211 return SZ_OK; 212 } 213 SZ_READ_BYTE(v); 214 if ((firstByte & 0x40) == 0) 215 { 216 *value = (((UInt32)firstByte & 0x3F) << 8) | v; 217 return SZ_OK; 218 } 219 SZ_READ_BYTE(mask); 220 *value = v | ((UInt32)mask << 8); 221 mask = 0x20; 222 for (i = 2; i < 8; i++) 223 { 224 Byte b; 225 if ((firstByte & mask) == 0) 226 { 227 UInt64 highPart = firstByte & (mask - 1); 228 *value |= (highPart << (8 * i)); 229 return SZ_OK; 230 } 231 SZ_READ_BYTE(b); 232 *value |= ((UInt64)b << (8 * i)); 233 mask >>= 1; 234 } 235 return SZ_OK; 236} 237 238/* 239static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num) 240{ 241 for (; num != 0; num--) 242 { 243 Byte firstByte; 244 Byte mask; 245 246 unsigned i; 247 UInt32 v; 248 UInt64 value; 249 250 if (data == dataLim) 251 return NULL; 252 firstByte = *data++; 253 254 if ((firstByte & 0x80) == 0) 255 { 256 *values++ = firstByte; 257 continue; 258 } 259 if (data == dataLim) 260 return NULL; 261 v = *data++; 262 if ((firstByte & 0x40) == 0) 263 { 264 *values++ = (((UInt32)firstByte & 0x3F) << 8) | v; 265 continue; 266 } 267 if (data == dataLim) 268 return NULL; 269 value = v | ((UInt32)*data++ << 8); 270 mask = 0x20; 271 for (i = 2; i < 8; i++) 272 { 273 if ((firstByte & mask) == 0) 274 { 275 UInt64 highPart = firstByte & (mask - 1); 276 value |= (highPart << (8 * i)); 277 break; 278 } 279 if (data == dataLim) 280 return NULL; 281 value |= ((UInt64)*data++ << (8 * i)); 282 mask >>= 1; 283 } 284 *values++ = value; 285 } 286 return data; 287} 288*/ 289 290static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) 291{ 292 Byte firstByte; 293 UInt64 value64; 294 if (sd->Size == 0) 295 return SZ_ERROR_ARCHIVE; 296 firstByte = *sd->Data; 297 if ((firstByte & 0x80) == 0) 298 { 299 *value = firstByte; 300 sd->Data++; 301 sd->Size--; 302 return SZ_OK; 303 } 304 RINOK(ReadNumber(sd, &value64)); 305 if (value64 >= (UInt32)0x80000000 - 1) 306 return SZ_ERROR_UNSUPPORTED; 307 if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) 308 return SZ_ERROR_UNSUPPORTED; 309 *value = (UInt32)value64; 310 return SZ_OK; 311} 312 313#define ReadID(sd, value) ReadNumber(sd, value) 314 315static SRes SkipData(CSzData *sd) 316{ 317 UInt64 size; 318 RINOK(ReadNumber(sd, &size)); 319 if (size > sd->Size) 320 return SZ_ERROR_ARCHIVE; 321 SKIP_DATA(sd, size); 322 return SZ_OK; 323} 324 325static SRes WaitId(CSzData *sd, UInt64 id) 326{ 327 for (;;) 328 { 329 UInt64 type; 330 RINOK(ReadID(sd, &type)); 331 if (type == id) 332 return SZ_OK; 333 if (type == k7zIdEnd) 334 return SZ_ERROR_ARCHIVE; 335 RINOK(SkipData(sd)); 336 } 337} 338 339static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) 340{ 341 UInt32 numBytes = (numItems + 7) >> 3; 342 if (numBytes > sd->Size) 343 return SZ_ERROR_ARCHIVE; 344 *v = sd->Data; 345 SKIP_DATA(sd, numBytes); 346 return SZ_OK; 347} 348 349static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) 350{ 351 Byte b = 0; 352 unsigned m = 0; 353 UInt32 sum = 0; 354 for (; numItems != 0; numItems--) 355 { 356 if (m == 0) 357 { 358 b = *bits++; 359 m = 8; 360 } 361 m--; 362 sum += ((b >> m) & 1); 363 } 364 return sum ; 365} 366 367static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc) 368{ 369 Byte allAreDefined; 370 UInt32 i; 371 Byte *v2; 372 UInt32 numBytes = (numItems + 7) >> 3; 373 RINOK(SzReadByte(sd, &allAreDefined)); 374 if (allAreDefined == 0) 375 { 376 if (numBytes > sd->Size) 377 return SZ_ERROR_ARCHIVE; 378 MY_ALLOC(Byte, *v, numBytes, alloc); 379 memcpy(*v, sd->Data, numBytes); 380 SKIP_DATA(sd, numBytes); 381 return SZ_OK; 382 } 383 MY_ALLOC(Byte, *v, numBytes, alloc); 384 v2 = *v; 385 for (i = 0; i < numBytes; i++) 386 v2[i] = 0xFF; 387 { 388 unsigned numBits = (unsigned)numItems & 7; 389 if (numBits != 0) 390 v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); 391 } 392 return SZ_OK; 393} 394 395static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) 396{ 397 UInt32 i; 398 CSzData sd; 399 UInt32 *vals; 400 const Byte *defs; 401 MY_ALLOC(UInt32, crcs->Vals, numItems, alloc); 402 sd = *sd2; 403 defs = crcs->Defs; 404 vals = crcs->Vals; 405 for (i = 0; i < numItems; i++) 406 if (SzBitArray_Check(defs, i)) 407 { 408 SZ_READ_32(vals[i]); 409 } 410 else 411 vals[i] = 0; 412 *sd2 = sd; 413 return SZ_OK; 414} 415 416static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) 417{ 418 SzBitUi32s_Free(crcs, alloc); 419 RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); 420 return ReadUi32s(sd, numItems, crcs, alloc); 421} 422 423static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) 424{ 425 Byte allAreDefined; 426 UInt32 numDefined = numItems; 427 RINOK(SzReadByte(sd, &allAreDefined)); 428 if (!allAreDefined) 429 { 430 size_t numBytes = (numItems + 7) >> 3; 431 if (numBytes > sd->Size) 432 return SZ_ERROR_ARCHIVE; 433 numDefined = CountDefinedBits(sd->Data, numItems); 434 SKIP_DATA(sd, numBytes); 435 } 436 if (numDefined > (sd->Size >> 2)) 437 return SZ_ERROR_ARCHIVE; 438 SKIP_DATA(sd, (size_t)numDefined * 4); 439 return SZ_OK; 440} 441 442static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc) 443{ 444 RINOK(SzReadNumber32(sd, &p->NumPackStreams)); 445 446 RINOK(WaitId(sd, k7zIdSize)); 447 MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); 448 { 449 UInt64 sum = 0; 450 UInt32 i; 451 UInt32 numPackStreams = p->NumPackStreams; 452 for (i = 0; i < numPackStreams; i++) 453 { 454 UInt64 packSize; 455 p->PackPositions[i] = sum; 456 RINOK(ReadNumber(sd, &packSize)); 457 sum += packSize; 458 if (sum < packSize) 459 return SZ_ERROR_ARCHIVE; 460 } 461 p->PackPositions[i] = sum; 462 } 463 464 for (;;) 465 { 466 UInt64 type; 467 RINOK(ReadID(sd, &type)); 468 if (type == k7zIdEnd) 469 return SZ_OK; 470 if (type == k7zIdCRC) 471 { 472 /* CRC of packed streams is unused now */ 473 RINOK(SkipBitUi32s(sd, p->NumPackStreams)); 474 continue; 475 } 476 RINOK(SkipData(sd)); 477 } 478} 479 480/* 481static SRes SzReadSwitch(CSzData *sd) 482{ 483 Byte external; 484 RINOK(SzReadByte(sd, &external)); 485 return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; 486} 487*/ 488 489#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16 490 491SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes) 492{ 493 UInt32 numCoders, numBindPairs, numPackStreams, i; 494 UInt32 numInStreams = 0, numOutStreams = 0; 495 const Byte *dataStart = sd->Data; 496 Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX]; 497 498 RINOK(SzReadNumber32(sd, &numCoders)); 499 if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) 500 return SZ_ERROR_UNSUPPORTED; 501 f->NumCoders = numCoders; 502 503 for (i = 0; i < numCoders; i++) 504 { 505 Byte mainByte; 506 CSzCoderInfo *coder = f->Coders + i; 507 unsigned idSize, j; 508 UInt64 id; 509 RINOK(SzReadByte(sd, &mainByte)); 510 if ((mainByte & 0xC0) != 0) 511 return SZ_ERROR_UNSUPPORTED; 512 idSize = (unsigned)(mainByte & 0xF); 513 if (idSize > sizeof(id)) 514 return SZ_ERROR_UNSUPPORTED; 515 if (idSize > sd->Size) 516 return SZ_ERROR_ARCHIVE; 517 id = 0; 518 for (j = 0; j < idSize; j++) 519 { 520 id = ((id << 8) | *sd->Data); 521 sd->Data++; 522 sd->Size--; 523 } 524 if (id > (UInt32)0xFFFFFFFF) 525 return SZ_ERROR_UNSUPPORTED; 526 coder->MethodID = (UInt32)id; 527 528 coder->NumInStreams = 1; 529 coder->NumOutStreams = 1; 530 coder->PropsOffset = 0; 531 coder->PropsSize = 0; 532 533 if ((mainByte & 0x10) != 0) 534 { 535 UInt32 numStreams; 536 RINOK(SzReadNumber32(sd, &numStreams)); 537 if (numStreams > NUM_CODER_STREAMS_MAX) 538 return SZ_ERROR_UNSUPPORTED; 539 coder->NumInStreams = (Byte)numStreams; 540 RINOK(SzReadNumber32(sd, &numStreams)); 541 if (numStreams > NUM_CODER_STREAMS_MAX) 542 return SZ_ERROR_UNSUPPORTED; 543 coder->NumOutStreams = (Byte)numStreams; 544 } 545 if ((mainByte & 0x20) != 0) 546 { 547 UInt32 propsSize = 0; 548 RINOK(SzReadNumber32(sd, &propsSize)); 549 if (propsSize >= 0x40) 550 return SZ_ERROR_UNSUPPORTED; 551 if (propsSize > sd->Size) 552 return SZ_ERROR_ARCHIVE; 553 coder->PropsOffset = sd->Data - dataStart; 554 coder->PropsSize = (Byte)propsSize; 555 sd->Data += (size_t)propsSize; 556 sd->Size -= (size_t)propsSize; 557 } 558 numInStreams += coder->NumInStreams; 559 numOutStreams += coder->NumOutStreams; 560 } 561 562 if (numOutStreams == 0) 563 return SZ_ERROR_UNSUPPORTED; 564 565 f->NumBindPairs = numBindPairs = numOutStreams - 1; 566 if (numInStreams < numBindPairs) 567 return SZ_ERROR_ARCHIVE; 568 if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX) 569 return SZ_ERROR_UNSUPPORTED; 570 f->MainOutStream = 0; 571 f->NumPackStreams = numPackStreams = numInStreams - numBindPairs; 572 if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) 573 return SZ_ERROR_UNSUPPORTED; 574 for (i = 0; i < numInStreams; i++) 575 inStreamUsed[i] = False; 576 if (numBindPairs != 0) 577 { 578 Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX]; 579 580 if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX) 581 return SZ_ERROR_UNSUPPORTED; 582 583 for (i = 0; i < numOutStreams; i++) 584 outStreamUsed[i] = False; 585 586 for (i = 0; i < numBindPairs; i++) 587 { 588 CSzBindPair *bp = f->BindPairs + i; 589 RINOK(SzReadNumber32(sd, &bp->InIndex)); 590 if (bp->InIndex >= numInStreams) 591 return SZ_ERROR_ARCHIVE; 592 inStreamUsed[bp->InIndex] = True; 593 RINOK(SzReadNumber32(sd, &bp->OutIndex)); 594 if (bp->OutIndex >= numInStreams) 595 return SZ_ERROR_ARCHIVE; 596 outStreamUsed[bp->OutIndex] = True; 597 } 598 for (i = 0; i < numOutStreams; i++) 599 if (!outStreamUsed[i]) 600 { 601 f->MainOutStream = i; 602 break; 603 } 604 if (i == numOutStreams) 605 return SZ_ERROR_ARCHIVE; 606 } 607 608 if (numPackStreams == 1) 609 { 610 for (i = 0; i < numInStreams; i++) 611 if (!inStreamUsed[i]) 612 break; 613 if (i == numInStreams) 614 return SZ_ERROR_ARCHIVE; 615 f->PackStreams[0] = i; 616 } 617 else 618 for (i = 0; i < numPackStreams; i++) 619 { 620 RINOK(SzReadNumber32(sd, f->PackStreams + i)); 621 } 622 623 for (i = 0; i < numOutStreams; i++) 624 { 625 RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i)); 626 } 627 628 return SZ_OK; 629} 630 631static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) 632{ 633 CSzData sd; 634 sd = *sd2; 635 for (; num != 0; num--) 636 { 637 Byte firstByte, mask; 638 unsigned i; 639 SZ_READ_BYTE_2(firstByte); 640 if ((firstByte & 0x80) == 0) 641 continue; 642 if ((firstByte & 0x40) == 0) 643 { 644 if (sd.Size == 0) 645 return SZ_ERROR_ARCHIVE; 646 sd.Size--; 647 sd.Data++; 648 continue; 649 } 650 mask = 0x20; 651 for (i = 2; i < 8 && (firstByte & mask) != 0; i++) 652 mask >>= 1; 653 if (i > sd.Size) 654 return SZ_ERROR_ARCHIVE; 655 SKIP_DATA2(sd, i); 656 } 657 *sd2 = sd; 658 return SZ_OK; 659} 660 661#define k_InStreamUsed_MAX 64 662#define k_OutStreamUsed_MAX 64 663 664static SRes ReadUnpackInfo(CSzAr *p, 665 CSzData *sd2, 666 UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, 667 ISzAlloc *alloc) 668{ 669 CSzData sd; 670 Byte inStreamUsed[k_InStreamUsed_MAX]; 671 Byte outStreamUsed[k_OutStreamUsed_MAX]; 672 UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; 673 const Byte *startBufPtr; 674 Byte external; 675 676 RINOK(WaitId(sd2, k7zIdFolder)); 677 RINOK(SzReadNumber32(sd2, &numFolders)); 678 if (p->NumFolders > numFoldersMax) 679 return SZ_ERROR_UNSUPPORTED; 680 p->NumFolders = numFolders; 681 682 SZ_READ_BYTE_SD(sd2, external); 683 if (external == 0) 684 sd = *sd2; 685 else 686 { 687 UInt32 index; 688 SzReadNumber32(sd2, &index); 689 if (index >= numTempBufs) 690 return SZ_ERROR_ARCHIVE; 691 sd.Data = tempBufs[index].data; 692 sd.Size = tempBufs[index].size; 693 } 694 695 MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); 696 MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc); 697 MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); 698 699 startBufPtr = sd.Data; 700 701 packStreamIndex = 0; 702 numCodersOutStreams = 0; 703 704 for (fo = 0; fo < numFolders; fo++) 705 { 706 UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0; 707 708 p->FoCodersOffsets[fo] = sd.Data - startBufPtr; 709 RINOK(SzReadNumber32(&sd, &numCoders)); 710 if (numCoders > NUM_FOLDER_CODERS_MAX) 711 return SZ_ERROR_UNSUPPORTED; 712 713 for (ci = 0; ci < numCoders; ci++) 714 { 715 Byte mainByte; 716 unsigned idSize; 717 UInt32 coderInStreams, coderOutStreams; 718 719 SZ_READ_BYTE_2(mainByte); 720 if ((mainByte & 0xC0) != 0) 721 return SZ_ERROR_UNSUPPORTED; 722 idSize = (mainByte & 0xF); 723 if (idSize > 8) 724 return SZ_ERROR_UNSUPPORTED; 725 if (idSize > sd.Size) 726 return SZ_ERROR_ARCHIVE; 727 SKIP_DATA2(sd, idSize); 728 729 coderInStreams = 1; 730 coderOutStreams = 1; 731 if ((mainByte & 0x10) != 0) 732 { 733 RINOK(SzReadNumber32(&sd, &coderInStreams)); 734 RINOK(SzReadNumber32(&sd, &coderOutStreams)); 735 if (coderInStreams > NUM_CODER_STREAMS_MAX || 736 coderOutStreams > NUM_CODER_STREAMS_MAX) 737 return SZ_ERROR_UNSUPPORTED; 738 } 739 numInStreams += coderInStreams; 740 numOutStreams += coderOutStreams; 741 if ((mainByte & 0x20) != 0) 742 { 743 UInt32 propsSize; 744 RINOK(SzReadNumber32(&sd, &propsSize)); 745 if (propsSize > sd.Size) 746 return SZ_ERROR_ARCHIVE; 747 SKIP_DATA2(sd, propsSize); 748 } 749 } 750 751 { 752 UInt32 indexOfMainStream = 0; 753 UInt32 numPackStreams = 1; 754 if (numOutStreams != 1 || numInStreams != 1) 755 { 756 UInt32 i; 757 UInt32 numBindPairs = numOutStreams - 1; 758 if (numOutStreams == 0 || numInStreams < numBindPairs) 759 return SZ_ERROR_ARCHIVE; 760 761 if (numInStreams > k_InStreamUsed_MAX || 762 numOutStreams > k_OutStreamUsed_MAX) 763 return SZ_ERROR_UNSUPPORTED; 764 765 for (i = 0; i < numInStreams; i++) 766 inStreamUsed[i] = False; 767 for (i = 0; i < numOutStreams; i++) 768 outStreamUsed[i] = False; 769 770 for (i = 0; i < numBindPairs; i++) 771 { 772 UInt32 index; 773 RINOK(SzReadNumber32(&sd, &index)); 774 if (index >= numInStreams || inStreamUsed[index]) 775 return SZ_ERROR_ARCHIVE; 776 inStreamUsed[index] = True; 777 RINOK(SzReadNumber32(&sd, &index)); 778 if (index >= numInStreams || outStreamUsed[index]) 779 return SZ_ERROR_ARCHIVE; 780 outStreamUsed[index] = True; 781 } 782 783 numPackStreams = numInStreams - numBindPairs; 784 785 if (numPackStreams != 1) 786 for (i = 0; i < numPackStreams; i++) 787 { 788 UInt32 temp; 789 RINOK(SzReadNumber32(&sd, &temp)); 790 if (temp >= numInStreams) 791 return SZ_ERROR_ARCHIVE; 792 } 793 794 for (i = 0; i < numOutStreams; i++) 795 if (!outStreamUsed[i]) 796 { 797 indexOfMainStream = i; 798 break; 799 } 800 801 if (i == numOutStreams) 802 return SZ_ERROR_ARCHIVE; 803 } 804 p->FoStartPackStreamIndex[fo] = packStreamIndex; 805 p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream; 806 numCodersOutStreams += numOutStreams; 807 if (numCodersOutStreams < numOutStreams) 808 return SZ_ERROR_UNSUPPORTED; 809 packStreamIndex += numPackStreams; 810 if (packStreamIndex < numPackStreams) 811 return SZ_ERROR_UNSUPPORTED; 812 if (packStreamIndex > p->NumPackStreams) 813 return SZ_ERROR_ARCHIVE; 814 } 815 } 816 817 { 818 size_t dataSize = sd.Data - startBufPtr; 819 p->FoStartPackStreamIndex[fo] = packStreamIndex; 820 p->FoCodersOffsets[fo] = dataSize; 821 MY_ALLOC(Byte, p->CodersData, dataSize, alloc); 822 memcpy(p->CodersData, startBufPtr, dataSize); 823 } 824 825 if (external != 0) 826 { 827 if (sd.Size != 0) 828 return SZ_ERROR_ARCHIVE; 829 sd = *sd2; 830 } 831 832 RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); 833 834 // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); 835 { 836 size_t dataSize = sd.Size; 837 /* 838 UInt32 i; 839 for (i = 0; i < numCodersOutStreams; i++) 840 { 841 RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); 842 } 843 */ 844 RINOK(SkipNumbers(&sd, numCodersOutStreams)); 845 dataSize -= sd.Size; 846 MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc); 847 memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize); 848 p->UnpackSizesDataSize = dataSize; 849 /* 850 const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams); 851 if (data == NULL) 852 return SZ_ERROR_ARCHIVE; 853 sd.Size = sd.Data + sd.Size - data; 854 sd.Data = data; 855 */ 856 } 857 858 for (;;) 859 { 860 UInt64 type; 861 RINOK(ReadID(&sd, &type)); 862 if (type == k7zIdEnd) 863 { 864 *sd2 = sd; 865 return SZ_OK; 866 } 867 if (type == k7zIdCRC) 868 { 869 RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); 870 continue; 871 } 872 RINOK(SkipData(&sd)); 873 } 874} 875 876typedef struct 877{ 878 UInt32 NumTotalSubStreams; 879 UInt32 NumSubDigests; 880 CSzData sdNumSubStreams; 881 CSzData sdSizes; 882 CSzData sdCRCs; 883} CSubStreamInfo; 884 885#define SzUi32IndexMax (((UInt32)1 << 31) - 2) 886 887static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) 888{ 889 UInt64 type = 0; 890 UInt32 i; 891 UInt32 numSubDigests = 0; 892 UInt32 numFolders = p->NumFolders; 893 UInt32 numUnpackStreams = numFolders; 894 UInt32 numUnpackSizesInData = 0; 895 896 for (;;) 897 { 898 RINOK(ReadID(sd, &type)); 899 if (type == k7zIdNumUnpackStream) 900 { 901 ssi->sdNumSubStreams.Data = sd->Data; 902 numUnpackStreams = 0; 903 numSubDigests = 0; 904 for (i = 0; i < numFolders; i++) 905 { 906 UInt32 numStreams; 907 RINOK(SzReadNumber32(sd, &numStreams)); 908 if (numUnpackStreams > numUnpackStreams + numStreams) 909 return SZ_ERROR_UNSUPPORTED; 910 numUnpackStreams += numStreams; 911 if (numStreams != 0) 912 numUnpackSizesInData += (numStreams - 1); 913 if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) 914 numSubDigests += numStreams; 915 } 916 ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; 917 continue; 918 } 919 if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) 920 break; 921 RINOK(SkipData(sd)); 922 } 923 924 if (!ssi->sdNumSubStreams.Data) 925 { 926 numSubDigests = numFolders; 927 if (p->FolderCRCs.Defs) 928 numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); 929 } 930 931 ssi->NumTotalSubStreams = numUnpackStreams; 932 ssi->NumSubDigests = numSubDigests; 933 934 if (type == k7zIdSize) 935 { 936 ssi->sdSizes.Data = sd->Data; 937 RINOK(SkipNumbers(sd, numUnpackSizesInData)); 938 ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; 939 RINOK(ReadID(sd, &type)); 940 } 941 942 for (;;) 943 { 944 if (type == k7zIdEnd) 945 return SZ_OK; 946 if (type == k7zIdCRC) 947 { 948 ssi->sdCRCs.Data = sd->Data; 949 RINOK(SkipBitUi32s(sd, numSubDigests)); 950 ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; 951 } 952 else 953 { 954 RINOK(SkipData(sd)); 955 } 956 RINOK(ReadID(sd, &type)); 957 } 958} 959 960static SRes SzReadStreamsInfo(CSzAr *p, 961 CSzData *sd, 962 UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, 963 UInt64 *dataOffset, 964 CSubStreamInfo *ssi, 965 ISzAlloc *alloc) 966{ 967 UInt64 type; 968 969 SzData_Clear(&ssi->sdSizes); 970 SzData_Clear(&ssi->sdCRCs); 971 SzData_Clear(&ssi->sdNumSubStreams); 972 973 *dataOffset = 0; 974 RINOK(ReadID(sd, &type)); 975 if (type == k7zIdPackInfo) 976 { 977 RINOK(ReadNumber(sd, dataOffset)); 978 RINOK(ReadPackInfo(p, sd, alloc)); 979 RINOK(ReadID(sd, &type)); 980 } 981 if (type == k7zIdUnpackInfo) 982 { 983 RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); 984 RINOK(ReadID(sd, &type)); 985 } 986 if (type == k7zIdSubStreamsInfo) 987 { 988 RINOK(ReadSubStreamsInfo(p, sd, ssi)); 989 RINOK(ReadID(sd, &type)); 990 } 991 else 992 { 993 ssi->NumTotalSubStreams = p->NumFolders; 994 // ssi->NumSubDigests = 0; 995 } 996 997 return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); 998} 999 1000static SRes SzReadAndDecodePackedStreams( 1001 ILookInStream *inStream, 1002 CSzData *sd, 1003 CBuf *tempBufs, 1004 UInt32 numFoldersMax, 1005 UInt64 baseOffset, 1006 CSzAr *p, 1007 ISzAlloc *allocTemp) 1008{ 1009 UInt64 dataStartPos; 1010 UInt32 fo; 1011 CSubStreamInfo ssi; 1012 CSzData sdCodersUnpSizes; 1013 1014 RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); 1015 1016 dataStartPos += baseOffset; 1017 if (p->NumFolders == 0) 1018 return SZ_ERROR_ARCHIVE; 1019 1020 sdCodersUnpSizes.Data = p->UnpackSizesData; 1021 sdCodersUnpSizes.Size = p->UnpackSizesDataSize; 1022 for (fo = 0; fo < p->NumFolders; fo++) 1023 Buf_Init(tempBufs + fo); 1024 for (fo = 0; fo < p->NumFolders; fo++) 1025 { 1026 CBuf *tempBuf = tempBufs + fo; 1027 // folder = p->Folders; 1028 // unpackSize = SzAr_GetFolderUnpackSize(p, 0); 1029 UInt32 mix = (UInt32)p->FoSizesOffsets[fo]; 1030 UInt32 mainIndex = mix & 0xFF; 1031 UInt32 numOutStreams = mix >> 8; 1032 UInt32 si; 1033 UInt64 unpackSize = 0; 1034 p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; 1035 for (si = 0; si < numOutStreams; si++) 1036 { 1037 UInt64 curSize; 1038 RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); 1039 if (si == mainIndex) 1040 { 1041 unpackSize = curSize; 1042 break; 1043 } 1044 } 1045 if (si == numOutStreams) 1046 return SZ_ERROR_FAIL; 1047 if ((size_t)unpackSize != unpackSize) 1048 return SZ_ERROR_MEM; 1049 if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) 1050 return SZ_ERROR_MEM; 1051 } 1052 p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; 1053 1054 for (fo = 0; fo < p->NumFolders; fo++) 1055 { 1056 const CBuf *tempBuf = tempBufs + fo; 1057 RINOK(LookInStream_SeekTo(inStream, dataStartPos)); 1058 RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); 1059 if (SzBitWithVals_Check(&p->FolderCRCs, fo)) 1060 if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo]) 1061 return SZ_ERROR_CRC; 1062 } 1063 return SZ_OK; 1064} 1065 1066static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) 1067{ 1068 size_t pos = 0; 1069 *offsets++ = 0; 1070 if (numFiles == 0) 1071 return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; 1072 if (data[size - 2] != 0 || data[size - 1] != 0) 1073 return SZ_ERROR_ARCHIVE; 1074 do 1075 { 1076 const Byte *p; 1077 if (pos == size) 1078 return SZ_ERROR_ARCHIVE; 1079 for (p = data + pos; 1080 #ifdef _WIN32 1081 *(const UInt16 *)p != 0 1082 #else 1083 p[0] != 0 || p[1] != 0 1084 #endif 1085 ; p += 2); 1086 pos = p - data + 2; 1087 *offsets++ = (pos >> 1); 1088 } 1089 while (--numFiles); 1090 return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; 1091} 1092 1093static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, 1094 CSzData *sd2, 1095 const CBuf *tempBufs, UInt32 numTempBufs, 1096 ISzAlloc *alloc) 1097{ 1098 CSzData sd; 1099 UInt32 i; 1100 CNtfsFileTime *vals; 1101 Byte *defs; 1102 Byte external; 1103 RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); 1104 RINOK(SzReadByte(sd2, &external)); 1105 if (external == 0) 1106 sd = *sd2; 1107 else 1108 { 1109 UInt32 index; 1110 SzReadNumber32(sd2, &index); 1111 if (index >= numTempBufs) 1112 return SZ_ERROR_ARCHIVE; 1113 sd.Data = tempBufs[index].data; 1114 sd.Size = tempBufs[index].size; 1115 } 1116 MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc); 1117 vals = p->Vals; 1118 defs = p->Defs; 1119 for (i = 0; i < num; i++) 1120 if (SzBitArray_Check(defs, i)) 1121 { 1122 if (sd.Size < 8) 1123 return SZ_ERROR_ARCHIVE; 1124 vals[i].Low = GetUi32(sd.Data); 1125 vals[i].High = GetUi32(sd.Data + 4); 1126 SKIP_DATA2(sd, 8); 1127 } 1128 else 1129 vals[i].High = vals[i].Low = 0; 1130 if (external == 0) 1131 *sd2 = sd; 1132 return SZ_OK; 1133} 1134 1135#define NUM_ADDITIONAL_STREAMS_MAX 8 1136 1137static SRes SzReadHeader2( 1138 CSzArEx *p, /* allocMain */ 1139 CSzData *sd, 1140 // Byte **emptyStreamVector, /* allocTemp */ 1141 // Byte **emptyFileVector, /* allocTemp */ 1142 // Byte **lwtVector, /* allocTemp */ 1143 ILookInStream *inStream, 1144 CBuf *tempBufs, 1145 UInt32 *numTempBufs, 1146 ISzAlloc *allocMain, 1147 ISzAlloc *allocTemp 1148 ) 1149{ 1150 UInt64 type; 1151 UInt32 numFiles = 0; 1152 UInt32 numEmptyStreams = 0; 1153 UInt32 i; 1154 CSubStreamInfo ssi; 1155 const Byte *emptyStreams = 0; 1156 const Byte *emptyFiles = 0; 1157 1158 SzData_Clear(&ssi.sdSizes); 1159 SzData_Clear(&ssi.sdCRCs); 1160 SzData_Clear(&ssi.sdNumSubStreams); 1161 1162 ssi.NumSubDigests = 0; 1163 ssi.NumTotalSubStreams = 0; 1164 1165 RINOK(ReadID(sd, &type)); 1166 1167 if (type == k7zIdArchiveProperties) 1168 { 1169 for (;;) 1170 { 1171 UInt64 type; 1172 RINOK(ReadID(sd, &type)); 1173 if (type == k7zIdEnd) 1174 break; 1175 RINOK(SkipData(sd)); 1176 } 1177 RINOK(ReadID(sd, &type)); 1178 } 1179 1180 // if (type == k7zIdAdditionalStreamsInfo) return SZ_ERROR_UNSUPPORTED; 1181 1182 if (type == k7zIdAdditionalStreamsInfo) 1183 { 1184 CSzAr tempAr; 1185 SRes res; 1186 UInt32 numTempFolders; 1187 1188 SzAr_Init(&tempAr); 1189 res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, 1190 p->startPosAfterHeader, &tempAr, allocTemp); 1191 numTempFolders = tempAr.NumFolders; 1192 SzAr_Free(&tempAr, allocTemp); 1193 if (res != SZ_OK) 1194 return res; 1195 *numTempBufs = numTempFolders; 1196 RINOK(ReadID(sd, &type)); 1197 } 1198 1199 if (type == k7zIdMainStreamsInfo) 1200 { 1201 RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, 1202 &p->dataPos, &ssi, allocMain)); 1203 p->dataPos += p->startPosAfterHeader; 1204 RINOK(ReadID(sd, &type)); 1205 } 1206 1207 if (type == k7zIdEnd) 1208 { 1209 // *sd2 = sd; 1210 return SZ_OK; 1211 } 1212 if (type != k7zIdFilesInfo) 1213 return SZ_ERROR_ARCHIVE; 1214 1215 RINOK(SzReadNumber32(sd, &numFiles)); 1216 p->NumFiles = numFiles; 1217 1218 for (;;) 1219 { 1220 UInt64 type; 1221 UInt64 size; 1222 RINOK(ReadID(sd, &type)); 1223 if (type == k7zIdEnd) 1224 break; 1225 RINOK(ReadNumber(sd, &size)); 1226 if (size > sd->Size) 1227 return SZ_ERROR_ARCHIVE; 1228 if ((UInt64)(int)type != type) 1229 { 1230 SKIP_DATA(sd, size); 1231 } 1232 else switch((int)type) 1233 { 1234 case k7zIdName: 1235 { 1236 size_t namesSize; 1237 const Byte *namesData; 1238 Byte external; 1239 1240 SZ_READ_BYTE(external); 1241 if (external == 0) 1242 { 1243 namesSize = (size_t)size - 1; 1244 namesData = sd->Data; 1245 } 1246 else 1247 { 1248 UInt32 index; 1249 SzReadNumber32(sd, &index); 1250 if (index >= *numTempBufs) 1251 return SZ_ERROR_ARCHIVE; 1252 namesData = (tempBufs)[index].data; 1253 namesSize = (tempBufs)[index].size; 1254 } 1255 1256 if ((namesSize & 1) != 0) 1257 return SZ_ERROR_ARCHIVE; 1258 MY_ALLOC(Byte, p->FileNames, namesSize, allocMain); 1259 MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); 1260 memcpy(p->FileNames, namesData, namesSize); 1261 RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) 1262 if (external == 0) 1263 { 1264 SKIP_DATA(sd, namesSize); 1265 } 1266 break; 1267 } 1268 case k7zIdEmptyStream: 1269 { 1270 RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); 1271 numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); 1272 break; 1273 } 1274 case k7zIdEmptyFile: 1275 { 1276 RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); 1277 break; 1278 } 1279 case k7zIdWinAttrib: 1280 { 1281 Byte external; 1282 CSzData sdSwitch; 1283 CSzData *sdPtr; 1284 SzBitUi32s_Free(&p->Attribs, allocMain); 1285 RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); 1286 1287 SZ_READ_BYTE(external); 1288 if (external == 0) 1289 sdPtr = sd; 1290 else 1291 { 1292 UInt32 index; 1293 SzReadNumber32(sd, &index); 1294 if (index >= *numTempBufs) 1295 return SZ_ERROR_ARCHIVE; 1296 sdSwitch.Data = (tempBufs)[index].data; 1297 sdSwitch.Size = (tempBufs)[index].size; 1298 sdPtr = &sdSwitch; 1299 } 1300 RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); 1301 break; 1302 } 1303 /* 1304 case k7zParent: 1305 { 1306 SzBitUi32s_Free(&p->Parents, allocMain); 1307 RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); 1308 RINOK(SzReadSwitch(sd)); 1309 RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); 1310 break; 1311 } 1312 */ 1313 case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; 1314 case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; 1315 default: 1316 { 1317 SKIP_DATA(sd, size); 1318 } 1319 } 1320 } 1321 1322 if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) 1323 return SZ_ERROR_ARCHIVE; 1324 1325 for (;;) 1326 { 1327 UInt64 type; 1328 RINOK(ReadID(sd, &type)); 1329 if (type == k7zIdEnd) 1330 break; 1331 RINOK(SkipData(sd)); 1332 } 1333 1334 { 1335 UInt32 emptyFileIndex = 0; 1336 1337 UInt32 folderIndex = 0; 1338 UInt32 indexInFolder = 0; 1339 UInt64 unpackPos = 0; 1340 const Byte *digestsDefs = 0; 1341 const Byte *digestsVals = 0; 1342 UInt32 digestsValsIndex = 0; 1343 UInt32 digestIndex; 1344 Byte allDigestsDefined = 0; 1345 UInt32 curNumSubStreams = (UInt32)(Int32)-1; 1346 Byte isDirMask = 0; 1347 Byte crcMask = 0; 1348 Byte mask = 0x80; 1349 // size_t unpSizesOffset = 0; 1350 CSzData sdCodersUnpSizes; 1351 sdCodersUnpSizes.Data = p->db.UnpackSizesData; 1352 sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize; 1353 1354 MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain); 1355 MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain); 1356 MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); 1357 MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); 1358 1359 RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); 1360 1361 if (ssi.sdCRCs.Size != 0) 1362 { 1363 RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined)); 1364 if (allDigestsDefined) 1365 digestsVals = ssi.sdCRCs.Data; 1366 else 1367 { 1368 size_t numBytes = (ssi.NumSubDigests + 7) >> 3; 1369 digestsDefs = ssi.sdCRCs.Data; 1370 digestsVals = digestsDefs + numBytes; 1371 } 1372 } 1373 1374 digestIndex = 0; 1375 for (i = 0; i < numFiles; i++, mask >>= 1) 1376 { 1377 if (mask == 0) 1378 { 1379 UInt32 byteIndex = (i - 1) >> 3; 1380 p->IsDirs[byteIndex] = isDirMask; 1381 p->CRCs.Defs[byteIndex] = crcMask; 1382 isDirMask = 0; 1383 crcMask = 0; 1384 mask = 0x80; 1385 } 1386 1387 p->UnpackPositions[i] = unpackPos; 1388 p->CRCs.Vals[i] = 0; 1389 // p->CRCs.Defs[i] = 0; 1390 if (emptyStreams && SzBitArray_Check(emptyStreams , i)) 1391 { 1392 if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex)) 1393 isDirMask |= mask; 1394 emptyFileIndex++; 1395 if (indexInFolder == 0) 1396 { 1397 p->FileIndexToFolderIndexMap[i] = (UInt32)-1; 1398 continue; 1399 } 1400 } 1401 if (indexInFolder == 0) 1402 { 1403 /* 1404 v3.13 incorrectly worked with empty folders 1405 v4.07: Loop for skipping empty folders 1406 */ 1407 for (;;) 1408 { 1409 if (folderIndex >= p->db.NumFolders) 1410 return SZ_ERROR_ARCHIVE; 1411 p->FolderStartFileIndex[folderIndex] = i; 1412 if (curNumSubStreams == (UInt32)(Int32)-1); 1413 { 1414 curNumSubStreams = 1; 1415 if (ssi.sdNumSubStreams.Data != 0) 1416 { 1417 RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams)); 1418 } 1419 } 1420 if (curNumSubStreams != 0) 1421 break; 1422 curNumSubStreams = (UInt32)(Int32)-1; 1423 folderIndex++; // check it 1424 } 1425 } 1426 p->FileIndexToFolderIndexMap[i] = folderIndex; 1427 if (emptyStreams && SzBitArray_Check(emptyStreams , i)) 1428 continue; 1429 1430 indexInFolder++; 1431 if (indexInFolder >= curNumSubStreams) 1432 { 1433 UInt64 folderUnpackSize = 0; 1434 UInt64 startFolderUnpackPos; 1435 { 1436 UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex]; 1437 UInt32 mainIndex = mix & 0xFF; 1438 UInt32 numOutStreams = mix >> 8; 1439 UInt32 si; 1440 p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; 1441 for (si = 0; si < numOutStreams; si++) 1442 { 1443 UInt64 curSize; 1444 RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); 1445 if (si == mainIndex) 1446 { 1447 folderUnpackSize = curSize; 1448 break; 1449 } 1450 } 1451 if (si == numOutStreams) 1452 return SZ_ERROR_FAIL; 1453 } 1454 1455 // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); 1456 startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; 1457 if (folderUnpackSize < unpackPos - startFolderUnpackPos) 1458 return SZ_ERROR_ARCHIVE; 1459 unpackPos = startFolderUnpackPos + folderUnpackSize; 1460 1461 if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) 1462 { 1463 p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; 1464 crcMask |= mask; 1465 } 1466 else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) 1467 { 1468 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); 1469 digestsValsIndex++; 1470 crcMask |= mask; 1471 } 1472 folderIndex++; 1473 indexInFolder = 0; 1474 } 1475 else 1476 { 1477 UInt64 v; 1478 RINOK(ReadNumber(&ssi.sdSizes, &v)); 1479 unpackPos += v; 1480 if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) 1481 { 1482 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); 1483 digestsValsIndex++; 1484 crcMask |= mask; 1485 } 1486 } 1487 } 1488 if (mask != 0x80) 1489 { 1490 UInt32 byteIndex = (i - 1) >> 3; 1491 p->IsDirs[byteIndex] = isDirMask; 1492 p->CRCs.Defs[byteIndex] = crcMask; 1493 } 1494 p->UnpackPositions[i] = unpackPos; 1495 p->FolderStartFileIndex[folderIndex] = i; 1496 p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; 1497 } 1498 return SZ_OK; 1499} 1500 1501static SRes SzReadHeader( 1502 CSzArEx *p, 1503 CSzData *sd, 1504 ILookInStream *inStream, 1505 ISzAlloc *allocMain 1506 ,ISzAlloc *allocTemp 1507 ) 1508{ 1509 // Byte *emptyStreamVector = 0; 1510 // Byte *emptyFileVector = 0; 1511 // Byte *lwtVector = 0; 1512 UInt32 i; 1513 UInt32 numTempBufs = 0; 1514 SRes res; 1515 CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; 1516 1517 for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) 1518 Buf_Init(tempBufs + i); 1519 // SzBitUi32s_Init(&digests); 1520 1521 res = SzReadHeader2(p, sd, 1522 // &emptyStreamVector, 1523 // &emptyFileVector, 1524 // &lwtVector, 1525 inStream, 1526 tempBufs, &numTempBufs, 1527 allocMain, allocTemp 1528 ); 1529 1530 for (i = 0; i < numTempBufs; i++) 1531 Buf_Free(tempBufs + i, allocTemp); 1532 1533 // IAlloc_Free(allocTemp, emptyStreamVector); 1534 // IAlloc_Free(allocTemp, emptyFileVector); 1535 // IAlloc_Free(allocTemp, lwtVector); 1536 1537 RINOK(res); 1538 { 1539 if (sd->Size != 0) 1540 return SZ_ERROR_FAIL; 1541 } 1542 1543 return res; 1544} 1545 1546/* 1547static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) 1548{ 1549 const CSzFolder2 *f = p->Folders + folderIndex; 1550 1551 // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream]; 1552 1553 UInt32 si; 1554 CSzData sdCodersUnpSizes; 1555 sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset; 1556 sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset; 1557 for (si = 0; si < numOutStreams; si++) 1558 { 1559 UInt64 curSize; 1560 ReadNumber(&sdCodersUnpSizes, &curSize); 1561 if (si == mainIndex) 1562 return curSize; 1563 } 1564 return 0; 1565} 1566*/ 1567 1568static SRes SzArEx_Open2( 1569 CSzArEx *p, 1570 ILookInStream *inStream, 1571 ISzAlloc *allocMain, 1572 ISzAlloc *allocTemp) 1573{ 1574 Byte header[k7zStartHeaderSize]; 1575 Int64 startArcPos; 1576 UInt64 nextHeaderOffset, nextHeaderSize; 1577 size_t nextHeaderSizeT; 1578 UInt32 nextHeaderCRC; 1579 CBuf buf; 1580 SRes res; 1581 1582 startArcPos = 0; 1583 RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); 1584 1585 RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); 1586 1587 if (!TestSignatureCandidate(header)) 1588 return SZ_ERROR_NO_ARCHIVE; 1589 if (header[6] != k7zMajorVersion) 1590 return SZ_ERROR_UNSUPPORTED; 1591 1592 nextHeaderOffset = GetUi64(header + 12); 1593 nextHeaderSize = GetUi64(header + 20); 1594 nextHeaderCRC = GetUi32(header + 28); 1595 1596 p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; 1597 1598 if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) 1599 return SZ_ERROR_CRC; 1600 1601 nextHeaderSizeT = (size_t)nextHeaderSize; 1602 if (nextHeaderSizeT != nextHeaderSize) 1603 return SZ_ERROR_MEM; 1604 if (nextHeaderSizeT == 0) 1605 return SZ_OK; 1606 if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || 1607 nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) 1608 return SZ_ERROR_NO_ARCHIVE; 1609 1610 { 1611 Int64 pos = 0; 1612 RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); 1613 if ((UInt64)pos < startArcPos + nextHeaderOffset || 1614 (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || 1615 (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) 1616 return SZ_ERROR_INPUT_EOF; 1617 } 1618 1619 RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); 1620 1621 if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) 1622 return SZ_ERROR_MEM; 1623 1624 res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); 1625 if (res == SZ_OK) 1626 { 1627 res = SZ_ERROR_ARCHIVE; 1628 if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) 1629 { 1630 CSzData sd; 1631 UInt64 type; 1632 sd.Data = buf.data; 1633 sd.Size = buf.size; 1634 res = ReadID(&sd, &type); 1635 if (res == SZ_OK && type == k7zIdEncodedHeader) 1636 { 1637 CSzAr tempAr; 1638 CBuf tempBuf; 1639 Buf_Init(&tempBuf); 1640 1641 SzAr_Init(&tempAr); 1642 res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); 1643 SzAr_Free(&tempAr, allocTemp); 1644 1645 if (res != SZ_OK) 1646 { 1647 Buf_Free(&tempBuf, allocTemp); 1648 } 1649 else 1650 { 1651 Buf_Free(&buf, allocTemp); 1652 buf.data = tempBuf.data; 1653 buf.size = tempBuf.size; 1654 sd.Data = buf.data; 1655 sd.Size = buf.size; 1656 res = ReadID(&sd, &type); 1657 } 1658 } 1659 if (res == SZ_OK) 1660 { 1661 if (type == k7zIdHeader) 1662 { 1663 CSzData sd2; 1664 int ttt; 1665 for (ttt = 0; ttt < 1; ttt++) 1666 // for (ttt = 0; ttt < 40000; ttt++) 1667 { 1668 SzArEx_Free(p, allocMain); 1669 sd2 = sd; 1670 res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp 1671 ); 1672 if (res != SZ_OK) 1673 break; 1674 } 1675 1676 // res = SzReadHeader(p, &sd, allocMain, allocTemp); 1677 } 1678 else 1679 res = SZ_ERROR_UNSUPPORTED; 1680 } 1681 } 1682 } 1683 Buf_Free(&buf, allocTemp); 1684 return res; 1685} 1686 1687// #include <stdio.h> 1688 1689SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, 1690 ISzAlloc *allocMain, ISzAlloc *allocTemp) 1691{ 1692 SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); 1693 if (res != SZ_OK) 1694 SzArEx_Free(p, allocMain); 1695 // printf ("\nrrr=%d\n", rrr); 1696 return res; 1697} 1698 1699SRes SzArEx_Extract( 1700 const CSzArEx *p, 1701 ILookInStream *inStream, 1702 UInt32 fileIndex, 1703 UInt32 *blockIndex, 1704 Byte **tempBuf, 1705 size_t *outBufferSize, 1706 size_t *offset, 1707 size_t *outSizeProcessed, 1708 ISzAlloc *allocMain, 1709 ISzAlloc *allocTemp) 1710{ 1711 UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; 1712 SRes res = SZ_OK; 1713 *offset = 0; 1714 *outSizeProcessed = 0; 1715 if (folderIndex == (UInt32)-1) 1716 { 1717 IAlloc_Free(allocMain, *tempBuf); 1718 *blockIndex = folderIndex; 1719 *tempBuf = 0; 1720 *outBufferSize = 0; 1721 return SZ_OK; 1722 } 1723 1724 if (*tempBuf == 0 || *blockIndex != folderIndex) 1725 { 1726 // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); 1727 UInt64 unpackSizeSpec = 1728 p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] - 1729 p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; 1730 size_t unpackSize = (size_t)unpackSizeSpec; 1731 1732 if (unpackSize != unpackSizeSpec) 1733 return SZ_ERROR_MEM; 1734 *blockIndex = folderIndex; 1735 IAlloc_Free(allocMain, *tempBuf); 1736 *tempBuf = 0; 1737 1738 // RINOK(LookInStream_SeekTo(inStream, startOffset)); 1739 1740 if (res == SZ_OK) 1741 { 1742 *outBufferSize = unpackSize; 1743 if (unpackSize != 0) 1744 { 1745 *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize); 1746 if (*tempBuf == 0) 1747 res = SZ_ERROR_MEM; 1748 } 1749 if (res == SZ_OK) 1750 { 1751 res = SzAr_DecodeFolder(&p->db, folderIndex, 1752 inStream, 1753 p->dataPos, 1754 *tempBuf, unpackSize, allocTemp); 1755 if (res == SZ_OK) 1756 { 1757 if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex)) 1758 { 1759 if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex]) 1760 res = SZ_ERROR_CRC; 1761 } 1762 } 1763 } 1764 } 1765 } 1766 if (res == SZ_OK) 1767 { 1768 UInt64 unpackPos = p->UnpackPositions[fileIndex]; 1769 *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]); 1770 *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos); 1771 if (*offset + *outSizeProcessed > *outBufferSize) 1772 return SZ_ERROR_FAIL; 1773 if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) 1774 res = SZ_ERROR_CRC; 1775 } 1776 return res; 1777} 1778 1779 1780size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) 1781{ 1782 size_t offs = p->FileNameOffsets[fileIndex]; 1783 size_t len = p->FileNameOffsets[fileIndex + 1] - offs; 1784 if (dest != 0) 1785 { 1786 size_t i; 1787 const Byte *src = p->FileNames + offs * 2; 1788 for (i = 0; i < len; i++) 1789 dest[i] = GetUi16(src + i * 2); 1790 } 1791 return len; 1792} 1793 1794/* 1795size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) 1796{ 1797 size_t len; 1798 if (!p->FileNameOffsets) 1799 return 1; 1800 len = 0; 1801 for (;;) 1802 { 1803 UInt32 parent = (UInt32)(Int32)-1; 1804 len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; 1805 if SzBitWithVals_Check(&p->Parents, fileIndex) 1806 parent = p->Parents.Vals[fileIndex]; 1807 if (parent == (UInt32)(Int32)-1) 1808 return len; 1809 fileIndex = parent; 1810 } 1811} 1812 1813UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) 1814{ 1815 Bool needSlash; 1816 if (!p->FileNameOffsets) 1817 { 1818 *(--dest) = 0; 1819 return dest; 1820 } 1821 needSlash = False; 1822 for (;;) 1823 { 1824 UInt32 parent = (UInt32)(Int32)-1; 1825 size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; 1826 SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); 1827 if (needSlash) 1828 *(dest - 1) = '/'; 1829 needSlash = True; 1830 dest -= curLen; 1831 1832 if SzBitWithVals_Check(&p->Parents, fileIndex) 1833 parent = p->Parents.Vals[fileIndex]; 1834 if (parent == (UInt32)(Int32)-1) 1835 return dest; 1836 fileIndex = parent; 1837 } 1838} 1839*/ 1840