all repos — mgba @ f836a67863e66499c812c8d963d37ff56ad10638

mGBA Game Boy Advance Emulator

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

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