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