592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			592 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /* 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; | ||
|  |   } | ||
|  | } |