Exemplo n.º 1
0
static int Buf_EnsureSize(CBuf *dest, size_t size)
{
  if (dest->size >= size)
    return 1;
  Buf_Free(dest, &g_Alloc);
  return Buf_Create(dest, size, &g_Alloc);
}
Exemplo n.º 2
0
static SRes SzReadAndDecodePackedStreams2(
    ISeekInStream *inStream,
    CSzData *sd,
    ISeqOutStream *outStream,
    UInt64 baseOffset,
    CSzAr *p,
    UInt64 **unpackSizes,
    Byte **digestsDefined,
    UInt32 **digests,
    ISzAlloc *allocTemp)
{
  CMemOutStream* memStream;
  UInt32 numUnpackStreams = 0;
  UInt64 dataStartPos;
  CSzFolder *folder;
  UInt64 unpackSize;
  SRes res;
  Int64 offset;

  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
      allocTemp, allocTemp));
  
  dataStartPos += baseOffset;
  if (p->NumFolders != 1)
    return SZ_ERROR_ARCHIVE;

  folder = p->Folders;
  unpackSize = SzFolder_GetUnpackSize(folder);
  
  offset = (Int64)dataStartPos;
  RINOK(inStream->Seek(inStream, &offset, SZ_SEEK_SET));

  memStream = (CMemOutStream*)outStream;
  if (!Buf_Create((CBuf*)&memStream->data, (size_t)unpackSize, allocTemp))
    return SZ_ERROR_MEM;
  
  res = SzFolder_Decode(folder, p->PackSizes,
          inStream, dataStartPos,
          outStream, (size_t)unpackSize, NULL, allocTemp);
  RINOK(res);
  if (folder->UnpackCRCDefined)
    if (CrcCalc(memStream->data, (size_t)unpackSize) != folder->UnpackCRC)
      return SZ_ERROR_CRC;
  return SZ_OK;
}
Exemplo n.º 3
0
static SRes SzReadAndDecodePackedStreams2(
    ILookInStream *inStream,
    CSzData *sd,
    CBuf *outBuffer,
    UInt64 baseOffset,
    CSzAr *p,
    UInt64 **unpackSizes,
    Byte **digestsDefined,
    UInt32 **digests,
    ISzAlloc *allocTemp)
{

  UInt32 numUnpackStreams = 0;
  UInt64 dataStartPos;
  CSzFolder *folder;
  UInt64 unpackSize;
  SRes res;

  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
      allocTemp, allocTemp));
  
  dataStartPos += baseOffset;
  if (p->NumFolders != 1)
    return SZ_ERROR_ARCHIVE;

  folder = p->Folders;
  unpackSize = SzFolder_GetUnpackSize(folder);
  
  RINOK(LookInStream_SeekTo(inStream, dataStartPos));

  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
    return SZ_ERROR_MEM;
  
  res = SzFolder_Decode(folder, p->PackSizes,
          inStream, dataStartPos,
          outBuffer->data, (size_t)unpackSize, allocTemp);
  RINOK(res);
#ifdef _7ZIP_CRC_SUPPORT
  if (folder->UnpackCRCDefined)
    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
      return SZ_ERROR_CRC;
#endif
  return SZ_OK;
}
Exemplo n.º 4
0
static SRes SzReadHeader2(
      CSzArEx *p,   /* allocMain */
      CSzData *sd,
      uint64_t **unpackSizes,  /* allocTemp */
      uint8_t **digestsDefined,    /* allocTemp */
      uint32_t **digests,         /* allocTemp */
      uint8_t **emptyStreamVector, /* allocTemp */
      uint8_t **emptyFileVector,   /* allocTemp */
      uint8_t **lwtVector,         /* allocTemp */
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint64_t type;
   uint32_t numUnpackStreams = 0;
   uint32_t numFiles = 0;
   CSzFileItem *files = 0;
   uint32_t numEmptyStreams = 0;
   uint32_t i;

   RINOK(SzReadID(sd, &type));

   if (type == k7zIdArchiveProperties)
   {
      RINOK(SzReadArchiveProperties(sd));
      RINOK(SzReadID(sd, &type));
   }


   if (type == k7zIdMainStreamsInfo)
   {
      RINOK(SzReadStreamsInfo(sd,
               &p->dataPos,
               &p->db,
               &numUnpackStreams,
               unpackSizes,
               digestsDefined,
               digests, allocMain, allocTemp));
      p->dataPos += p->startPosAfterHeader;
      RINOK(SzReadID(sd, &type));
   }

   if (type == k7zIdEnd)
      return SZ_OK;
   if (type != k7zIdFilesInfo)
      return SZ_ERROR_ARCHIVE;

   RINOK(SzReadNumber32(sd, &numFiles));
   p->db.NumFiles = numFiles;

   MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);

   p->db.Files = files;
   for (i = 0; i < numFiles; i++)
      SzFile_Init(files + i);

   for (;;)
   {
      uint64_t size;
      RINOK(SzReadID(sd, &type));
      if (type == k7zIdEnd)
         break;
      RINOK(SzReadNumber(sd, &size));
      if (size > sd->Size)
         return SZ_ERROR_ARCHIVE;
      if ((uint64_t)(int)type != type)
      {
         RINOK(SzSkeepDataSize(sd, size));
      }
      else
         switch((int)type)
         {
            case k7zIdName:
               {
                  size_t namesSize;
                  RINOK(SzReadSwitch(sd));
                  namesSize = (size_t)size - 1;
                  if ((namesSize & 1) != 0)
                     return SZ_ERROR_ARCHIVE;
                  if (!Buf_Create(&p->FileNames, namesSize, allocMain))
                     return SZ_ERROR_MEM;
                  MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
                  memcpy(p->FileNames.data, sd->Data, namesSize);
                  RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
                     RINOK(SzSkeepDataSize(sd, namesSize));
                  break;
               }
            case k7zIdEmptyStream:
               {
                  RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
                  numEmptyStreams = 0;
                  for (i = 0; i < numFiles; i++)
                     if ((*emptyStreamVector)[i])
                        numEmptyStreams++;
                  break;
               }
            case k7zIdEmptyFile:
               {
                  RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
                  break;
               }
            case k7zIdWinAttributes:
               {
                  RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
                  RINOK(SzReadSwitch(sd));
                  for (i = 0; i < numFiles; i++)
                  {
                     CSzFileItem *f = &files[i];
                     uint8_t defined = (*lwtVector)[i];
                     f->AttribDefined = defined;
                     f->Attrib = 0;
                     if (defined)
                     {
                        RINOK(SzReaduint32_t(sd, &f->Attrib));
                     }
                  }
                  IAlloc_Free(allocTemp, *lwtVector);
                  *lwtVector = NULL;
                  break;
               }
            case k7zIdMTime:
               {
                  RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
                  RINOK(SzReadSwitch(sd));
                  for (i = 0; i < numFiles; i++)
                  {
                     CSzFileItem *f = &files[i];
                     uint8_t defined = (*lwtVector)[i];
                     f->MTimeDefined = defined;
                     f->MTime.Low = f->MTime.High = 0;
                     if (defined)
                     {
                        RINOK(SzReaduint32_t(sd, &f->MTime.Low));
                        RINOK(SzReaduint32_t(sd, &f->MTime.High));
                     }
                  }
                  IAlloc_Free(allocTemp, *lwtVector);
                  *lwtVector = NULL;
                  break;
               }
            default:
               {
                  RINOK(SzSkeepDataSize(sd, size));
               }
         }
   }

   {
      uint32_t emptyFileIndex = 0;
      uint32_t sizeIndex = 0;
      for (i = 0; i < numFiles; i++)
      {
         CSzFileItem *file = files + i;
         file->IsAnti = 0;
         if (*emptyStreamVector == 0)
            file->HasStream = 1;
         else
            file->HasStream = (uint8_t)((*emptyStreamVector)[i] ? 0 : 1);
         if (file->HasStream)
         {
            file->IsDir = 0;
            file->Size = (*unpackSizes)[sizeIndex];
            file->Crc = (*digests)[sizeIndex];
            file->CrcDefined = (uint8_t)(*digestsDefined)[sizeIndex];
            sizeIndex++;
         }
         else
         {
            if (*emptyFileVector == 0)
               file->IsDir = 1;
            else
               file->IsDir = (uint8_t)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
            emptyFileIndex++;
            file->Size = 0;
            file->Crc = 0;
            file->CrcDefined = 0;
         }
      }
   }
   return SzArEx_Fill(p, allocMain);
}
Exemplo n.º 5
0
static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
{
   uint32_t numCoders, numBindPairs, numPackStreams, i;
   uint32_t numInStreams = 0, numOutStreams = 0;

   RINOK(SzReadNumber32(sd, &numCoders));
   if (numCoders > NUM_FOLDER_CODERS_MAX)
      return SZ_ERROR_UNSUPPORTED;
   folder->NumCoders = numCoders;

   MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);

   for (i = 0; i < numCoders; i++)
      SzCoderInfo_Init(folder->Coders + i);

   for (i = 0; i < numCoders; i++)
   {
      uint8_t mainuint8_t;
      CSzCoderInfo *coder = folder->Coders + i;
      {
         unsigned idSize, j;
         uint8_t longID[15];
         RINOK(SzReaduint8_t(sd, &mainuint8_t));
         idSize = (unsigned)(mainuint8_t & 0xF);
         RINOK(SzReaduint8_ts(sd, longID, idSize));
         if (idSize > sizeof(coder->MethodID))
            return SZ_ERROR_UNSUPPORTED;
         coder->MethodID = 0;
         for (j = 0; j < idSize; j++)
            coder->MethodID |= (uint64_t)longID[idSize - 1 - j] << (8 * j);

         if ((mainuint8_t & 0x10) != 0)
         {
            RINOK(SzReadNumber32(sd, &coder->NumInStreams));
            RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
            if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||
                  coder->NumOutStreams > NUM_CODER_STREAMS_MAX)
               return SZ_ERROR_UNSUPPORTED;
         }
         else
         {
            coder->NumInStreams = 1;
            coder->NumOutStreams = 1;
         }
         if ((mainuint8_t & 0x20) != 0)
         {
            uint64_t propertiesSize = 0;
            RINOK(SzReadNumber(sd, &propertiesSize));
            if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))
               return SZ_ERROR_MEM;
            RINOK(SzReaduint8_ts(sd, coder->Props.data, (size_t)propertiesSize));
         }
      }
      while ((mainuint8_t & 0x80) != 0)
      {
         RINOK(SzReaduint8_t(sd, &mainuint8_t));
         RINOK(SzSkeepDataSize(sd, (mainuint8_t & 0xF)));
         if ((mainuint8_t & 0x10) != 0)
         {
            uint32_t n;
            RINOK(SzReadNumber32(sd, &n));
            RINOK(SzReadNumber32(sd, &n));
         }
         if ((mainuint8_t & 0x20) != 0)
         {
            uint64_t propertiesSize = 0;
            RINOK(SzReadNumber(sd, &propertiesSize));
            RINOK(SzSkeepDataSize(sd, propertiesSize));
         }
      }
      numInStreams += coder->NumInStreams;
      numOutStreams += coder->NumOutStreams;
   }

   if (numOutStreams == 0)
      return SZ_ERROR_UNSUPPORTED;

   folder->NumBindPairs = numBindPairs = numOutStreams - 1;
   MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);

   for (i = 0; i < numBindPairs; i++)
   {
      CSzBindPair *bp = folder->BindPairs + i;
      RINOK(SzReadNumber32(sd, &bp->InIndex));
      RINOK(SzReadNumber32(sd, &bp->OutIndex));
   }

   if (numInStreams < numBindPairs)
      return SZ_ERROR_UNSUPPORTED;

   folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
   MY_ALLOC(uint32_t, folder->PackStreams, (size_t)numPackStreams, alloc);

   if (numPackStreams == 1)
   {
      for (i = 0; i < numInStreams ; i++)
         if (SzFolder_FindBindPairForInStream(folder, i) < 0)
            break;
      if (i == numInStreams)
         return SZ_ERROR_UNSUPPORTED;
      folder->PackStreams[0] = i;
   }
   else
      for (i = 0; i < numPackStreams; i++)
      {
         RINOK(SzReadNumber32(sd, folder->PackStreams + i));
      }
   return SZ_OK;
}
Exemplo n.º 6
0
static SRes SzArEx_Open2(
      CSzArEx *p,
      ILookInStream *inStream,
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint8_t header[k7zStartHeaderSize];
   int64_t startArcPos;
   uint64_t nextHeaderOffset, nextHeaderSize;
   size_t nextHeaderSizeT;
   uint32_t nextHeaderCRC;
   CBuf buffer;
   SRes res;

   startArcPos = 0;
   RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));

   RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));

   if (!TestSignatureCandidate(header))
      return SZ_ERROR_NO_ARCHIVE;
   if (header[6] != k7zMajorVersion)
      return SZ_ERROR_UNSUPPORTED;

   nextHeaderOffset = GetUi64(header + 12);
   nextHeaderSize = GetUi64(header + 20);
   nextHeaderCRC = GetUi32(header + 28);

   p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;

   if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
      return SZ_ERROR_CRC;

   nextHeaderSizeT = (size_t)nextHeaderSize;
   if (nextHeaderSizeT != nextHeaderSize)
      return SZ_ERROR_MEM;
   if (nextHeaderSizeT == 0)
      return SZ_OK;
   if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
         nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
      return SZ_ERROR_NO_ARCHIVE;

   {
      int64_t pos = 0;
      RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
      if ((uint64_t)pos < startArcPos + nextHeaderOffset ||
            (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
            (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
         return SZ_ERROR_INPUT_EOF;
   }

   RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));

   if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
      return SZ_ERROR_MEM;

   res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);
   if (res == SZ_OK)
   {
      res = SZ_ERROR_ARCHIVE;
      if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
      {
         CSzData sd;
         uint64_t type;
         sd.Data = buffer.data;
         sd.Size = buffer.size;
         res = SzReadID(&sd, &type);
         if (res == SZ_OK)
         {
            if (type == k7zIdEncodedHeader)
            {
               CBuf outBuffer;
               Buf_Init(&outBuffer);
               res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);
               if (res != SZ_OK)
                  Buf_Free(&outBuffer, allocTemp);
               else
               {
                  Buf_Free(&buffer, allocTemp);
                  buffer.data = outBuffer.data;
                  buffer.size = outBuffer.size;
                  sd.Data = buffer.data;
                  sd.Size = buffer.size;
                  res = SzReadID(&sd, &type);
               }
            }
         }
         if (res == SZ_OK)
         {
            if (type == k7zIdHeader)
               res = SzReadHeader(p, &sd, allocMain, allocTemp);
            else
               res = SZ_ERROR_UNSUPPORTED;
         }
      }
   }
   Buf_Free(&buffer, allocTemp);
   return res;
}
Exemplo n.º 7
0
static SRes SzArEx_Open2(
    CSzArEx *p,
    ISeekInStream *inStream,
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  Byte header[k7zStartHeaderSize];
  Int64 startArcPos;
  UInt64 nextHeaderOffset, nextHeaderSize;
  size_t nextHeaderSizeT;
  UInt32 nextHeaderCRC;
  CBuf buffer;
  SRes res;
  size_t readSize;

  startArcPos = 0;
  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));

  readSize = k7zStartHeaderSize;
  res = inStream->Read(inStream, header, &readSize);
  if(res != SZ_OK)
	  return SZ_ERROR_NO_ARCHIVE;

  if (!TestSignatureCandidate(header))
    return SZ_ERROR_NO_ARCHIVE;
  if (header[6] != k7zMajorVersion)
    return SZ_ERROR_UNSUPPORTED;

  nextHeaderOffset = GetUi64(header + 12);
  nextHeaderSize = GetUi64(header + 20);
  nextHeaderCRC = GetUi32(header + 28);

  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
  
  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
    return SZ_ERROR_CRC;

  nextHeaderSizeT = (size_t)nextHeaderSize;
  if (nextHeaderSizeT != nextHeaderSize)
    return SZ_ERROR_MEM;
  if (nextHeaderSizeT == 0)
    return SZ_OK;
  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
    return SZ_ERROR_NO_ARCHIVE;

  {
	  Int64 pos = 0;
	  RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
	  if ((UInt64)pos < startArcPos + nextHeaderOffset ||
		  (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
		  (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
		  return SZ_ERROR_INPUT_EOF;

	  pos = startArcPos + k7zStartHeaderSize + nextHeaderOffset;
	  RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_SET));
  }


  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
    return SZ_ERROR_MEM;

  readSize = nextHeaderSizeT;
  res = inStream->Read(inStream, buffer.data, &readSize);
  if (res == SZ_OK)
  {
    res = SZ_ERROR_ARCHIVE;
    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
    {
      CSzData sd;
      UInt64 type;
      sd.Data = buffer.data;
      sd.Size = buffer.size;
      res = SzReadID(&sd, &type);
      if (res == SZ_OK)
      {
        if (type == k7zIdEncodedHeader)
        {
		  CMemOutStream outStream;
		  MemOutStream_Init(&outStream);
          res = SzReadAndDecodePackedStreams(inStream, &sd, &outStream.s, p->startPosAfterHeader, allocTemp);
          if (res != SZ_OK)
            Buf_Free((CBuf*)&outStream.data, allocTemp);
          else
          {
            Buf_Free(&buffer, allocTemp);
            buffer.data = outStream.data;
            buffer.size = outStream.size;
            sd.Data = buffer.data;
            sd.Size = buffer.size;
            res = SzReadID(&sd, &type);
          }
        }
      }
      if (res == SZ_OK)
      {
        if (type == k7zIdHeader)
          res = SzReadHeader(p, &sd, allocMain, allocTemp);
        else
          res = SZ_ERROR_UNSUPPORTED;
      }
    }
  }
  Buf_Free(&buffer, allocTemp);
  return res;
}