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