misc/libphysfs/lzma/C/Archive/7z/7zDecode.c
changeset 12213 bb5522e88ab2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zDecode.c	Mon Apr 10 12:06:43 2017 -0400
@@ -0,0 +1,345 @@
+/* 7zDecode.c */
+
+#include <memory.h>
+
+/* BEGIN PHYSFS CHANGE */
+#include <string.h>
+/* END PHYSFS CHANGE */
+
+#include "7zDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#else
+#include "../../Compress/Lzma/LzmaDecode.h"
+#include "../../Compress/Branch/BranchX86.h"
+#include "../../Compress/Branch/BranchX86_2.h"
+#endif
+
+#define k_Copy 0
+#define k_LZMA 0x30101
+#define k_BCJ 0x03030103
+#define k_BCJ2 0x0303011B
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+  ILzmaInCallback InCallback;
+  ISzInStream *InStream;
+  CFileSize Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
+{
+  CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+  size_t processedSize;
+  SZ_RESULT res;
+  size_t curSize = (1 << 20);
+  if (curSize > cb->Size)
+    curSize = (size_t)cb->Size;
+  *size = 0;
+  res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
+  *size = (SizeT)processedSize;
+  if (processedSize > curSize)
+    return (int)SZE_FAIL;
+  cb->Size -= processedSize;
+  if (res == SZ_OK)
+    return 0;
+  return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+  #ifdef _LZMA_IN_CB
+  CLzmaInCallbackImp lzmaCallback;
+  #else
+  SizeT inProcessed;
+  #endif
+  
+  CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
+  int result;
+  SizeT outSizeProcessedLoc;
+  
+  #ifdef _LZMA_IN_CB
+  lzmaCallback.Size = inSize;
+  lzmaCallback.InStream = inStream;
+  lzmaCallback.InCallback.Read = LzmaReadImp;
+  #endif
+  
+  if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, 
+      (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
+    return SZE_FAIL;
+  
+  state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+  if (state.Probs == 0)
+    return SZE_OUTOFMEMORY;
+  
+  #ifdef _LZMA_OUT_READ
+  if (state.Properties.DictionarySize == 0)
+    state.Dictionary = 0;
+  else
+  {
+    state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+    if (state.Dictionary == 0)
+    {
+      allocMain->Free(state.Probs);
+      return SZE_OUTOFMEMORY;
+    }
+  }
+  LzmaDecoderInit(&state);
+  #endif
+  
+  result = LzmaDecode(&state,
+  #ifdef _LZMA_IN_CB
+    &lzmaCallback.InCallback,
+  #else
+    inBuffer, (SizeT)inSize, &inProcessed,
+  #endif
+    outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+  allocMain->Free(state.Probs);
+  #ifdef _LZMA_OUT_READ
+  allocMain->Free(state.Dictionary);
+  #endif
+  if (result == LZMA_RESULT_DATA_ERROR)
+    return SZE_DATA_ERROR;
+  if (result != LZMA_RESULT_OK)
+    return SZE_FAIL;
+  return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
+}
+
+#ifdef _LZMA_IN_CB
+SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
+{
+  while (inSize > 0)
+  {
+    void *inBuffer;
+    size_t processedSize, curSize = (1 << 18);
+    if (curSize > inSize)
+      curSize = (size_t)(inSize);
+    RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
+    if (processedSize == 0)
+      return SZE_DATA_ERROR;
+    if (processedSize > curSize)
+      return SZE_FAIL;
+    memcpy(outBuffer, inBuffer, processedSize);
+    outBuffer += processedSize;
+    inSize -= processedSize;
+  }
+  return SZ_OK;
+}
+#endif
+
+#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
+#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
+#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
+#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
+
+SZ_RESULT CheckSupportedFolder(const CFolder *f)
+{
+  if (f->NumCoders < 1 || f->NumCoders > 4)
+    return SZE_NOTIMPL;
+  if (IS_UNSUPPORTED_CODER(f->Coders[0]))
+    return SZE_NOTIMPL;
+  if (f->NumCoders == 1)
+  {
+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
+      return SZE_NOTIMPL;
+    return SZ_OK;
+  }
+  if (f->NumCoders == 2)
+  {
+    if (IS_NO_BCJ(f->Coders[1]) ||
+        f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
+        f->NumBindPairs != 1 ||
+        f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
+      return SZE_NOTIMPL;
+    return SZ_OK;
+  }
+  if (f->NumCoders == 4)
+  {
+    if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
+        IS_UNSUPPORTED_CODER(f->Coders[2]) ||
+        IS_NO_BCJ2(f->Coders[3]))
+      return SZE_NOTIMPL;
+    if (f->NumPackStreams != 4 || 
+        f->PackStreams[0] != 2 ||
+        f->PackStreams[1] != 6 ||
+        f->PackStreams[2] != 1 ||
+        f->PackStreams[3] != 0 ||
+        f->NumBindPairs != 3 ||
+        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
+        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
+        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
+      return SZE_NOTIMPL;
+    return SZ_OK;
+  }
+  return SZE_NOTIMPL;
+}
+
+CFileSize GetSum(const CFileSize *values, UInt32 index)
+{
+  CFileSize sum = 0;
+  UInt32 i;
+  for (i = 0; i < index; i++)
+    sum += values[i];
+  return sum;
+}
+
+SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream, CFileSize startPos,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
+    Byte *tempBuf[])
+{
+  UInt32 ci;
+  size_t tempSizes[3] = { 0, 0, 0};
+  size_t tempSize3 = 0;
+  Byte *tempBuf3 = 0;
+
+  RINOK(CheckSupportedFolder(folder));
+
+  for (ci = 0; ci < folder->NumCoders; ci++)
+  {
+    CCoderInfo *coder = &folder->Coders[ci];
+
+    if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
+    {
+      UInt32 si = 0;
+      CFileSize offset;
+      CFileSize inSize;
+      Byte *outBufCur = outBuffer;
+      size_t outSizeCur = outSize;
+      if (folder->NumCoders == 4)
+      {
+        UInt32 indices[] = { 3, 2, 0 };
+        CFileSize unpackSize = folder->UnPackSizes[ci];
+        si = indices[ci];
+        if (ci < 2)
+        {
+          Byte *temp;
+          outSizeCur = (size_t)unpackSize;
+          if (outSizeCur != unpackSize)
+            return SZE_OUTOFMEMORY;
+          temp = (Byte *)allocMain->Alloc(outSizeCur);
+          if (temp == 0 && outSizeCur != 0)
+            return SZE_OUTOFMEMORY;
+          outBufCur = tempBuf[1 - ci] = temp;
+          tempSizes[1 - ci] = outSizeCur;
+        }
+        else if (ci == 2)
+        {
+          if (unpackSize > outSize)
+            return SZE_OUTOFMEMORY;
+          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
+          tempSize3 = outSizeCur = (size_t)unpackSize;
+        }
+        else
+          return SZE_NOTIMPL;
+      }
+      offset = GetSum(packSizes, si);
+      inSize = packSizes[si];
+      #ifdef _LZMA_IN_CB
+      RINOK(inStream->Seek(inStream, startPos + offset));
+      #endif
+
+      if (coder->MethodID == k_Copy)
+      {
+        if (inSize != outSizeCur)
+          return SZE_DATA_ERROR;
+        
+        #ifdef _LZMA_IN_CB
+        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
+        #else
+        memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
+        #endif
+      }
+      else
+      {
+        SZ_RESULT res = SzDecodeLzma(coder, inSize,
+            #ifdef _LZMA_IN_CB
+            inStream,
+            #else
+            inBuffer + (size_t)offset,
+            #endif
+            outBufCur, outSizeCur, allocMain);
+        RINOK(res)
+      }
+    }
+    else if (coder->MethodID == k_BCJ)
+    {
+      UInt32 state;
+      if (ci != 1)
+        return SZE_NOTIMPL;
+      x86_Convert_Init(state);
+      x86_Convert(outBuffer, outSize, 0, &state, 0);
+    }
+    else if (coder->MethodID == k_BCJ2)
+    {
+      CFileSize offset = GetSum(packSizes, 1);
+      CFileSize s3Size = packSizes[1];
+      SZ_RESULT res;
+      if (ci != 3)
+        return SZE_NOTIMPL;
+
+      #ifdef _LZMA_IN_CB
+      RINOK(inStream->Seek(inStream, startPos + offset));
+      tempSizes[2] = (size_t)s3Size;
+      if (tempSizes[2] != s3Size)
+        return SZE_OUTOFMEMORY;
+      tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
+      if (tempBuf[2] == 0 && tempSizes[2] != 0)
+        return SZE_OUTOFMEMORY;
+      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
+      RINOK(res)
+      #endif
+
+      res = x86_2_Decode(
+          tempBuf3, tempSize3, 
+          tempBuf[0], tempSizes[0], 
+          tempBuf[1], tempSizes[1], 
+          #ifdef _LZMA_IN_CB
+          tempBuf[2], tempSizes[2], 
+          #else
+          inBuffer + (size_t)offset, (size_t)s3Size, 
+          #endif
+          outBuffer, outSize);
+      RINOK(res)
+    }
+    else 
+      return SZE_NOTIMPL;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream, CFileSize startPos,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+  Byte *tempBuf[3] = { 0, 0, 0};
+  int i;
+  SZ_RESULT res = SzDecode2(packSizes, folder,
+      #ifdef _LZMA_IN_CB
+      inStream, startPos,
+      #else
+      inBuffer,
+      #endif
+      outBuffer, outSize, allocMain, tempBuf);
+  for (i = 0; i < 3; i++)
+    allocMain->Free(tempBuf[i]);
+  return res;
+}