tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

7zArcIn.c (45462B)


      1 /* 7zArcIn.c -- 7z Input functions
      2 2017-04-03 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 #include <string.h>
      7 
      8 #include "7z.h"
      9 #include "7zBuf.h"
     10 #include "7zCrc.h"
     11 #include "CpuArch.h"
     12 
     13 #define MY_ALLOC(T, p, size, alloc) { \
     14  if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
     15 
     16 #define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
     17 
     18 #define MY_ALLOC_AND_CPY(to, size, from, alloc) \
     19  { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
     20 
     21 #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
     22  { if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
     23 
     24 #define k7zMajorVersion 0
     25 
     26 enum EIdEnum
     27 {
     28  k7zIdEnd,
     29  k7zIdHeader,
     30  k7zIdArchiveProperties,
     31  k7zIdAdditionalStreamsInfo,
     32  k7zIdMainStreamsInfo,
     33  k7zIdFilesInfo,
     34  k7zIdPackInfo,
     35  k7zIdUnpackInfo,
     36  k7zIdSubStreamsInfo,
     37  k7zIdSize,
     38  k7zIdCRC,
     39  k7zIdFolder,
     40  k7zIdCodersUnpackSize,
     41  k7zIdNumUnpackStream,
     42  k7zIdEmptyStream,
     43  k7zIdEmptyFile,
     44  k7zIdAnti,
     45  k7zIdName,
     46  k7zIdCTime,
     47  k7zIdATime,
     48  k7zIdMTime,
     49  k7zIdWinAttrib,
     50  k7zIdComment,
     51  k7zIdEncodedHeader,
     52  k7zIdStartPos,
     53  k7zIdDummy
     54  // k7zNtSecure,
     55  // k7zParent,
     56  // k7zIsReal
     57 };
     58 
     59 const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
     60 
     61 #define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
     62 
     63 static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
     64 {
     65  if (num == 0)
     66  {
     67    p->Defs = NULL;
     68    p->Vals = NULL;
     69  }
     70  else
     71  {
     72    MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);
     73    MY_ALLOC(UInt32, p->Vals, num, alloc);
     74  }
     75  return SZ_OK;
     76 }
     77 
     78 void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
     79 {
     80  ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
     81  ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
     82 }
     83 
     84 #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
     85 
     86 void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
     87 {
     88  ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
     89  ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
     90 }
     91 
     92 
     93 static void SzAr_Init(CSzAr *p)
     94 {
     95  p->NumPackStreams = 0;
     96  p->NumFolders = 0;
     97  
     98  p->PackPositions = NULL;
     99  SzBitUi32s_Init(&p->FolderCRCs);
    100 
    101  p->FoCodersOffsets = NULL;
    102  p->FoStartPackStreamIndex = NULL;
    103  p->FoToCoderUnpackSizes = NULL;
    104  p->FoToMainUnpackSizeIndex = NULL;
    105  p->CoderUnpackSizes = NULL;
    106 
    107  p->CodersData = NULL;
    108 }
    109 
    110 static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
    111 {
    112  ISzAlloc_Free(alloc, p->PackPositions);
    113  SzBitUi32s_Free(&p->FolderCRCs, alloc);
    114 
    115  ISzAlloc_Free(alloc, p->FoCodersOffsets);
    116  ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
    117  ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
    118  ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
    119  ISzAlloc_Free(alloc, p->CoderUnpackSizes);
    120  
    121  ISzAlloc_Free(alloc, p->CodersData);
    122 
    123  SzAr_Init(p);
    124 }
    125 
    126 
    127 void 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 
    150 void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
    151 {
    152  ISzAlloc_Free(alloc, p->UnpackPositions);
    153  ISzAlloc_Free(alloc, p->IsDirs);
    154 
    155  ISzAlloc_Free(alloc, p->FolderToFile);
    156  ISzAlloc_Free(alloc, p->FileToFolder);
    157 
    158  ISzAlloc_Free(alloc, p->FileNameOffsets);
    159  ISzAlloc_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 
    172 static 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 
    193 static 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 
    231 static 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 
    256 static 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 
    266 static 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 
    280 static 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 
    290 static 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 
    308 static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr 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[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
    332  }
    333  return SZ_OK;
    334 }
    335 
    336 static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr 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 
    357 static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
    358 {
    359  SzBitUi32s_Free(crcs, alloc);
    360  RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
    361  return ReadUi32s(sd, numItems, crcs, alloc);
    362 }
    363 
    364 static 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 
    383 static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr 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 /*
    422 static 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 
    432 SRes 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 
    599 static 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 
    634 static SRes ReadUnpackInfo(CSzAr *p,
    635    CSzData *sd2,
    636    UInt32 numFoldersMax,
    637    const CBuf *tempBufs, UInt32 numTempBufs,
    638    ISzAllocPtr 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 
    843 UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
    844 {
    845  return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
    846 }
    847 
    848 
    849 typedef struct
    850 {
    851  UInt32 NumTotalSubStreams;
    852  UInt32 NumSubDigests;
    853  CSzData sdNumSubStreams;
    854  CSzData sdSizes;
    855  CSzData sdCRCs;
    856 } CSubStreamInfo;
    857 
    858 
    859 static 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 
    932 static SRes SzReadStreamsInfo(CSzAr *p,
    933    CSzData *sd,
    934    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
    935    UInt64 *dataOffset,
    936    CSubStreamInfo *ssi,
    937    ISzAllocPtr alloc)
    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 
    972 static SRes SzReadAndDecodePackedStreams(
    973    ILookInStream *inStream,
    974    CSzData *sd,
    975    CBuf *tempBufs,
    976    UInt32 numFoldersMax,
    977    UInt64 baseOffset,
    978    CSzAr *p,
    979    ISzAllocPtr allocTemp)
    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 
   1014 static 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 
   1043 static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
   1044    CSzData *sd2,
   1045    const CBuf *tempBufs, UInt32 numTempBufs,
   1046    ISzAllocPtr 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 
   1094 static SRes SzReadHeader2(
   1095    CSzArEx *p,   /* allocMain */
   1096    CSzData *sd,
   1097    ILookInStream *inStream,
   1098    CBuf *tempBufs, UInt32 *numTempBufs,
   1099    ISzAllocPtr allocMain,
   1100    ISzAllocPtr allocTemp
   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 
   1471 static SRes SzReadHeader(
   1472    CSzArEx *p,
   1473    CSzData *sd,
   1474    ILookInStream *inStream,
   1475    ISzAllocPtr allocMain,
   1476    ISzAllocPtr 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 
   1501 static SRes SzArEx_Open2(
   1502    CSzArEx *p,
   1503    ILookInStream *inStream,
   1504    ISzAllocPtr allocMain,
   1505    ISzAllocPtr 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(ILookInStream_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(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END));
   1546    if ((UInt64)pos < startArcPos + nextHeaderOffset ||
   1547        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
   1548        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
   1549      return SZ_ERROR_INPUT_EOF;
   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 
   1625 SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
   1626    ISzAllocPtr allocMain, ISzAllocPtr 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 
   1635 SRes SzArEx_Extract(
   1636    const CSzArEx *p,
   1637    ILookInStream *inStream,
   1638    UInt32 fileIndex,
   1639    UInt32 *blockIndex,
   1640    Byte **tempBuf,
   1641    size_t *outBufferSize,
   1642    size_t *offset,
   1643    size_t *outSizeProcessed,
   1644    ISzAllocPtr allocMain,
   1645    ISzAllocPtr allocTemp)
   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    ISzAlloc_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[(size_t)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    ISzAlloc_Free(allocMain, *tempBuf);
   1676    *tempBuf = NULL;
   1677    
   1678    if (res == SZ_OK)
   1679    {
   1680      *outBufferSize = unpackSize;
   1681      if (unpackSize != 0)
   1682      {
   1683        *tempBuf = (Byte *)ISzAlloc_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[(size_t)fileIndex + 1] - unpackPos);
   1701    if (*offset + *outSizeProcessed > *outBufferSize)
   1702      return SZ_ERROR_FAIL;
   1703    if (SzBitWithVals_Check(&p->CRCs, fileIndex))
   1704      if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
   1705        res = SZ_ERROR_CRC;
   1706  }
   1707 
   1708  return res;
   1709 }
   1710 
   1711 
   1712 size_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 /*
   1727 size_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 
   1745 UInt16 *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 */