all repos — mgba @ b2d406a411b31acce5bbf0246af32a80c22ca834

mGBA Game Boy Advance Emulator

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

   1/* 7zArcIn.c -- 7z Input functions
   22018-12-31 : 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
  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, 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
  78void 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
  86void 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
  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, ISzAllocPtr alloc)
 111{
 112  ISzAlloc_Free(alloc, p->PackPositions);
 113  SzBitUi32s_Free(&p->FolderCRCs, alloc);
 114 
 115  ISzAlloc_Free(alloc, p->FoCodersOffsets);
 116  ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
 117  ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
 118  ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
 119  ISzAlloc_Free(alloc, p->CoderUnpackSizes);
 120  
 121  ISzAlloc_Free(alloc, p->CodersData);
 122
 123  SzAr_Init(p);
 124}
 125
 126
 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, ISzAllocPtr alloc)
 151{
 152  ISzAlloc_Free(alloc, p->UnpackPositions);
 153  ISzAlloc_Free(alloc, p->IsDirs);
 154
 155  ISzAlloc_Free(alloc, p->FolderToFile);
 156  ISzAlloc_Free(alloc, p->FileToFolder);
 157
 158  ISzAlloc_Free(alloc, p->FileNameOffsets);
 159  ISzAlloc_Free(alloc, p->FileNames);
 160
 161  SzBitUi32s_Free(&p->CRCs, alloc);
 162  SzBitUi32s_Free(&p->Attribs, alloc);
 163  // SzBitUi32s_Free(&p->Parents, alloc);
 164  SzBitUi64s_Free(&p->MTime, alloc);
 165  SzBitUi64s_Free(&p->CTime, alloc);
 166  
 167  SzAr_Free(&p->db, alloc);
 168  SzArEx_Init(p);
 169}
 170
 171
 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, ISzAllocPtr alloc)
 309{
 310  Byte allAreDefined;
 311  Byte *v2;
 312  UInt32 numBytes = (numItems + 7) >> 3;
 313  *v = NULL;
 314  SZ_READ_BYTE(allAreDefined);
 315  if (numBytes == 0)
 316    return SZ_OK;
 317  if (allAreDefined == 0)
 318  {
 319    if (numBytes > sd->Size)
 320      return SZ_ERROR_ARCHIVE;
 321    MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc);
 322    SKIP_DATA(sd, numBytes);
 323    return SZ_OK;
 324  }
 325  MY_ALLOC(Byte, *v, numBytes, alloc);
 326  v2 = *v;
 327  memset(v2, 0xFF, (size_t)numBytes);
 328  {
 329    unsigned numBits = (unsigned)numItems & 7;
 330    if (numBits != 0)
 331      v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
 332  }
 333  return SZ_OK;
 334}
 335
 336static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
 337{
 338  UInt32 i;
 339  CSzData sd;
 340  UInt32 *vals;
 341  const Byte *defs;
 342  MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc);
 343  sd = *sd2;
 344  defs = crcs->Defs;
 345  vals = crcs->Vals;
 346  for (i = 0; i < numItems; i++)
 347    if (SzBitArray_Check(defs, i))
 348    {
 349      SZ_READ_32(vals[i]);
 350    }
 351    else
 352      vals[i] = 0;
 353  *sd2 = sd;
 354  return SZ_OK;
 355}
 356
 357static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
 358{
 359  SzBitUi32s_Free(crcs, alloc);
 360  RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
 361  return ReadUi32s(sd, numItems, crcs, alloc);
 362}
 363
 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, ISzAllocPtr alloc)
 384{
 385  RINOK(SzReadNumber32(sd, &p->NumPackStreams));
 386
 387  RINOK(WaitId(sd, k7zIdSize));
 388  MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc);
 389  {
 390    UInt64 sum = 0;
 391    UInt32 i;
 392    UInt32 numPackStreams = p->NumPackStreams;
 393    for (i = 0; i < numPackStreams; i++)
 394    {
 395      UInt64 packSize;
 396      p->PackPositions[i] = sum;
 397      RINOK(ReadNumber(sd, &packSize));
 398      sum += packSize;
 399      if (sum < packSize)
 400        return SZ_ERROR_ARCHIVE;
 401    }
 402    p->PackPositions[i] = sum;
 403  }
 404
 405  for (;;)
 406  {
 407    UInt64 type;
 408    RINOK(ReadID(sd, &type));
 409    if (type == k7zIdEnd)
 410      return SZ_OK;
 411    if (type == k7zIdCRC)
 412    {
 413      /* CRC of packed streams is unused now */
 414      RINOK(SkipBitUi32s(sd, p->NumPackStreams));
 415      continue;
 416    }
 417    RINOK(SkipData(sd));
 418  }
 419}
 420
 421/*
 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    ISzAllocPtr alloc)
 639{
 640  CSzData sd;
 641  
 642  UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
 643  const Byte *startBufPtr;
 644  Byte external;
 645  
 646  RINOK(WaitId(sd2, k7zIdFolder));
 647  
 648  RINOK(SzReadNumber32(sd2, &numFolders));
 649  if (numFolders > numFoldersMax)
 650    return SZ_ERROR_UNSUPPORTED;
 651  p->NumFolders = numFolders;
 652
 653  SZ_READ_BYTE_SD(sd2, external);
 654  if (external == 0)
 655    sd = *sd2;
 656  else
 657  {
 658    UInt32 index;
 659    RINOK(SzReadNumber32(sd2, &index));
 660    if (index >= numTempBufs)
 661      return SZ_ERROR_ARCHIVE;
 662    sd.Data = tempBufs[index].data;
 663    sd.Size = tempBufs[index].size;
 664  }
 665  
 666  MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);
 667  MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);
 668  MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc);
 669  MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc);
 670  
 671  startBufPtr = sd.Data;
 672  
 673  packStreamIndex = 0;
 674  numCodersOutStreams = 0;
 675
 676  for (fo = 0; fo < numFolders; fo++)
 677  {
 678    UInt32 numCoders, ci, numInStreams = 0;
 679    
 680    p->FoCodersOffsets[fo] = sd.Data - startBufPtr;
 681    
 682    RINOK(SzReadNumber32(&sd, &numCoders));
 683    if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
 684      return SZ_ERROR_UNSUPPORTED;
 685    
 686    for (ci = 0; ci < numCoders; ci++)
 687    {
 688      Byte mainByte;
 689      unsigned idSize;
 690      UInt32 coderInStreams;
 691      
 692      SZ_READ_BYTE_2(mainByte);
 693      if ((mainByte & 0xC0) != 0)
 694        return SZ_ERROR_UNSUPPORTED;
 695      idSize = (mainByte & 0xF);
 696      if (idSize > 8)
 697        return SZ_ERROR_UNSUPPORTED;
 698      if (idSize > sd.Size)
 699        return SZ_ERROR_ARCHIVE;
 700      SKIP_DATA2(sd, idSize);
 701      
 702      coderInStreams = 1;
 703      
 704      if ((mainByte & 0x10) != 0)
 705      {
 706        UInt32 coderOutStreams;
 707        RINOK(SzReadNumber32(&sd, &coderInStreams));
 708        RINOK(SzReadNumber32(&sd, &coderOutStreams));
 709        if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)
 710          return SZ_ERROR_UNSUPPORTED;
 711      }
 712      
 713      numInStreams += coderInStreams;
 714
 715      if ((mainByte & 0x20) != 0)
 716      {
 717        UInt32 propsSize;
 718        RINOK(SzReadNumber32(&sd, &propsSize));
 719        if (propsSize > sd.Size)
 720          return SZ_ERROR_ARCHIVE;
 721        SKIP_DATA2(sd, propsSize);
 722      }
 723    }
 724    
 725    {
 726      UInt32 indexOfMainStream = 0;
 727      UInt32 numPackStreams = 1;
 728      
 729      if (numCoders != 1 || numInStreams != 1)
 730      {
 731        Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
 732        Byte coderUsed[k_Scan_NumCoders_MAX];
 733    
 734        UInt32 i;
 735        UInt32 numBonds = numCoders - 1;
 736        if (numInStreams < numBonds)
 737          return SZ_ERROR_ARCHIVE;
 738        
 739        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
 740          return SZ_ERROR_UNSUPPORTED;
 741        
 742        for (i = 0; i < numInStreams; i++)
 743          streamUsed[i] = False;
 744        for (i = 0; i < numCoders; i++)
 745          coderUsed[i] = False;
 746        
 747        for (i = 0; i < numBonds; i++)
 748        {
 749          UInt32 index;
 750          
 751          RINOK(SzReadNumber32(&sd, &index));
 752          if (index >= numInStreams || streamUsed[index])
 753            return SZ_ERROR_ARCHIVE;
 754          streamUsed[index] = True;
 755          
 756          RINOK(SzReadNumber32(&sd, &index));
 757          if (index >= numCoders || coderUsed[index])
 758            return SZ_ERROR_ARCHIVE;
 759          coderUsed[index] = True;
 760        }
 761        
 762        numPackStreams = numInStreams - numBonds;
 763        
 764        if (numPackStreams != 1)
 765          for (i = 0; i < numPackStreams; i++)
 766          {
 767            UInt32 index;
 768            RINOK(SzReadNumber32(&sd, &index));
 769            if (index >= numInStreams || streamUsed[index])
 770              return SZ_ERROR_ARCHIVE;
 771            streamUsed[index] = True;
 772          }
 773          
 774        for (i = 0; i < numCoders; i++)
 775          if (!coderUsed[i])
 776          {
 777            indexOfMainStream = i;
 778            break;
 779          }
 780 
 781        if (i == numCoders)
 782          return SZ_ERROR_ARCHIVE;
 783      }
 784      
 785      p->FoStartPackStreamIndex[fo] = packStreamIndex;
 786      p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
 787      p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
 788      numCodersOutStreams += numCoders;
 789      if (numCodersOutStreams < numCoders)
 790        return SZ_ERROR_UNSUPPORTED;
 791      if (numPackStreams > p->NumPackStreams - packStreamIndex)
 792        return SZ_ERROR_ARCHIVE;
 793      packStreamIndex += numPackStreams;
 794    }
 795  }
 796
 797  p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
 798  
 799  {
 800    size_t dataSize = sd.Data - startBufPtr;
 801    p->FoStartPackStreamIndex[fo] = packStreamIndex;
 802    p->FoCodersOffsets[fo] = dataSize;
 803    MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);
 804  }
 805  
 806  if (external != 0)
 807  {
 808    if (sd.Size != 0)
 809      return SZ_ERROR_ARCHIVE;
 810    sd = *sd2;
 811  }
 812  
 813  RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
 814  
 815  MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
 816  {
 817    UInt32 i;
 818    for (i = 0; i < numCodersOutStreams; i++)
 819    {
 820      RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));
 821    }
 822  }
 823
 824  for (;;)
 825  {
 826    UInt64 type;
 827    RINOK(ReadID(&sd, &type));
 828    if (type == k7zIdEnd)
 829    {
 830      *sd2 = sd;
 831      return SZ_OK;
 832    }
 833    if (type == k7zIdCRC)
 834    {
 835      RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));
 836      continue;
 837    }
 838    RINOK(SkipData(&sd));
 839  }
 840}
 841
 842
 843UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
 844{
 845  return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
 846}
 847
 848
 849typedef struct
 850{
 851  UInt32 NumTotalSubStreams;
 852  UInt32 NumSubDigests;
 853  CSzData sdNumSubStreams;
 854  CSzData sdSizes;
 855  CSzData sdCRCs;
 856} CSubStreamInfo;
 857
 858
 859static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
 860{
 861  UInt64 type = 0;
 862  UInt32 numSubDigests = 0;
 863  UInt32 numFolders = p->NumFolders;
 864  UInt32 numUnpackStreams = numFolders;
 865  UInt32 numUnpackSizesInData = 0;
 866
 867  for (;;)
 868  {
 869    RINOK(ReadID(sd, &type));
 870    if (type == k7zIdNumUnpackStream)
 871    {
 872      UInt32 i;
 873      ssi->sdNumSubStreams.Data = sd->Data;
 874      numUnpackStreams = 0;
 875      numSubDigests = 0;
 876      for (i = 0; i < numFolders; i++)
 877      {
 878        UInt32 numStreams;
 879        RINOK(SzReadNumber32(sd, &numStreams));
 880        if (numUnpackStreams > numUnpackStreams + numStreams)
 881          return SZ_ERROR_UNSUPPORTED;
 882        numUnpackStreams += numStreams;
 883        if (numStreams != 0)
 884          numUnpackSizesInData += (numStreams - 1);
 885        if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
 886          numSubDigests += numStreams;
 887      }
 888      ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;
 889      continue;
 890    }
 891    if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
 892      break;
 893    RINOK(SkipData(sd));
 894  }
 895
 896  if (!ssi->sdNumSubStreams.Data)
 897  {
 898    numSubDigests = numFolders;
 899    if (p->FolderCRCs.Defs)
 900      numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
 901  }
 902  
 903  ssi->NumTotalSubStreams = numUnpackStreams;
 904  ssi->NumSubDigests = numSubDigests;
 905
 906  if (type == k7zIdSize)
 907  {
 908    ssi->sdSizes.Data = sd->Data;
 909    RINOK(SkipNumbers(sd, numUnpackSizesInData));
 910    ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;
 911    RINOK(ReadID(sd, &type));
 912  }
 913
 914  for (;;)
 915  {
 916    if (type == k7zIdEnd)
 917      return SZ_OK;
 918    if (type == k7zIdCRC)
 919    {
 920      ssi->sdCRCs.Data = sd->Data;
 921      RINOK(SkipBitUi32s(sd, numSubDigests));
 922      ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;
 923    }
 924    else
 925    {
 926      RINOK(SkipData(sd));
 927    }
 928    RINOK(ReadID(sd, &type));
 929  }
 930}
 931
 932static SRes SzReadStreamsInfo(CSzAr *p,
 933    CSzData *sd,
 934    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
 935    UInt64 *dataOffset,
 936    CSubStreamInfo *ssi,
 937    ISzAllocPtr alloc)
 938{
 939  UInt64 type;
 940
 941  SzData_Clear(&ssi->sdSizes);
 942  SzData_Clear(&ssi->sdCRCs);
 943  SzData_Clear(&ssi->sdNumSubStreams);
 944
 945  *dataOffset = 0;
 946  RINOK(ReadID(sd, &type));
 947  if (type == k7zIdPackInfo)
 948  {
 949    RINOK(ReadNumber(sd, dataOffset));
 950    RINOK(ReadPackInfo(p, sd, alloc));
 951    RINOK(ReadID(sd, &type));
 952  }
 953  if (type == k7zIdUnpackInfo)
 954  {
 955    RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));
 956    RINOK(ReadID(sd, &type));
 957  }
 958  if (type == k7zIdSubStreamsInfo)
 959  {
 960    RINOK(ReadSubStreamsInfo(p, sd, ssi));
 961    RINOK(ReadID(sd, &type));
 962  }
 963  else
 964  {
 965    ssi->NumTotalSubStreams = p->NumFolders;
 966    // ssi->NumSubDigests = 0;
 967  }
 968
 969  return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
 970}
 971
 972static SRes SzReadAndDecodePackedStreams(
 973    ILookInStream *inStream,
 974    CSzData *sd,
 975    CBuf *tempBufs,
 976    UInt32 numFoldersMax,
 977    UInt64 baseOffset,
 978    CSzAr *p,
 979    ISzAllocPtr allocTemp)
 980{
 981  UInt64 dataStartPos;
 982  UInt32 fo;
 983  CSubStreamInfo ssi;
 984
 985  RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));
 986  
 987  dataStartPos += baseOffset;
 988  if (p->NumFolders == 0)
 989    return SZ_ERROR_ARCHIVE;
 990 
 991  for (fo = 0; fo < p->NumFolders; fo++)
 992    Buf_Init(tempBufs + fo);
 993  
 994  for (fo = 0; fo < p->NumFolders; fo++)
 995  {
 996    CBuf *tempBuf = tempBufs + fo;
 997    UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);
 998    if ((size_t)unpackSize != unpackSize)
 999      return SZ_ERROR_MEM;
1000    if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
1001      return SZ_ERROR_MEM;
1002  }
1003  
1004  for (fo = 0; fo < p->NumFolders; fo++)
1005  {
1006    const CBuf *tempBuf = tempBufs + fo;
1007    RINOK(LookInStream_SeekTo(inStream, dataStartPos));
1008    RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));
1009  }
1010  
1011  return SZ_OK;
1012}
1013
1014static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
1015{
1016  size_t pos = 0;
1017  *offsets++ = 0;
1018  if (numFiles == 0)
1019    return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
1020  if (size < 2)
1021    return SZ_ERROR_ARCHIVE;
1022  if (data[size - 2] != 0 || data[size - 1] != 0)
1023    return SZ_ERROR_ARCHIVE;
1024  do
1025  {
1026    const Byte *p;
1027    if (pos == size)
1028      return SZ_ERROR_ARCHIVE;
1029    for (p = data + pos;
1030      #ifdef _WIN32
1031      *(const UInt16 *)p != 0
1032      #else
1033      p[0] != 0 || p[1] != 0
1034      #endif
1035      ; p += 2);
1036    pos = p - data + 2;
1037    *offsets++ = (pos >> 1);
1038  }
1039  while (--numFiles);
1040  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1041}
1042
1043static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1044    CSzData *sd2,
1045    const CBuf *tempBufs, UInt32 numTempBufs,
1046    ISzAllocPtr alloc)
1047{
1048  CSzData sd;
1049  UInt32 i;
1050  CNtfsFileTime *vals;
1051  Byte *defs;
1052  Byte external;
1053  
1054  RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
1055  
1056  SZ_READ_BYTE_SD(sd2, external);
1057  if (external == 0)
1058    sd = *sd2;
1059  else
1060  {
1061    UInt32 index;
1062    RINOK(SzReadNumber32(sd2, &index));
1063    if (index >= numTempBufs)
1064      return SZ_ERROR_ARCHIVE;
1065    sd.Data = tempBufs[index].data;
1066    sd.Size = tempBufs[index].size;
1067  }
1068  
1069  MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc);
1070  vals = p->Vals;
1071  defs = p->Defs;
1072  for (i = 0; i < num; i++)
1073    if (SzBitArray_Check(defs, i))
1074    {
1075      if (sd.Size < 8)
1076        return SZ_ERROR_ARCHIVE;
1077      vals[i].Low = GetUi32(sd.Data);
1078      vals[i].High = GetUi32(sd.Data + 4);
1079      SKIP_DATA2(sd, 8);
1080    }
1081    else
1082      vals[i].High = vals[i].Low = 0;
1083  
1084  if (external == 0)
1085    *sd2 = sd;
1086  
1087  return SZ_OK;
1088}
1089
1090
1091#define NUM_ADDITIONAL_STREAMS_MAX 8
1092
1093
1094static SRes SzReadHeader2(
1095    CSzArEx *p,   /* allocMain */
1096    CSzData *sd,
1097    ILookInStream *inStream,
1098    CBuf *tempBufs, UInt32 *numTempBufs,
1099    ISzAllocPtr allocMain,
1100    ISzAllocPtr allocTemp
1101    )
1102{
1103  CSubStreamInfo ssi;
1104
1105{
1106  UInt64 type;
1107  
1108  SzData_Clear(&ssi.sdSizes);
1109  SzData_Clear(&ssi.sdCRCs);
1110  SzData_Clear(&ssi.sdNumSubStreams);
1111
1112  ssi.NumSubDigests = 0;
1113  ssi.NumTotalSubStreams = 0;
1114
1115  RINOK(ReadID(sd, &type));
1116
1117  if (type == k7zIdArchiveProperties)
1118  {
1119    for (;;)
1120    {
1121      UInt64 type2;
1122      RINOK(ReadID(sd, &type2));
1123      if (type2 == k7zIdEnd)
1124        break;
1125      RINOK(SkipData(sd));
1126    }
1127    RINOK(ReadID(sd, &type));
1128  }
1129
1130  if (type == k7zIdAdditionalStreamsInfo)
1131  {
1132    CSzAr tempAr;
1133    SRes res;
1134    
1135    SzAr_Init(&tempAr);
1136    res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
1137        p->startPosAfterHeader, &tempAr, allocTemp);
1138    *numTempBufs = tempAr.NumFolders;
1139    SzAr_Free(&tempAr, allocTemp);
1140    
1141    if (res != SZ_OK)
1142      return res;
1143    RINOK(ReadID(sd, &type));
1144  }
1145
1146  if (type == k7zIdMainStreamsInfo)
1147  {
1148    RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
1149        &p->dataPos, &ssi, allocMain));
1150    p->dataPos += p->startPosAfterHeader;
1151    RINOK(ReadID(sd, &type));
1152  }
1153
1154  if (type == k7zIdEnd)
1155  {
1156    return SZ_OK;
1157  }
1158
1159  if (type != k7zIdFilesInfo)
1160    return SZ_ERROR_ARCHIVE;
1161}
1162
1163{
1164  UInt32 numFiles = 0;
1165  UInt32 numEmptyStreams = 0;
1166  const Byte *emptyStreams = NULL;
1167  const Byte *emptyFiles = NULL;
1168  
1169  RINOK(SzReadNumber32(sd, &numFiles));
1170  p->NumFiles = numFiles;
1171
1172  for (;;)
1173  {
1174    UInt64 type;
1175    UInt64 size;
1176    RINOK(ReadID(sd, &type));
1177    if (type == k7zIdEnd)
1178      break;
1179    RINOK(ReadNumber(sd, &size));
1180    if (size > sd->Size)
1181      return SZ_ERROR_ARCHIVE;
1182    
1183    if (type >= ((UInt32)1 << 8))
1184    {
1185      SKIP_DATA(sd, size);
1186    }
1187    else switch ((unsigned)type)
1188    {
1189      case k7zIdName:
1190      {
1191        size_t namesSize;
1192        const Byte *namesData;
1193        Byte external;
1194
1195        SZ_READ_BYTE(external);
1196        if (external == 0)
1197        {
1198          namesSize = (size_t)size - 1;
1199          namesData = sd->Data;
1200        }
1201        else
1202        {
1203          UInt32 index;
1204          RINOK(SzReadNumber32(sd, &index));
1205          if (index >= *numTempBufs)
1206            return SZ_ERROR_ARCHIVE;
1207          namesData = (tempBufs)[index].data;
1208          namesSize = (tempBufs)[index].size;
1209        }
1210
1211        if ((namesSize & 1) != 0)
1212          return SZ_ERROR_ARCHIVE;
1213        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
1214        MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);
1215        RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
1216        if (external == 0)
1217        {
1218          SKIP_DATA(sd, namesSize);
1219        }
1220        break;
1221      }
1222      case k7zIdEmptyStream:
1223      {
1224        RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
1225        numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1226        emptyFiles = NULL;
1227        break;
1228      }
1229      case k7zIdEmptyFile:
1230      {
1231        RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));
1232        break;
1233      }
1234      case k7zIdWinAttrib:
1235      {
1236        Byte external;
1237        CSzData sdSwitch;
1238        CSzData *sdPtr;
1239        SzBitUi32s_Free(&p->Attribs, allocMain);
1240        RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));
1241
1242        SZ_READ_BYTE(external);
1243        if (external == 0)
1244          sdPtr = sd;
1245        else
1246        {
1247          UInt32 index;
1248          RINOK(SzReadNumber32(sd, &index));
1249          if (index >= *numTempBufs)
1250            return SZ_ERROR_ARCHIVE;
1251          sdSwitch.Data = (tempBufs)[index].data;
1252          sdSwitch.Size = (tempBufs)[index].size;
1253          sdPtr = &sdSwitch;
1254        }
1255        RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));
1256        break;
1257      }
1258      /*
1259      case k7zParent:
1260      {
1261        SzBitUi32s_Free(&p->Parents, allocMain);
1262        RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1263        RINOK(SzReadSwitch(sd));
1264        RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1265        break;
1266      }
1267      */
1268      case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1269      case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1270      default:
1271      {
1272        SKIP_DATA(sd, size);
1273      }
1274    }
1275  }
1276
1277  if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1278    return SZ_ERROR_ARCHIVE;
1279
1280  for (;;)
1281  {
1282    UInt64 type;
1283    RINOK(ReadID(sd, &type));
1284    if (type == k7zIdEnd)
1285      break;
1286    RINOK(SkipData(sd));
1287  }
1288
1289  {
1290    UInt32 i;
1291    UInt32 emptyFileIndex = 0;
1292    UInt32 folderIndex = 0;
1293    UInt32 remSubStreams = 0;
1294    UInt32 numSubStreams = 0;
1295    UInt64 unpackPos = 0;
1296    const Byte *digestsDefs = NULL;
1297    const Byte *digestsVals = NULL;
1298    UInt32 digestsValsIndex = 0;
1299    UInt32 digestIndex;
1300    Byte allDigestsDefined = 0;
1301    Byte isDirMask = 0;
1302    Byte crcMask = 0;
1303    Byte mask = 0x80;
1304    
1305    MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain);
1306    MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain);
1307    MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
1308    MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
1309
1310    RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
1311
1312    if (ssi.sdCRCs.Size != 0)
1313    {
1314      SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);
1315      if (allDigestsDefined)
1316        digestsVals = ssi.sdCRCs.Data;
1317      else
1318      {
1319        size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1320        digestsDefs = ssi.sdCRCs.Data;
1321        digestsVals = digestsDefs + numBytes;
1322      }
1323    }
1324
1325    digestIndex = 0;
1326    
1327    for (i = 0; i < numFiles; i++, mask >>= 1)
1328    {
1329      if (mask == 0)
1330      {
1331        UInt32 byteIndex = (i - 1) >> 3;
1332        p->IsDirs[byteIndex] = isDirMask;
1333        p->CRCs.Defs[byteIndex] = crcMask;
1334        isDirMask = 0;
1335        crcMask = 0;
1336        mask = 0x80;
1337      }
1338
1339      p->UnpackPositions[i] = unpackPos;
1340      p->CRCs.Vals[i] = 0;
1341      
1342      if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1343      {
1344        if (emptyFiles)
1345        {
1346          if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
1347            isDirMask |= mask;
1348          emptyFileIndex++;
1349        }
1350        else
1351          isDirMask |= mask;
1352        if (remSubStreams == 0)
1353        {
1354          p->FileToFolder[i] = (UInt32)-1;
1355          continue;
1356        }
1357      }
1358      
1359      if (remSubStreams == 0)
1360      {
1361        for (;;)
1362        {
1363          if (folderIndex >= p->db.NumFolders)
1364            return SZ_ERROR_ARCHIVE;
1365          p->FolderToFile[folderIndex] = i;
1366          numSubStreams = 1;
1367          if (ssi.sdNumSubStreams.Data)
1368          {
1369            RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
1370          }
1371          remSubStreams = numSubStreams;
1372          if (numSubStreams != 0)
1373            break;
1374          {
1375            UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1376            unpackPos += folderUnpackSize;
1377            if (unpackPos < folderUnpackSize)
1378              return SZ_ERROR_ARCHIVE;
1379          }
1380
1381          folderIndex++;
1382        }
1383      }
1384      
1385      p->FileToFolder[i] = folderIndex;
1386      
1387      if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1388        continue;
1389      
1390      if (--remSubStreams == 0)
1391      {
1392        UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1393        UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
1394        if (folderUnpackSize < unpackPos - startFolderUnpackPos)
1395          return SZ_ERROR_ARCHIVE;
1396        unpackPos = startFolderUnpackPos + folderUnpackSize;
1397        if (unpackPos < folderUnpackSize)
1398          return SZ_ERROR_ARCHIVE;
1399
1400        if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
1401        {
1402          p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1403          crcMask |= mask;
1404        }
1405        else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1406        {
1407          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1408          digestsValsIndex++;
1409          crcMask |= mask;
1410        }
1411        
1412        folderIndex++;
1413      }
1414      else
1415      {
1416        UInt64 v;
1417        RINOK(ReadNumber(&ssi.sdSizes, &v));
1418        unpackPos += v;
1419        if (unpackPos < v)
1420          return SZ_ERROR_ARCHIVE;
1421        if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1422        {
1423          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1424          digestsValsIndex++;
1425          crcMask |= mask;
1426        }
1427      }
1428    }
1429
1430    if (mask != 0x80)
1431    {
1432      UInt32 byteIndex = (i - 1) >> 3;
1433      p->IsDirs[byteIndex] = isDirMask;
1434      p->CRCs.Defs[byteIndex] = crcMask;
1435    }
1436    
1437    p->UnpackPositions[i] = unpackPos;
1438
1439    if (remSubStreams != 0)
1440      return SZ_ERROR_ARCHIVE;
1441
1442    for (;;)
1443    {
1444      p->FolderToFile[folderIndex] = i;
1445      if (folderIndex >= p->db.NumFolders)
1446        break;
1447      if (!ssi.sdNumSubStreams.Data)
1448        return SZ_ERROR_ARCHIVE;
1449      RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
1450      if (numSubStreams != 0)
1451        return SZ_ERROR_ARCHIVE;
1452      /*
1453      {
1454        UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1455        unpackPos += folderUnpackSize;
1456        if (unpackPos < folderUnpackSize)
1457          return SZ_ERROR_ARCHIVE;
1458      }
1459      */
1460      folderIndex++;
1461    }
1462
1463    if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
1464      return SZ_ERROR_ARCHIVE;
1465  }
1466}
1467  return SZ_OK;
1468}
1469
1470
1471static SRes SzReadHeader(
1472    CSzArEx *p,
1473    CSzData *sd,
1474    ILookInStream *inStream,
1475    ISzAllocPtr allocMain,
1476    ISzAllocPtr allocTemp)
1477{
1478  UInt32 i;
1479  UInt32 numTempBufs = 0;
1480  SRes res;
1481  CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1482
1483  for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1484    Buf_Init(tempBufs + i);
1485  
1486  res = SzReadHeader2(p, sd, inStream,
1487      tempBufs, &numTempBufs,
1488      allocMain, allocTemp);
1489  
1490  for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1491    Buf_Free(tempBufs + i, allocTemp);
1492
1493  RINOK(res);
1494
1495  if (sd->Size != 0)
1496    return SZ_ERROR_FAIL;
1497
1498  return res;
1499}
1500
1501static SRes SzArEx_Open2(
1502    CSzArEx *p,
1503    ILookInStream *inStream,
1504    ISzAllocPtr allocMain,
1505    ISzAllocPtr allocTemp)
1506{
1507  Byte header[k7zStartHeaderSize];
1508  Int64 startArcPos;
1509  UInt64 nextHeaderOffset, nextHeaderSize;
1510  size_t nextHeaderSizeT;
1511  UInt32 nextHeaderCRC;
1512  CBuf buf;
1513  SRes res;
1514
1515  startArcPos = 0;
1516  RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR));
1517
1518  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1519
1520  if (!TestSignatureCandidate(header))
1521    return SZ_ERROR_NO_ARCHIVE;
1522  if (header[6] != k7zMajorVersion)
1523    return SZ_ERROR_UNSUPPORTED;
1524
1525  nextHeaderOffset = GetUi64(header + 12);
1526  nextHeaderSize = GetUi64(header + 20);
1527  nextHeaderCRC = GetUi32(header + 28);
1528
1529  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
1530  
1531  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1532    return SZ_ERROR_CRC;
1533
1534  nextHeaderSizeT = (size_t)nextHeaderSize;
1535  if (nextHeaderSizeT != nextHeaderSize)
1536    return SZ_ERROR_MEM;
1537  if (nextHeaderSizeT == 0)
1538    return SZ_OK;
1539  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1540      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1541    return SZ_ERROR_NO_ARCHIVE;
1542
1543  {
1544    Int64 pos = 0;
1545    RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END));
1546    if ((UInt64)pos < startArcPos + nextHeaderOffset ||
1547        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1548        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1549      return SZ_ERROR_INPUT_EOF;
1550  }
1551
1552  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
1553
1554  if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1555    return SZ_ERROR_MEM;
1556
1557  res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1558  
1559  if (res == SZ_OK)
1560  {
1561    res = SZ_ERROR_ARCHIVE;
1562    if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1563    {
1564      CSzData sd;
1565      UInt64 type;
1566      sd.Data = buf.data;
1567      sd.Size = buf.size;
1568      
1569      res = ReadID(&sd, &type);
1570      
1571      if (res == SZ_OK && type == k7zIdEncodedHeader)
1572      {
1573        CSzAr tempAr;
1574        CBuf tempBuf;
1575        Buf_Init(&tempBuf);
1576        
1577        SzAr_Init(&tempAr);
1578        res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1579        SzAr_Free(&tempAr, allocTemp);
1580       
1581        if (res != SZ_OK)
1582        {
1583          Buf_Free(&tempBuf, allocTemp);
1584        }
1585        else
1586        {
1587          Buf_Free(&buf, allocTemp);
1588          buf.data = tempBuf.data;
1589          buf.size = tempBuf.size;
1590          sd.Data = buf.data;
1591          sd.Size = buf.size;
1592          res = ReadID(&sd, &type);
1593        }
1594      }
1595  
1596      if (res == SZ_OK)
1597      {
1598        if (type == k7zIdHeader)
1599        {
1600          /*
1601          CSzData sd2;
1602          unsigned ttt;
1603          for (ttt = 0; ttt < 40000; ttt++)
1604          {
1605            SzArEx_Free(p, allocMain);
1606            sd2 = sd;
1607            res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1608            if (res != SZ_OK)
1609              break;
1610          }
1611          */
1612          res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1613        }
1614        else
1615          res = SZ_ERROR_UNSUPPORTED;
1616      }
1617    }
1618  }
1619 
1620  Buf_Free(&buf, allocTemp);
1621  return res;
1622}
1623
1624
1625SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
1626    ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
1627{
1628  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1629  if (res != SZ_OK)
1630    SzArEx_Free(p, allocMain);
1631  return res;
1632}
1633
1634
1635SRes SzArEx_Extract(
1636    const CSzArEx *p,
1637    ILookInStream *inStream,
1638    UInt32 fileIndex,
1639    UInt32 *blockIndex,
1640    Byte **tempBuf,
1641    size_t *outBufferSize,
1642    size_t *offset,
1643    size_t *outSizeProcessed,
1644    ISzAllocPtr allocMain,
1645    ISzAllocPtr allocTemp)
1646{
1647  UInt32 folderIndex = p->FileToFolder[fileIndex];
1648  SRes res = SZ_OK;
1649  
1650  *offset = 0;
1651  *outSizeProcessed = 0;
1652  
1653  if (folderIndex == (UInt32)-1)
1654  {
1655    ISzAlloc_Free(allocMain, *tempBuf);
1656    *blockIndex = folderIndex;
1657    *tempBuf = NULL;
1658    *outBufferSize = 0;
1659    return SZ_OK;
1660  }
1661
1662  if (*tempBuf == NULL || *blockIndex != folderIndex)
1663  {
1664    UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1665    /*
1666    UInt64 unpackSizeSpec =
1667        p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
1668        p->UnpackPositions[p->FolderToFile[folderIndex]];
1669    */
1670    size_t unpackSize = (size_t)unpackSizeSpec;
1671
1672    if (unpackSize != unpackSizeSpec)
1673      return SZ_ERROR_MEM;
1674    *blockIndex = folderIndex;
1675    ISzAlloc_Free(allocMain, *tempBuf);
1676    *tempBuf = NULL;
1677    
1678    if (res == SZ_OK)
1679    {
1680      *outBufferSize = unpackSize;
1681      if (unpackSize != 0)
1682      {
1683        *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
1684        if (*tempBuf == NULL)
1685          res = SZ_ERROR_MEM;
1686      }
1687  
1688      if (res == SZ_OK)
1689      {
1690        res = SzAr_DecodeFolder(&p->db, folderIndex,
1691            inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
1692      }
1693    }
1694  }
1695
1696  if (res == SZ_OK)
1697  {
1698    UInt64 unpackPos = p->UnpackPositions[fileIndex];
1699    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
1700    *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos);
1701    if (*offset + *outSizeProcessed > *outBufferSize)
1702      return SZ_ERROR_FAIL;
1703    if (SzBitWithVals_Check(&p->CRCs, fileIndex))
1704      if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
1705        res = SZ_ERROR_CRC;
1706  }
1707
1708  return res;
1709}
1710
1711
1712size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1713{
1714  size_t offs = p->FileNameOffsets[fileIndex];
1715  size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1716  if (dest != 0)
1717  {
1718    size_t i;
1719    const Byte *src = p->FileNames + offs * 2;
1720    for (i = 0; i < len; i++)
1721      dest[i] = GetUi16(src + i * 2);
1722  }
1723  return len;
1724}
1725
1726/*
1727size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1728{
1729  size_t len;
1730  if (!p->FileNameOffsets)
1731    return 1;
1732  len = 0;
1733  for (;;)
1734  {
1735    UInt32 parent = (UInt32)(Int32)-1;
1736    len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1737    if SzBitWithVals_Check(&p->Parents, fileIndex)
1738      parent = p->Parents.Vals[fileIndex];
1739    if (parent == (UInt32)(Int32)-1)
1740      return len;
1741    fileIndex = parent;
1742  }
1743}
1744
1745UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1746{
1747  BoolInt needSlash;
1748  if (!p->FileNameOffsets)
1749  {
1750    *(--dest) = 0;
1751    return dest;
1752  }
1753  needSlash = False;
1754  for (;;)
1755  {
1756    UInt32 parent = (UInt32)(Int32)-1;
1757    size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1758    SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1759    if (needSlash)
1760      *(dest - 1) = '/';
1761    needSlash = True;
1762    dest -= curLen;
1763
1764    if SzBitWithVals_Check(&p->Parents, fileIndex)
1765      parent = p->Parents.Vals[fileIndex];
1766    if (parent == (UInt32)(Int32)-1)
1767      return dest;
1768    fileIndex = parent;
1769  }
1770}
1771*/