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