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