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