"Fossies" - the Fresh Open Source Software Archive

Member "hashcat-6.2.6/deps/LZMA-SDK/C/7zArcIn.c" (2 Sep 2022, 45951 Bytes) of package /linux/privat/hashcat-6.2.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "7zArcIn.c": 6.2.1_vs_6.2.2.

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