592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* 7zDec.c -- Decoding from 7z folder
 | 
						|
2017-04-03 : Igor Pavlov : Public domain */
 | 
						|
 | 
						|
#include "Precomp.h"
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
/* #define _7ZIP_PPMD_SUPPPORT */
 | 
						|
 | 
						|
#include "7z.h"
 | 
						|
#include "7zCrc.h"
 | 
						|
 | 
						|
#include "Bcj2.h"
 | 
						|
#include "Bra.h"
 | 
						|
#include "CpuArch.h"
 | 
						|
#include "Delta.h"
 | 
						|
#include "LzmaDec.h"
 | 
						|
#include "Lzma2Dec.h"
 | 
						|
#ifdef _7ZIP_PPMD_SUPPPORT
 | 
						|
#include "Ppmd7.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#define k_Copy 0
 | 
						|
#define k_Delta 3
 | 
						|
#define k_LZMA2 0x21
 | 
						|
#define k_LZMA  0x30101
 | 
						|
#define k_BCJ   0x3030103
 | 
						|
#define k_BCJ2  0x303011B
 | 
						|
#define k_PPC   0x3030205
 | 
						|
#define k_IA64  0x3030401
 | 
						|
#define k_ARM   0x3030501
 | 
						|
#define k_ARMT  0x3030701
 | 
						|
#define k_SPARC 0x3030805
 | 
						|
 | 
						|
 | 
						|
#ifdef _7ZIP_PPMD_SUPPPORT
 | 
						|
 | 
						|
#define k_PPMD 0x30401
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  IByteIn vt;
 | 
						|
  const Byte *cur;
 | 
						|
  const Byte *end;
 | 
						|
  const Byte *begin;
 | 
						|
  UInt64 processed;
 | 
						|
  Bool extra;
 | 
						|
  SRes res;
 | 
						|
  const ILookInStream *inStream;
 | 
						|
} CByteInToLook;
 | 
						|
 | 
						|
static Byte ReadByte(const IByteIn *pp)
 | 
						|
{
 | 
						|
  CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
 | 
						|
  if (p->cur != p->end)
 | 
						|
    return *p->cur++;
 | 
						|
  if (p->res == SZ_OK)
 | 
						|
  {
 | 
						|
    size_t size = p->cur - p->begin;
 | 
						|
    p->processed += size;
 | 
						|
    p->res = ILookInStream_Skip(p->inStream, size);
 | 
						|
    size = (1 << 25);
 | 
						|
    p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
 | 
						|
    p->cur = p->begin;
 | 
						|
    p->end = p->begin + size;
 | 
						|
    if (size != 0)
 | 
						|
      return *p->cur++;;
 | 
						|
  }
 | 
						|
  p->extra = True;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream,
 | 
						|
    Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | 
						|
{
 | 
						|
  CPpmd7 ppmd;
 | 
						|
  CByteInToLook s;
 | 
						|
  SRes res = SZ_OK;
 | 
						|
 | 
						|
  s.vt.Read = ReadByte;
 | 
						|
  s.inStream = inStream;
 | 
						|
  s.begin = s.end = s.cur = NULL;
 | 
						|
  s.extra = False;
 | 
						|
  s.res = SZ_OK;
 | 
						|
  s.processed = 0;
 | 
						|
 | 
						|
  if (propsSize != 5)
 | 
						|
    return SZ_ERROR_UNSUPPORTED;
 | 
						|
 | 
						|
  {
 | 
						|
    unsigned order = props[0];
 | 
						|
    UInt32 memSize = GetUi32(props + 1);
 | 
						|
    if (order < PPMD7_MIN_ORDER ||
 | 
						|
        order > PPMD7_MAX_ORDER ||
 | 
						|
        memSize < PPMD7_MIN_MEM_SIZE ||
 | 
						|
        memSize > PPMD7_MAX_MEM_SIZE)
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
    Ppmd7_Construct(&ppmd);
 | 
						|
    if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
 | 
						|
      return SZ_ERROR_MEM;
 | 
						|
    Ppmd7_Init(&ppmd, order);
 | 
						|
  }
 | 
						|
  {
 | 
						|
    CPpmd7z_RangeDec rc;
 | 
						|
    Ppmd7z_RangeDec_CreateVTable(&rc);
 | 
						|
    rc.Stream = &s.vt;
 | 
						|
    if (!Ppmd7z_RangeDec_Init(&rc))
 | 
						|
      res = SZ_ERROR_DATA;
 | 
						|
    else if (s.extra)
 | 
						|
      res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
 | 
						|
    else
 | 
						|
    {
 | 
						|
      SizeT i;
 | 
						|
      for (i = 0; i < outSize; i++)
 | 
						|
      {
 | 
						|
        int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
 | 
						|
        if (s.extra || sym < 0)
 | 
						|
          break;
 | 
						|
        outBuffer[i] = (Byte)sym;
 | 
						|
      }
 | 
						|
      if (i != outSize)
 | 
						|
        res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
 | 
						|
      else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
 | 
						|
        res = SZ_ERROR_DATA;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  Ppmd7_Free(&ppmd, allocMain);
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
 | 
						|
    Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | 
						|
{
 | 
						|
  CLzmaDec state;
 | 
						|
  SRes res = SZ_OK;
 | 
						|
 | 
						|
  LzmaDec_Construct(&state);
 | 
						|
  RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
 | 
						|
  state.dic = outBuffer;
 | 
						|
  state.dicBufSize = outSize;
 | 
						|
  LzmaDec_Init(&state);
 | 
						|
 | 
						|
  for (;;)
 | 
						|
  {
 | 
						|
    const void *inBuf = NULL;
 | 
						|
    size_t lookahead = (1 << 18);
 | 
						|
    if (lookahead > inSize)
 | 
						|
      lookahead = (size_t)inSize;
 | 
						|
    res = ILookInStream_Look(inStream, &inBuf, &lookahead);
 | 
						|
    if (res != SZ_OK)
 | 
						|
      break;
 | 
						|
 | 
						|
    {
 | 
						|
      SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
 | 
						|
      ELzmaStatus status;
 | 
						|
      res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
 | 
						|
      lookahead -= inProcessed;
 | 
						|
      inSize -= inProcessed;
 | 
						|
      if (res != SZ_OK)
 | 
						|
        break;
 | 
						|
 | 
						|
      if (status == LZMA_STATUS_FINISHED_WITH_MARK)
 | 
						|
      {
 | 
						|
        if (outSize != state.dicPos || inSize != 0)
 | 
						|
          res = SZ_ERROR_DATA;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
 | 
						|
        break;
 | 
						|
 | 
						|
      if (inProcessed == 0 && dicPos == state.dicPos)
 | 
						|
      {
 | 
						|
        res = SZ_ERROR_DATA;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      res = ILookInStream_Skip(inStream, inProcessed);
 | 
						|
      if (res != SZ_OK)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  LzmaDec_FreeProbs(&state, allocMain);
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifndef _7Z_NO_METHOD_LZMA2
 | 
						|
 | 
						|
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
 | 
						|
    Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
 | 
						|
{
 | 
						|
  CLzma2Dec state;
 | 
						|
  SRes res = SZ_OK;
 | 
						|
 | 
						|
  Lzma2Dec_Construct(&state);
 | 
						|
  if (propsSize != 1)
 | 
						|
    return SZ_ERROR_DATA;
 | 
						|
  RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
 | 
						|
  state.decoder.dic = outBuffer;
 | 
						|
  state.decoder.dicBufSize = outSize;
 | 
						|
  Lzma2Dec_Init(&state);
 | 
						|
 | 
						|
  for (;;)
 | 
						|
  {
 | 
						|
    const void *inBuf = NULL;
 | 
						|
    size_t lookahead = (1 << 18);
 | 
						|
    if (lookahead > inSize)
 | 
						|
      lookahead = (size_t)inSize;
 | 
						|
    res = ILookInStream_Look(inStream, &inBuf, &lookahead);
 | 
						|
    if (res != SZ_OK)
 | 
						|
      break;
 | 
						|
 | 
						|
    {
 | 
						|
      SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
 | 
						|
      ELzmaStatus status;
 | 
						|
      res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
 | 
						|
      lookahead -= inProcessed;
 | 
						|
      inSize -= inProcessed;
 | 
						|
      if (res != SZ_OK)
 | 
						|
        break;
 | 
						|
 | 
						|
      if (status == LZMA_STATUS_FINISHED_WITH_MARK)
 | 
						|
      {
 | 
						|
        if (outSize != state.decoder.dicPos || inSize != 0)
 | 
						|
          res = SZ_ERROR_DATA;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (inProcessed == 0 && dicPos == state.decoder.dicPos)
 | 
						|
      {
 | 
						|
        res = SZ_ERROR_DATA;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      res = ILookInStream_Skip(inStream, inProcessed);
 | 
						|
      if (res != SZ_OK)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Lzma2Dec_FreeProbs(&state, allocMain);
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
 | 
						|
{
 | 
						|
  while (inSize > 0)
 | 
						|
  {
 | 
						|
    const void *inBuf;
 | 
						|
    size_t curSize = (1 << 18);
 | 
						|
    if (curSize > inSize)
 | 
						|
      curSize = (size_t)inSize;
 | 
						|
    RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
 | 
						|
    if (curSize == 0)
 | 
						|
      return SZ_ERROR_INPUT_EOF;
 | 
						|
    memcpy(outBuffer, inBuf, curSize);
 | 
						|
    outBuffer += curSize;
 | 
						|
    inSize -= curSize;
 | 
						|
    RINOK(ILookInStream_Skip(inStream, curSize));
 | 
						|
  }
 | 
						|
  return SZ_OK;
 | 
						|
}
 | 
						|
 | 
						|
static Bool IS_MAIN_METHOD(UInt32 m)
 | 
						|
{
 | 
						|
  switch (m)
 | 
						|
  {
 | 
						|
    case k_Copy:
 | 
						|
    case k_LZMA:
 | 
						|
    #ifndef _7Z_NO_METHOD_LZMA2
 | 
						|
    case k_LZMA2:
 | 
						|
    #endif
 | 
						|
    #ifdef _7ZIP_PPMD_SUPPPORT
 | 
						|
    case k_PPMD:
 | 
						|
    #endif
 | 
						|
      return True;
 | 
						|
  }
 | 
						|
  return False;
 | 
						|
}
 | 
						|
 | 
						|
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
 | 
						|
{
 | 
						|
  return
 | 
						|
      c->NumStreams == 1
 | 
						|
      /* && c->MethodID <= (UInt32)0xFFFFFFFF */
 | 
						|
      && IS_MAIN_METHOD((UInt32)c->MethodID);
 | 
						|
}
 | 
						|
 | 
						|
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
 | 
						|
 | 
						|
static SRes CheckSupportedFolder(const CSzFolder *f)
 | 
						|
{
 | 
						|
  if (f->NumCoders < 1 || f->NumCoders > 4)
 | 
						|
    return SZ_ERROR_UNSUPPORTED;
 | 
						|
  if (!IS_SUPPORTED_CODER(&f->Coders[0]))
 | 
						|
    return SZ_ERROR_UNSUPPORTED;
 | 
						|
  if (f->NumCoders == 1)
 | 
						|
  {
 | 
						|
    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
    return SZ_OK;
 | 
						|
  }
 | 
						|
  
 | 
						|
  
 | 
						|
  #ifndef _7Z_NO_METHODS_FILTERS
 | 
						|
 | 
						|
  if (f->NumCoders == 2)
 | 
						|
  {
 | 
						|
    const CSzCoderInfo *c = &f->Coders[1];
 | 
						|
    if (
 | 
						|
        /* c->MethodID > (UInt32)0xFFFFFFFF || */
 | 
						|
        c->NumStreams != 1
 | 
						|
        || f->NumPackStreams != 1
 | 
						|
        || f->PackStreams[0] != 0
 | 
						|
        || f->NumBonds != 1
 | 
						|
        || f->Bonds[0].InIndex != 1
 | 
						|
        || f->Bonds[0].OutIndex != 0)
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
    switch ((UInt32)c->MethodID)
 | 
						|
    {
 | 
						|
      case k_Delta:
 | 
						|
      case k_BCJ:
 | 
						|
      case k_PPC:
 | 
						|
      case k_IA64:
 | 
						|
      case k_SPARC:
 | 
						|
      case k_ARM:
 | 
						|
      case k_ARMT:
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        return SZ_ERROR_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    return SZ_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  #endif
 | 
						|
 | 
						|
  
 | 
						|
  if (f->NumCoders == 4)
 | 
						|
  {
 | 
						|
    if (!IS_SUPPORTED_CODER(&f->Coders[1])
 | 
						|
        || !IS_SUPPORTED_CODER(&f->Coders[2])
 | 
						|
        || !IS_BCJ2(&f->Coders[3]))
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
    if (f->NumPackStreams != 4
 | 
						|
        || f->PackStreams[0] != 2
 | 
						|
        || f->PackStreams[1] != 6
 | 
						|
        || f->PackStreams[2] != 1
 | 
						|
        || f->PackStreams[3] != 0
 | 
						|
        || f->NumBonds != 3
 | 
						|
        || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
 | 
						|
        || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
 | 
						|
        || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
    return SZ_OK;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return SZ_ERROR_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
 | 
						|
 | 
						|
static SRes SzFolder_Decode2(const CSzFolder *folder,
 | 
						|
    const Byte *propsData,
 | 
						|
    const UInt64 *unpackSizes,
 | 
						|
    const UInt64 *packPositions,
 | 
						|
    ILookInStream *inStream, UInt64 startPos,
 | 
						|
    Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
 | 
						|
    Byte *tempBuf[])
 | 
						|
{
 | 
						|
  UInt32 ci;
 | 
						|
  SizeT tempSizes[3] = { 0, 0, 0};
 | 
						|
  SizeT tempSize3 = 0;
 | 
						|
  Byte *tempBuf3 = 0;
 | 
						|
 | 
						|
  RINOK(CheckSupportedFolder(folder));
 | 
						|
 | 
						|
  for (ci = 0; ci < folder->NumCoders; ci++)
 | 
						|
  {
 | 
						|
    const CSzCoderInfo *coder = &folder->Coders[ci];
 | 
						|
 | 
						|
    if (IS_MAIN_METHOD((UInt32)coder->MethodID))
 | 
						|
    {
 | 
						|
      UInt32 si = 0;
 | 
						|
      UInt64 offset;
 | 
						|
      UInt64 inSize;
 | 
						|
      Byte *outBufCur = outBuffer;
 | 
						|
      SizeT outSizeCur = outSize;
 | 
						|
      if (folder->NumCoders == 4)
 | 
						|
      {
 | 
						|
        UInt32 indices[] = { 3, 2, 0 };
 | 
						|
        UInt64 unpackSize = unpackSizes[ci];
 | 
						|
        si = indices[ci];
 | 
						|
        if (ci < 2)
 | 
						|
        {
 | 
						|
          Byte *temp;
 | 
						|
          outSizeCur = (SizeT)unpackSize;
 | 
						|
          if (outSizeCur != unpackSize)
 | 
						|
            return SZ_ERROR_MEM;
 | 
						|
          temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
 | 
						|
          if (!temp && outSizeCur != 0)
 | 
						|
            return SZ_ERROR_MEM;
 | 
						|
          outBufCur = tempBuf[1 - ci] = temp;
 | 
						|
          tempSizes[1 - ci] = outSizeCur;
 | 
						|
        }
 | 
						|
        else if (ci == 2)
 | 
						|
        {
 | 
						|
          if (unpackSize > outSize) /* check it */
 | 
						|
            return SZ_ERROR_PARAM;
 | 
						|
          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
 | 
						|
          tempSize3 = outSizeCur = (SizeT)unpackSize;
 | 
						|
        }
 | 
						|
        else
 | 
						|
          return SZ_ERROR_UNSUPPORTED;
 | 
						|
      }
 | 
						|
      offset = packPositions[si];
 | 
						|
      inSize = packPositions[(size_t)si + 1] - offset;
 | 
						|
      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
 | 
						|
 | 
						|
      if (coder->MethodID == k_Copy)
 | 
						|
      {
 | 
						|
        if (inSize != outSizeCur) /* check it */
 | 
						|
          return SZ_ERROR_DATA;
 | 
						|
        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
 | 
						|
      }
 | 
						|
      else if (coder->MethodID == k_LZMA)
 | 
						|
      {
 | 
						|
        RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | 
						|
      }
 | 
						|
      #ifndef _7Z_NO_METHOD_LZMA2
 | 
						|
      else if (coder->MethodID == k_LZMA2)
 | 
						|
      {
 | 
						|
        RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | 
						|
      }
 | 
						|
      #endif
 | 
						|
      #ifdef _7ZIP_PPMD_SUPPPORT
 | 
						|
      else if (coder->MethodID == k_PPMD)
 | 
						|
      {
 | 
						|
        RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
 | 
						|
      }
 | 
						|
      #endif
 | 
						|
      else
 | 
						|
        return SZ_ERROR_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    else if (coder->MethodID == k_BCJ2)
 | 
						|
    {
 | 
						|
      UInt64 offset = packPositions[1];
 | 
						|
      UInt64 s3Size = packPositions[2] - offset;
 | 
						|
      
 | 
						|
      if (ci != 3)
 | 
						|
        return SZ_ERROR_UNSUPPORTED;
 | 
						|
      
 | 
						|
      tempSizes[2] = (SizeT)s3Size;
 | 
						|
      if (tempSizes[2] != s3Size)
 | 
						|
        return SZ_ERROR_MEM;
 | 
						|
      tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
 | 
						|
      if (!tempBuf[2] && tempSizes[2] != 0)
 | 
						|
        return SZ_ERROR_MEM;
 | 
						|
      
 | 
						|
      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
 | 
						|
      RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
 | 
						|
 | 
						|
      if ((tempSizes[0] & 3) != 0 ||
 | 
						|
          (tempSizes[1] & 3) != 0 ||
 | 
						|
          tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
 | 
						|
        return SZ_ERROR_DATA;
 | 
						|
 | 
						|
      {
 | 
						|
        CBcj2Dec p;
 | 
						|
        
 | 
						|
        p.bufs[0] = tempBuf3;   p.lims[0] = tempBuf3 + tempSize3;
 | 
						|
        p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
 | 
						|
        p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
 | 
						|
        p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
 | 
						|
        
 | 
						|
        p.dest = outBuffer;
 | 
						|
        p.destLim = outBuffer + outSize;
 | 
						|
        
 | 
						|
        Bcj2Dec_Init(&p);
 | 
						|
        RINOK(Bcj2Dec_Decode(&p));
 | 
						|
 | 
						|
        {
 | 
						|
          unsigned i;
 | 
						|
          for (i = 0; i < 4; i++)
 | 
						|
            if (p.bufs[i] != p.lims[i])
 | 
						|
              return SZ_ERROR_DATA;
 | 
						|
          
 | 
						|
          if (!Bcj2Dec_IsFinished(&p))
 | 
						|
            return SZ_ERROR_DATA;
 | 
						|
 | 
						|
          if (p.dest != p.destLim
 | 
						|
             || p.state != BCJ2_STREAM_MAIN)
 | 
						|
            return SZ_ERROR_DATA;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    #ifndef _7Z_NO_METHODS_FILTERS
 | 
						|
    else if (ci == 1)
 | 
						|
    {
 | 
						|
      if (coder->MethodID == k_Delta)
 | 
						|
      {
 | 
						|
        if (coder->PropsSize != 1)
 | 
						|
          return SZ_ERROR_UNSUPPORTED;
 | 
						|
        {
 | 
						|
          Byte state[DELTA_STATE_SIZE];
 | 
						|
          Delta_Init(state);
 | 
						|
          Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (coder->PropsSize != 0)
 | 
						|
          return SZ_ERROR_UNSUPPORTED;
 | 
						|
        switch (coder->MethodID)
 | 
						|
        {
 | 
						|
          case k_BCJ:
 | 
						|
          {
 | 
						|
            UInt32 state;
 | 
						|
            x86_Convert_Init(state);
 | 
						|
            x86_Convert(outBuffer, outSize, 0, &state, 0);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
          CASE_BRA_CONV(PPC)
 | 
						|
          CASE_BRA_CONV(IA64)
 | 
						|
          CASE_BRA_CONV(SPARC)
 | 
						|
          CASE_BRA_CONV(ARM)
 | 
						|
          CASE_BRA_CONV(ARMT)
 | 
						|
          default:
 | 
						|
            return SZ_ERROR_UNSUPPORTED;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    #endif
 | 
						|
    else
 | 
						|
      return SZ_ERROR_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return SZ_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
 | 
						|
    ILookInStream *inStream, UInt64 startPos,
 | 
						|
    Byte *outBuffer, size_t outSize,
 | 
						|
    ISzAllocPtr allocMain)
 | 
						|
{
 | 
						|
  SRes res;
 | 
						|
  CSzFolder folder;
 | 
						|
  CSzData sd;
 | 
						|
  
 | 
						|
  const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
 | 
						|
  sd.Data = data;
 | 
						|
  sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
 | 
						|
  
 | 
						|
  res = SzGetNextFolderItem(&folder, &sd);
 | 
						|
  
 | 
						|
  if (res != SZ_OK)
 | 
						|
    return res;
 | 
						|
 | 
						|
  if (sd.Size != 0
 | 
						|
      || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
 | 
						|
      || outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
 | 
						|
    return SZ_ERROR_FAIL;
 | 
						|
  {
 | 
						|
    unsigned i;
 | 
						|
    Byte *tempBuf[3] = { 0, 0, 0};
 | 
						|
 | 
						|
    res = SzFolder_Decode2(&folder, data,
 | 
						|
        &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
 | 
						|
        p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
 | 
						|
        inStream, startPos,
 | 
						|
        outBuffer, (SizeT)outSize, allocMain, tempBuf);
 | 
						|
    
 | 
						|
    for (i = 0; i < 3; i++)
 | 
						|
      ISzAlloc_Free(allocMain, tempBuf[i]);
 | 
						|
 | 
						|
    if (res == SZ_OK)
 | 
						|
      if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
 | 
						|
        if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
 | 
						|
          res = SZ_ERROR_CRC;
 | 
						|
 | 
						|
    return res;
 | 
						|
  }
 | 
						|
}
 |