Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / other-licenses / 7zstub / src / C / 7zArcIn.c
blob70d7175e3d095d7bbc7d84b45a096c91b0b1e907
1 /* 7zArcIn.c -- 7z Input functions
2 2017-04-03 : Igor Pavlov : Public domain */
4 #include "Precomp.h"
6 #include <string.h>
8 #include "7z.h"
9 #include "7zBuf.h"
10 #include "7zCrc.h"
11 #include "CpuArch.h"
13 #define MY_ALLOC(T, p, size, alloc) { \
14 if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
16 #define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
18 #define MY_ALLOC_AND_CPY(to, size, from, alloc) \
19 { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
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) } }
24 #define k7zMajorVersion 0
26 enum EIdEnum
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
59 const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
61 #define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
63 static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
65 if (num == 0)
67 p->Defs = NULL;
68 p->Vals = NULL;
70 else
72 MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);
73 MY_ALLOC(UInt32, p->Vals, num, alloc);
75 return SZ_OK;
78 void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
80 ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
81 ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
84 #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
86 void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
88 ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
89 ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
93 static void SzAr_Init(CSzAr *p)
95 p->NumPackStreams = 0;
96 p->NumFolders = 0;
98 p->PackPositions = NULL;
99 SzBitUi32s_Init(&p->FolderCRCs);
101 p->FoCodersOffsets = NULL;
102 p->FoStartPackStreamIndex = NULL;
103 p->FoToCoderUnpackSizes = NULL;
104 p->FoToMainUnpackSizeIndex = NULL;
105 p->CoderUnpackSizes = NULL;
107 p->CodersData = NULL;
110 static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
112 ISzAlloc_Free(alloc, p->PackPositions);
113 SzBitUi32s_Free(&p->FolderCRCs, alloc);
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);
121 ISzAlloc_Free(alloc, p->CodersData);
123 SzAr_Init(p);
127 void SzArEx_Init(CSzArEx *p)
129 SzAr_Init(&p->db);
131 p->NumFiles = 0;
132 p->dataPos = 0;
134 p->UnpackPositions = NULL;
135 p->IsDirs = NULL;
137 p->FolderToFile = NULL;
138 p->FileToFolder = NULL;
140 p->FileNameOffsets = NULL;
141 p->FileNames = NULL;
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);
150 void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
152 ISzAlloc_Free(alloc, p->UnpackPositions);
153 ISzAlloc_Free(alloc, p->IsDirs);
155 ISzAlloc_Free(alloc, p->FolderToFile);
156 ISzAlloc_Free(alloc, p->FileToFolder);
158 ISzAlloc_Free(alloc, p->FileNameOffsets);
159 ISzAlloc_Free(alloc, p->FileNames);
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);
167 SzAr_Free(&p->db, alloc);
168 SzArEx_Init(p);
172 static int TestSignatureCandidate(const Byte *testBytes)
174 unsigned i;
175 for (i = 0; i < k7zSignatureSize; i++)
176 if (testBytes[i] != k7zSignature[i])
177 return 0;
178 return 1;
181 #define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; }
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++;
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); }
190 #define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \
191 dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);
193 static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
195 Byte firstByte, mask;
196 unsigned i;
197 UInt32 v;
199 SZ_READ_BYTE(firstByte);
200 if ((firstByte & 0x80) == 0)
202 *value = firstByte;
203 return SZ_OK;
205 SZ_READ_BYTE(v);
206 if ((firstByte & 0x40) == 0)
208 *value = (((UInt32)firstByte & 0x3F) << 8) | v;
209 return SZ_OK;
211 SZ_READ_BYTE(mask);
212 *value = v | ((UInt32)mask << 8);
213 mask = 0x20;
214 for (i = 2; i < 8; i++)
216 Byte b;
217 if ((firstByte & mask) == 0)
219 UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);
220 *value |= (highPart << (8 * i));
221 return SZ_OK;
223 SZ_READ_BYTE(b);
224 *value |= ((UInt64)b << (8 * i));
225 mask >>= 1;
227 return SZ_OK;
231 static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)
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)
240 *value = firstByte;
241 sd->Data++;
242 sd->Size--;
243 return SZ_OK;
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;
254 #define ReadID(sd, value) ReadNumber(sd, value)
256 static SRes SkipData(CSzData *sd)
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;
266 static SRes WaitId(CSzData *sd, UInt32 id)
268 for (;;)
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));
280 static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
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;
290 static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
292 Byte b = 0;
293 unsigned m = 0;
294 UInt32 sum = 0;
295 for (; numItems != 0; numItems--)
297 if (m == 0)
299 b = *bits++;
300 m = 8;
302 m--;
303 sum += ((b >> m) & 1);
305 return sum;
308 static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
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)
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;
325 MY_ALLOC(Byte, *v, numBytes, alloc);
326 v2 = *v;
327 memset(v2, 0xFF, (size_t)numBytes);
329 unsigned numBits = (unsigned)numItems & 7;
330 if (numBits != 0)
331 v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
333 return SZ_OK;
336 static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
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))
349 SZ_READ_32(vals[i]);
351 else
352 vals[i] = 0;
353 *sd2 = sd;
354 return SZ_OK;
357 static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
359 SzBitUi32s_Free(crcs, alloc);
360 RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
361 return ReadUi32s(sd, numItems, crcs, alloc);
364 static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
366 Byte allAreDefined;
367 UInt32 numDefined = numItems;
368 SZ_READ_BYTE(allAreDefined);
369 if (!allAreDefined)
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);
377 if (numDefined > (sd->Size >> 2))
378 return SZ_ERROR_ARCHIVE;
379 SKIP_DATA(sd, (size_t)numDefined * 4);
380 return SZ_OK;
383 static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc)
385 RINOK(SzReadNumber32(sd, &p->NumPackStreams));
387 RINOK(WaitId(sd, k7zIdSize));
388 MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc);
390 UInt64 sum = 0;
391 UInt32 i;
392 UInt32 numPackStreams = p->NumPackStreams;
393 for (i = 0; i < numPackStreams; i++)
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;
402 p->PackPositions[i] = sum;
405 for (;;)
407 UInt64 type;
408 RINOK(ReadID(sd, &type));
409 if (type == k7zIdEnd)
410 return SZ_OK;
411 if (type == k7zIdCRC)
413 /* CRC of packed streams is unused now */
414 RINOK(SkipBitUi32s(sd, p->NumPackStreams));
415 continue;
417 RINOK(SkipData(sd));
422 static SRes SzReadSwitch(CSzData *sd)
424 Byte external;
425 RINOK(SzReadByte(sd, &external));
426 return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
430 #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
432 SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)
434 UInt32 numCoders, i;
435 UInt32 numInStreams = 0;
436 const Byte *dataStart = sd->Data;
438 f->NumCoders = 0;
439 f->NumBonds = 0;
440 f->NumPackStreams = 0;
441 f->UnpackStream = 0;
443 RINOK(SzReadNumber32(sd, &numCoders));
444 if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
445 return SZ_ERROR_UNSUPPORTED;
447 for (i = 0; i < numCoders; i++)
449 Byte mainByte;
450 CSzCoderInfo *coder = f->Coders + i;
451 unsigned idSize, j;
452 UInt64 id;
454 SZ_READ_BYTE(mainByte);
455 if ((mainByte & 0xC0) != 0)
456 return SZ_ERROR_UNSUPPORTED;
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++)
466 id = ((id << 8) | *sd->Data);
467 sd->Data++;
468 sd->Size--;
470 if (id > (UInt32)0xFFFFFFFF)
471 return SZ_ERROR_UNSUPPORTED;
472 coder->MethodID = (UInt32)id;
474 coder->NumStreams = 1;
475 coder->PropsOffset = 0;
476 coder->PropsSize = 0;
478 if ((mainByte & 0x10) != 0)
480 UInt32 numStreams;
482 RINOK(SzReadNumber32(sd, &numStreams));
483 if (numStreams > k_NumCodersStreams_in_Folder_MAX)
484 return SZ_ERROR_UNSUPPORTED;
485 coder->NumStreams = (Byte)numStreams;
487 RINOK(SzReadNumber32(sd, &numStreams));
488 if (numStreams != 1)
489 return SZ_ERROR_UNSUPPORTED;
492 numInStreams += coder->NumStreams;
494 if (numInStreams > k_NumCodersStreams_in_Folder_MAX)
495 return SZ_ERROR_UNSUPPORTED;
497 if ((mainByte & 0x20) != 0)
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;
513 if (numInStreams == 1 && numCoders == 1)
515 f->NumPackStreams = 1;
516 f->PackStreams[0] = 0;
518 else
521 Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];
522 UInt32 numBonds, numPackStreams;
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;
531 numPackStreams = numInStreams - numBonds;
532 if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
533 return SZ_ERROR_UNSUPPORTED;
534 f->NumPackStreams = numPackStreams;
536 for (i = 0; i < numInStreams; i++)
537 streamUsed[i] = False;
539 if (numBonds != 0)
541 Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];
543 for (i = 0; i < numCoders; i++)
544 coderUsed[i] = False;
546 for (i = 0; i < numBonds; i++)
548 CSzBond *bp = f->Bonds + i;
550 RINOK(SzReadNumber32(sd, &bp->InIndex));
551 if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])
552 return SZ_ERROR_ARCHIVE;
553 streamUsed[bp->InIndex] = True;
555 RINOK(SzReadNumber32(sd, &bp->OutIndex));
556 if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])
557 return SZ_ERROR_ARCHIVE;
558 coderUsed[bp->OutIndex] = True;
561 for (i = 0; i < numCoders; i++)
562 if (!coderUsed[i])
564 f->UnpackStream = i;
565 break;
568 if (i == numCoders)
569 return SZ_ERROR_ARCHIVE;
572 if (numPackStreams == 1)
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;
581 else
582 for (i = 0; i < numPackStreams; i++)
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;
593 f->NumCoders = numCoders;
595 return SZ_OK;
599 static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
601 CSzData sd;
602 sd = *sd2;
603 for (; num != 0; num--)
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)
612 if (sd.Size == 0)
613 return SZ_ERROR_ARCHIVE;
614 sd.Size--;
615 sd.Data++;
616 continue;
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);
625 *sd2 = sd;
626 return SZ_OK;
630 #define k_Scan_NumCoders_MAX 64
631 #define k_Scan_NumCodersStreams_in_Folder_MAX 64
634 static SRes ReadUnpackInfo(CSzAr *p,
635 CSzData *sd2,
636 UInt32 numFoldersMax,
637 const CBuf *tempBufs, UInt32 numTempBufs,
638 ISzAllocPtr alloc)
640 CSzData sd;
642 UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
643 const Byte *startBufPtr;
644 Byte external;
646 RINOK(WaitId(sd2, k7zIdFolder));
648 RINOK(SzReadNumber32(sd2, &numFolders));
649 if (numFolders > numFoldersMax)
650 return SZ_ERROR_UNSUPPORTED;
651 p->NumFolders = numFolders;
653 SZ_READ_BYTE_SD(sd2, external);
654 if (external == 0)
655 sd = *sd2;
656 else
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;
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);
671 startBufPtr = sd.Data;
673 packStreamIndex = 0;
674 numCodersOutStreams = 0;
676 for (fo = 0; fo < numFolders; fo++)
678 UInt32 numCoders, ci, numInStreams = 0;
680 p->FoCodersOffsets[fo] = sd.Data - startBufPtr;
682 RINOK(SzReadNumber32(&sd, &numCoders));
683 if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
684 return SZ_ERROR_UNSUPPORTED;
686 for (ci = 0; ci < numCoders; ci++)
688 Byte mainByte;
689 unsigned idSize;
690 UInt32 coderInStreams;
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);
702 coderInStreams = 1;
704 if ((mainByte & 0x10) != 0)
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;
713 numInStreams += coderInStreams;
715 if ((mainByte & 0x20) != 0)
717 UInt32 propsSize;
718 RINOK(SzReadNumber32(&sd, &propsSize));
719 if (propsSize > sd.Size)
720 return SZ_ERROR_ARCHIVE;
721 SKIP_DATA2(sd, propsSize);
726 UInt32 indexOfMainStream = 0;
727 UInt32 numPackStreams = 1;
729 if (numCoders != 1 || numInStreams != 1)
731 Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
732 Byte coderUsed[k_Scan_NumCoders_MAX];
734 UInt32 i;
735 UInt32 numBonds = numCoders - 1;
736 if (numInStreams < numBonds)
737 return SZ_ERROR_ARCHIVE;
739 if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
740 return SZ_ERROR_UNSUPPORTED;
742 for (i = 0; i < numInStreams; i++)
743 streamUsed[i] = False;
744 for (i = 0; i < numCoders; i++)
745 coderUsed[i] = False;
747 for (i = 0; i < numBonds; i++)
749 UInt32 index;
751 RINOK(SzReadNumber32(&sd, &index));
752 if (index >= numInStreams || streamUsed[index])
753 return SZ_ERROR_ARCHIVE;
754 streamUsed[index] = True;
756 RINOK(SzReadNumber32(&sd, &index));
757 if (index >= numCoders || coderUsed[index])
758 return SZ_ERROR_ARCHIVE;
759 coderUsed[index] = True;
762 numPackStreams = numInStreams - numBonds;
764 if (numPackStreams != 1)
765 for (i = 0; i < numPackStreams; i++)
767 UInt32 index;
768 RINOK(SzReadNumber32(&sd, &index));
769 if (index >= numInStreams || streamUsed[index])
770 return SZ_ERROR_ARCHIVE;
771 streamUsed[index] = True;
774 for (i = 0; i < numCoders; i++)
775 if (!coderUsed[i])
777 indexOfMainStream = i;
778 break;
781 if (i == numCoders)
782 return SZ_ERROR_ARCHIVE;
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;
797 p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
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);
806 if (external != 0)
808 if (sd.Size != 0)
809 return SZ_ERROR_ARCHIVE;
810 sd = *sd2;
813 RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
815 MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
817 UInt32 i;
818 for (i = 0; i < numCodersOutStreams; i++)
820 RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));
824 for (;;)
826 UInt64 type;
827 RINOK(ReadID(&sd, &type));
828 if (type == k7zIdEnd)
830 *sd2 = sd;
831 return SZ_OK;
833 if (type == k7zIdCRC)
835 RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));
836 continue;
838 RINOK(SkipData(&sd));
843 UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
845 return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
849 typedef struct
851 UInt32 NumTotalSubStreams;
852 UInt32 NumSubDigests;
853 CSzData sdNumSubStreams;
854 CSzData sdSizes;
855 CSzData sdCRCs;
856 } CSubStreamInfo;
859 static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
861 UInt64 type = 0;
862 UInt32 numSubDigests = 0;
863 UInt32 numFolders = p->NumFolders;
864 UInt32 numUnpackStreams = numFolders;
865 UInt32 numUnpackSizesInData = 0;
867 for (;;)
869 RINOK(ReadID(sd, &type));
870 if (type == k7zIdNumUnpackStream)
872 UInt32 i;
873 ssi->sdNumSubStreams.Data = sd->Data;
874 numUnpackStreams = 0;
875 numSubDigests = 0;
876 for (i = 0; i < numFolders; i++)
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;
888 ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;
889 continue;
891 if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
892 break;
893 RINOK(SkipData(sd));
896 if (!ssi->sdNumSubStreams.Data)
898 numSubDigests = numFolders;
899 if (p->FolderCRCs.Defs)
900 numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
903 ssi->NumTotalSubStreams = numUnpackStreams;
904 ssi->NumSubDigests = numSubDigests;
906 if (type == k7zIdSize)
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));
914 for (;;)
916 if (type == k7zIdEnd)
917 return SZ_OK;
918 if (type == k7zIdCRC)
920 ssi->sdCRCs.Data = sd->Data;
921 RINOK(SkipBitUi32s(sd, numSubDigests));
922 ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;
924 else
926 RINOK(SkipData(sd));
928 RINOK(ReadID(sd, &type));
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)
939 UInt64 type;
941 SzData_Clear(&ssi->sdSizes);
942 SzData_Clear(&ssi->sdCRCs);
943 SzData_Clear(&ssi->sdNumSubStreams);
945 *dataOffset = 0;
946 RINOK(ReadID(sd, &type));
947 if (type == k7zIdPackInfo)
949 RINOK(ReadNumber(sd, dataOffset));
950 RINOK(ReadPackInfo(p, sd, alloc));
951 RINOK(ReadID(sd, &type));
953 if (type == k7zIdUnpackInfo)
955 RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));
956 RINOK(ReadID(sd, &type));
958 if (type == k7zIdSubStreamsInfo)
960 RINOK(ReadSubStreamsInfo(p, sd, ssi));
961 RINOK(ReadID(sd, &type));
963 else
965 ssi->NumTotalSubStreams = p->NumFolders;
966 // ssi->NumSubDigests = 0;
969 return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
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)
981 UInt64 dataStartPos;
982 UInt32 fo;
983 CSubStreamInfo ssi;
985 RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));
987 dataStartPos += baseOffset;
988 if (p->NumFolders == 0)
989 return SZ_ERROR_ARCHIVE;
991 for (fo = 0; fo < p->NumFolders; fo++)
992 Buf_Init(tempBufs + fo);
994 for (fo = 0; fo < p->NumFolders; fo++)
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;
1004 for (fo = 0; fo < p->NumFolders; fo++)
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));
1011 return SZ_OK;
1014 static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
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;
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);
1039 while (--numFiles);
1040 return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1043 static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1044 CSzData *sd2,
1045 const CBuf *tempBufs, UInt32 numTempBufs,
1046 ISzAllocPtr alloc)
1048 CSzData sd;
1049 UInt32 i;
1050 CNtfsFileTime *vals;
1051 Byte *defs;
1052 Byte external;
1054 RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
1056 SZ_READ_BYTE_SD(sd2, external);
1057 if (external == 0)
1058 sd = *sd2;
1059 else
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;
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))
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);
1081 else
1082 vals[i].High = vals[i].Low = 0;
1084 if (external == 0)
1085 *sd2 = sd;
1087 return SZ_OK;
1091 #define NUM_ADDITIONAL_STREAMS_MAX 8
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
1103 CSubStreamInfo ssi;
1106 UInt64 type;
1108 SzData_Clear(&ssi.sdSizes);
1109 SzData_Clear(&ssi.sdCRCs);
1110 SzData_Clear(&ssi.sdNumSubStreams);
1112 ssi.NumSubDigests = 0;
1113 ssi.NumTotalSubStreams = 0;
1115 RINOK(ReadID(sd, &type));
1117 if (type == k7zIdArchiveProperties)
1119 for (;;)
1121 UInt64 type2;
1122 RINOK(ReadID(sd, &type2));
1123 if (type2 == k7zIdEnd)
1124 break;
1125 RINOK(SkipData(sd));
1127 RINOK(ReadID(sd, &type));
1130 if (type == k7zIdAdditionalStreamsInfo)
1132 CSzAr tempAr;
1133 SRes res;
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);
1141 if (res != SZ_OK)
1142 return res;
1143 RINOK(ReadID(sd, &type));
1146 if (type == k7zIdMainStreamsInfo)
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));
1154 if (type == k7zIdEnd)
1156 return SZ_OK;
1159 if (type != k7zIdFilesInfo)
1160 return SZ_ERROR_ARCHIVE;
1164 UInt32 numFiles = 0;
1165 UInt32 numEmptyStreams = 0;
1166 const Byte *emptyStreams = NULL;
1167 const Byte *emptyFiles = NULL;
1169 RINOK(SzReadNumber32(sd, &numFiles));
1170 p->NumFiles = numFiles;
1172 for (;;)
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;
1183 if (type >= ((UInt32)1 << 8))
1185 SKIP_DATA(sd, size);
1187 else switch ((unsigned)type)
1189 case k7zIdName:
1191 size_t namesSize;
1192 const Byte *namesData;
1193 Byte external;
1195 SZ_READ_BYTE(external);
1196 if (external == 0)
1198 namesSize = (size_t)size - 1;
1199 namesData = sd->Data;
1201 else
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;
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)
1218 SKIP_DATA(sd, namesSize);
1220 break;
1222 case k7zIdEmptyStream:
1224 RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
1225 numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1226 emptyFiles = NULL;
1227 break;
1229 case k7zIdEmptyFile:
1231 RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));
1232 break;
1234 case k7zIdWinAttrib:
1236 Byte external;
1237 CSzData sdSwitch;
1238 CSzData *sdPtr;
1239 SzBitUi32s_Free(&p->Attribs, allocMain);
1240 RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));
1242 SZ_READ_BYTE(external);
1243 if (external == 0)
1244 sdPtr = sd;
1245 else
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;
1255 RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));
1256 break;
1259 case k7zParent:
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;
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:
1272 SKIP_DATA(sd, size);
1277 if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1278 return SZ_ERROR_ARCHIVE;
1280 for (;;)
1282 UInt64 type;
1283 RINOK(ReadID(sd, &type));
1284 if (type == k7zIdEnd)
1285 break;
1286 RINOK(SkipData(sd));
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;
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);
1310 RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
1312 if (ssi.sdCRCs.Size != 0)
1314 SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);
1315 if (allDigestsDefined)
1316 digestsVals = ssi.sdCRCs.Data;
1317 else
1319 size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1320 digestsDefs = ssi.sdCRCs.Data;
1321 digestsVals = digestsDefs + numBytes;
1325 digestIndex = 0;
1327 for (i = 0; i < numFiles; i++, mask >>= 1)
1329 if (mask == 0)
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;
1339 p->UnpackPositions[i] = unpackPos;
1340 p->CRCs.Vals[i] = 0;
1342 if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1344 if (emptyFiles)
1346 if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
1347 isDirMask |= mask;
1348 emptyFileIndex++;
1350 else
1351 isDirMask |= mask;
1352 if (remSubStreams == 0)
1354 p->FileToFolder[i] = (UInt32)-1;
1355 continue;
1359 if (remSubStreams == 0)
1361 for (;;)
1363 if (folderIndex >= p->db.NumFolders)
1364 return SZ_ERROR_ARCHIVE;
1365 p->FolderToFile[folderIndex] = i;
1366 numSubStreams = 1;
1367 if (ssi.sdNumSubStreams.Data)
1369 RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
1371 remSubStreams = numSubStreams;
1372 if (numSubStreams != 0)
1373 break;
1375 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1376 unpackPos += folderUnpackSize;
1377 if (unpackPos < folderUnpackSize)
1378 return SZ_ERROR_ARCHIVE;
1381 folderIndex++;
1385 p->FileToFolder[i] = folderIndex;
1387 if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1388 continue;
1390 if (--remSubStreams == 0)
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;
1400 if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
1402 p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1403 crcMask |= mask;
1405 else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1407 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1408 digestsValsIndex++;
1409 crcMask |= mask;
1412 folderIndex++;
1414 else
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)))
1423 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1424 digestsValsIndex++;
1425 crcMask |= mask;
1430 if (mask != 0x80)
1432 UInt32 byteIndex = (i - 1) >> 3;
1433 p->IsDirs[byteIndex] = isDirMask;
1434 p->CRCs.Defs[byteIndex] = crcMask;
1437 p->UnpackPositions[i] = unpackPos;
1439 if (remSubStreams != 0)
1440 return SZ_ERROR_ARCHIVE;
1442 for (;;)
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;
1454 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1455 unpackPos += folderUnpackSize;
1456 if (unpackPos < folderUnpackSize)
1457 return SZ_ERROR_ARCHIVE;
1460 folderIndex++;
1463 if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
1464 return SZ_ERROR_ARCHIVE;
1467 return SZ_OK;
1471 static SRes SzReadHeader(
1472 CSzArEx *p,
1473 CSzData *sd,
1474 ILookInStream *inStream,
1475 ISzAllocPtr allocMain,
1476 ISzAllocPtr allocTemp)
1478 UInt32 i;
1479 UInt32 numTempBufs = 0;
1480 SRes res;
1481 CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1483 for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1484 Buf_Init(tempBufs + i);
1486 res = SzReadHeader2(p, sd, inStream,
1487 tempBufs, &numTempBufs,
1488 allocMain, allocTemp);
1490 for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1491 Buf_Free(tempBufs + i, allocTemp);
1493 RINOK(res);
1495 if (sd->Size != 0)
1496 return SZ_ERROR_FAIL;
1498 return res;
1501 static SRes SzArEx_Open2(
1502 CSzArEx *p,
1503 ILookInStream *inStream,
1504 ISzAllocPtr allocMain,
1505 ISzAllocPtr allocTemp)
1507 Byte header[k7zStartHeaderSize];
1508 Int64 startArcPos;
1509 UInt64 nextHeaderOffset, nextHeaderSize;
1510 size_t nextHeaderSizeT;
1511 UInt32 nextHeaderCRC;
1512 CBuf buf;
1513 SRes res;
1515 startArcPos = 0;
1516 RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR));
1518 RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1520 if (!TestSignatureCandidate(header))
1521 return SZ_ERROR_NO_ARCHIVE;
1522 if (header[6] != k7zMajorVersion)
1523 return SZ_ERROR_UNSUPPORTED;
1525 nextHeaderOffset = GetUi64(header + 12);
1526 nextHeaderSize = GetUi64(header + 20);
1527 nextHeaderCRC = GetUi32(header + 28);
1529 p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
1531 if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1532 return SZ_ERROR_CRC;
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;
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;
1552 RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
1554 if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1555 return SZ_ERROR_MEM;
1557 res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1559 if (res == SZ_OK)
1561 res = SZ_ERROR_ARCHIVE;
1562 if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1564 CSzData sd;
1565 UInt64 type;
1566 sd.Data = buf.data;
1567 sd.Size = buf.size;
1569 res = ReadID(&sd, &type);
1571 if (res == SZ_OK && type == k7zIdEncodedHeader)
1573 CSzAr tempAr;
1574 CBuf tempBuf;
1575 Buf_Init(&tempBuf);
1577 SzAr_Init(&tempAr);
1578 res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1579 SzAr_Free(&tempAr, allocTemp);
1581 if (res != SZ_OK)
1583 Buf_Free(&tempBuf, allocTemp);
1585 else
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);
1596 if (res == SZ_OK)
1598 if (type == k7zIdHeader)
1601 CSzData sd2;
1602 unsigned ttt;
1603 for (ttt = 0; ttt < 40000; ttt++)
1605 SzArEx_Free(p, allocMain);
1606 sd2 = sd;
1607 res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1608 if (res != SZ_OK)
1609 break;
1612 res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1614 else
1615 res = SZ_ERROR_UNSUPPORTED;
1620 Buf_Free(&buf, allocTemp);
1621 return res;
1625 SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
1626 ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
1628 SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1629 if (res != SZ_OK)
1630 SzArEx_Free(p, allocMain);
1631 return res;
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)
1647 UInt32 folderIndex = p->FileToFolder[fileIndex];
1648 SRes res = SZ_OK;
1650 *offset = 0;
1651 *outSizeProcessed = 0;
1653 if (folderIndex == (UInt32)-1)
1655 ISzAlloc_Free(allocMain, *tempBuf);
1656 *blockIndex = folderIndex;
1657 *tempBuf = NULL;
1658 *outBufferSize = 0;
1659 return SZ_OK;
1662 if (*tempBuf == NULL || *blockIndex != folderIndex)
1664 UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1666 UInt64 unpackSizeSpec =
1667 p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
1668 p->UnpackPositions[p->FolderToFile[folderIndex]];
1670 size_t unpackSize = (size_t)unpackSizeSpec;
1672 if (unpackSize != unpackSizeSpec)
1673 return SZ_ERROR_MEM;
1674 *blockIndex = folderIndex;
1675 ISzAlloc_Free(allocMain, *tempBuf);
1676 *tempBuf = NULL;
1678 if (res == SZ_OK)
1680 *outBufferSize = unpackSize;
1681 if (unpackSize != 0)
1683 *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
1684 if (*tempBuf == NULL)
1685 res = SZ_ERROR_MEM;
1688 if (res == SZ_OK)
1690 res = SzAr_DecodeFolder(&p->db, folderIndex,
1691 inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
1696 if (res == SZ_OK)
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;
1708 return res;
1712 size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1714 size_t offs = p->FileNameOffsets[fileIndex];
1715 size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1716 if (dest != 0)
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);
1723 return len;
1727 size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1729 size_t len;
1730 if (!p->FileNameOffsets)
1731 return 1;
1732 len = 0;
1733 for (;;)
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;
1745 UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1747 Bool needSlash;
1748 if (!p->FileNameOffsets)
1750 *(--dest) = 0;
1751 return dest;
1753 needSlash = False;
1754 for (;;)
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;
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;