all repos — mgba @ dab12cf5c674542cae0db7708c333035255fbc65

mGBA Game Boy Advance Emulator

src/third-party/lzma/7zArcIn.c (view raw)

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