Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* 7zDec.c -- Decoding from 7z folder
  2. 2015-08-01 : Igor Pavlov : Public domain */
  3.  
  4. #include "Precomp.h"
  5.  
  6. #include <string.h>
  7.  
  8. /* #define _7ZIP_PPMD_SUPPPORT */
  9.  
  10. #include "7z.h"
  11.  
  12. #include "Bcj2.h"
  13. #include "Bra.h"
  14. #include "CpuArch.h"
  15. #include "Delta.h"
  16. #include "LzmaDec.h"
  17. #include "Lzma2Dec.h"
  18. #ifdef _7ZIP_PPMD_SUPPPORT
  19. #include "Ppmd7.h"
  20. #endif
  21.  
  22. #define k_Copy 0
  23. #define k_Delta 3
  24. #define k_LZMA2 0x21
  25. #define k_LZMA  0x30101
  26. #define k_BCJ   0x3030103
  27. #define k_BCJ2  0x303011B
  28. #define k_PPC   0x3030205
  29. #define k_IA64  0x3030401
  30. #define k_ARM   0x3030501
  31. #define k_ARMT  0x3030701
  32. #define k_SPARC 0x3030805
  33.  
  34.  
  35. #ifdef _7ZIP_PPMD_SUPPPORT
  36.  
  37. #define k_PPMD 0x30401
  38.  
  39. typedef struct
  40. {
  41.   IByteIn p;
  42.   const Byte *cur;
  43.   const Byte *end;
  44.   const Byte *begin;
  45.   UInt64 processed;
  46.   Bool extra;
  47.   SRes res;
  48.   ILookInStream *inStream;
  49. } CByteInToLook;
  50.  
  51. static Byte ReadByte(void *pp)
  52. {
  53.   CByteInToLook *p = (CByteInToLook *)pp;
  54.   if (p->cur != p->end)
  55.     return *p->cur++;
  56.   if (p->res == SZ_OK)
  57.   {
  58.     size_t size = p->cur - p->begin;
  59.     p->processed += size;
  60.     p->res = p->inStream->Skip(p->inStream, size);
  61.     size = (1 << 25);
  62.     p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
  63.     p->cur = p->begin;
  64.     p->end = p->begin + size;
  65.     if (size != 0)
  66.       return *p->cur++;;
  67.   }
  68.   p->extra = True;
  69.   return 0;
  70. }
  71.  
  72. static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
  73.     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
  74. {
  75.   CPpmd7 ppmd;
  76.   CByteInToLook s;
  77.   SRes res = SZ_OK;
  78.  
  79.   s.p.Read = ReadByte;
  80.   s.inStream = inStream;
  81.   s.begin = s.end = s.cur = NULL;
  82.   s.extra = False;
  83.   s.res = SZ_OK;
  84.   s.processed = 0;
  85.  
  86.   if (propsSize != 5)
  87.     return SZ_ERROR_UNSUPPORTED;
  88.  
  89.   {
  90.     unsigned order = props[0];
  91.     UInt32 memSize = GetUi32(props + 1);
  92.     if (order < PPMD7_MIN_ORDER ||
  93.         order > PPMD7_MAX_ORDER ||
  94.         memSize < PPMD7_MIN_MEM_SIZE ||
  95.         memSize > PPMD7_MAX_MEM_SIZE)
  96.       return SZ_ERROR_UNSUPPORTED;
  97.     Ppmd7_Construct(&ppmd);
  98.     if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
  99.       return SZ_ERROR_MEM;
  100.     Ppmd7_Init(&ppmd, order);
  101.   }
  102.   {
  103.     CPpmd7z_RangeDec rc;
  104.     Ppmd7z_RangeDec_CreateVTable(&rc);
  105.     rc.Stream = &s.p;
  106.     if (!Ppmd7z_RangeDec_Init(&rc))
  107.       res = SZ_ERROR_DATA;
  108.     else if (s.extra)
  109.       res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
  110.     else
  111.     {
  112.       SizeT i;
  113.       for (i = 0; i < outSize; i++)
  114.       {
  115.         int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
  116.         if (s.extra || sym < 0)
  117.           break;
  118.         outBuffer[i] = (Byte)sym;
  119.       }
  120.       if (i != outSize)
  121.         res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
  122.       else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
  123.         res = SZ_ERROR_DATA;
  124.     }
  125.   }
  126.   Ppmd7_Free(&ppmd, allocMain);
  127.   return res;
  128. }
  129.  
  130. #endif
  131.  
  132.  
  133. static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
  134.     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
  135. {
  136.   CLzmaDec state;
  137.   SRes res = SZ_OK;
  138.  
  139.   LzmaDec_Construct(&state);
  140.   RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
  141.   state.dic = outBuffer;
  142.   state.dicBufSize = outSize;
  143.   LzmaDec_Init(&state);
  144.  
  145.   for (;;)
  146.   {
  147.     const void *inBuf = NULL;
  148.     size_t lookahead = (1 << 18);
  149.     if (lookahead > inSize)
  150.       lookahead = (size_t)inSize;
  151.     res = inStream->Look(inStream, &inBuf, &lookahead);
  152.     if (res != SZ_OK)
  153.       break;
  154.  
  155.     {
  156.       SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
  157.       ELzmaStatus status;
  158.       res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
  159.       lookahead -= inProcessed;
  160.       inSize -= inProcessed;
  161.       if (res != SZ_OK)
  162.         break;
  163.       if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
  164.       {
  165.         if (state.dicBufSize != outSize || lookahead != 0 ||
  166.             (status != LZMA_STATUS_FINISHED_WITH_MARK &&
  167.              status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
  168.           res = SZ_ERROR_DATA;
  169.         break;
  170.       }
  171.       res = inStream->Skip((void *)inStream, inProcessed);
  172.       if (res != SZ_OK)
  173.         break;
  174.     }
  175.   }
  176.  
  177.   LzmaDec_FreeProbs(&state, allocMain);
  178.   return res;
  179. }
  180.  
  181.  
  182. #ifndef _7Z_NO_METHOD_LZMA2
  183.  
  184. static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
  185.     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
  186. {
  187.   CLzma2Dec state;
  188.   SRes res = SZ_OK;
  189.  
  190.   Lzma2Dec_Construct(&state);
  191.   if (propsSize != 1)
  192.     return SZ_ERROR_DATA;
  193.   RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
  194.   state.decoder.dic = outBuffer;
  195.   state.decoder.dicBufSize = outSize;
  196.   Lzma2Dec_Init(&state);
  197.  
  198.   for (;;)
  199.   {
  200.     const void *inBuf = NULL;
  201.     size_t lookahead = (1 << 18);
  202.     if (lookahead > inSize)
  203.       lookahead = (size_t)inSize;
  204.     res = inStream->Look(inStream, &inBuf, &lookahead);
  205.     if (res != SZ_OK)
  206.       break;
  207.  
  208.     {
  209.       SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
  210.       ELzmaStatus status;
  211.       res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
  212.       lookahead -= inProcessed;
  213.       inSize -= inProcessed;
  214.       if (res != SZ_OK)
  215.         break;
  216.       if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
  217.       {
  218.         if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
  219.             (status != LZMA_STATUS_FINISHED_WITH_MARK))
  220.           res = SZ_ERROR_DATA;
  221.         break;
  222.       }
  223.       res = inStream->Skip((void *)inStream, inProcessed);
  224.       if (res != SZ_OK)
  225.         break;
  226.     }
  227.   }
  228.  
  229.   Lzma2Dec_FreeProbs(&state, allocMain);
  230.   return res;
  231. }
  232.  
  233. #endif
  234.  
  235.  
  236. static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
  237. {
  238.   while (inSize > 0)
  239.   {
  240.     const void *inBuf;
  241.     size_t curSize = (1 << 18);
  242.     if (curSize > inSize)
  243.       curSize = (size_t)inSize;
  244.     RINOK(inStream->Look(inStream, &inBuf, &curSize));
  245.     if (curSize == 0)
  246.       return SZ_ERROR_INPUT_EOF;
  247.     memcpy(outBuffer, inBuf, curSize);
  248.     outBuffer += curSize;
  249.     inSize -= curSize;
  250.     RINOK(inStream->Skip((void *)inStream, curSize));
  251.   }
  252.   return SZ_OK;
  253. }
  254.  
  255. static Bool IS_MAIN_METHOD(UInt32 m)
  256. {
  257.   switch (m)
  258.   {
  259.     case k_Copy:
  260.     case k_LZMA:
  261.     #ifndef _7Z_NO_METHOD_LZMA2
  262.     case k_LZMA2:
  263.     #endif
  264.     #ifdef _7ZIP_PPMD_SUPPPORT
  265.     case k_PPMD:
  266.     #endif
  267.       return True;
  268.   }
  269.   return False;
  270. }
  271.  
  272. static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
  273. {
  274.   return
  275.       c->NumStreams == 1
  276.       /* && c->MethodID <= (UInt32)0xFFFFFFFF */
  277.       && IS_MAIN_METHOD((UInt32)c->MethodID);
  278. }
  279.  
  280. #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
  281.  
  282. static SRes CheckSupportedFolder(const CSzFolder *f)
  283. {
  284.   if (f->NumCoders < 1 || f->NumCoders > 4)
  285.     return SZ_ERROR_UNSUPPORTED;
  286.   if (!IS_SUPPORTED_CODER(&f->Coders[0]))
  287.     return SZ_ERROR_UNSUPPORTED;
  288.   if (f->NumCoders == 1)
  289.   {
  290.     if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
  291.       return SZ_ERROR_UNSUPPORTED;
  292.     return SZ_OK;
  293.   }
  294.  
  295.  
  296.   #ifndef _7Z_NO_METHODS_FILTERS
  297.  
  298.   if (f->NumCoders == 2)
  299.   {
  300.     const CSzCoderInfo *c = &f->Coders[1];
  301.     if (
  302.         /* c->MethodID > (UInt32)0xFFFFFFFF || */
  303.         c->NumStreams != 1
  304.         || f->NumPackStreams != 1
  305.         || f->PackStreams[0] != 0
  306.         || f->NumBonds != 1
  307.         || f->Bonds[0].InIndex != 1
  308.         || f->Bonds[0].OutIndex != 0)
  309.       return SZ_ERROR_UNSUPPORTED;
  310.     switch ((UInt32)c->MethodID)
  311.     {
  312.       case k_Delta:
  313.       case k_BCJ:
  314.       case k_PPC:
  315.       case k_IA64:
  316.       case k_SPARC:
  317.       case k_ARM:
  318.       case k_ARMT:
  319.         break;
  320.       default:
  321.         return SZ_ERROR_UNSUPPORTED;
  322.     }
  323.     return SZ_OK;
  324.   }
  325.  
  326.   #endif
  327.  
  328.  
  329.   if (f->NumCoders == 4)
  330.   {
  331.     if (!IS_SUPPORTED_CODER(&f->Coders[1])
  332.         || !IS_SUPPORTED_CODER(&f->Coders[2])
  333.         || !IS_BCJ2(&f->Coders[3]))
  334.       return SZ_ERROR_UNSUPPORTED;
  335.     if (f->NumPackStreams != 4
  336.         || f->PackStreams[0] != 2
  337.         || f->PackStreams[1] != 6
  338.         || f->PackStreams[2] != 1
  339.         || f->PackStreams[3] != 0
  340.         || f->NumBonds != 3
  341.         || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
  342.         || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
  343.         || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
  344.       return SZ_ERROR_UNSUPPORTED;
  345.     return SZ_OK;
  346.   }
  347.  
  348.   return SZ_ERROR_UNSUPPORTED;
  349. }
  350.  
  351. #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
  352.  
  353. static SRes SzFolder_Decode2(const CSzFolder *folder,
  354.     const Byte *propsData,
  355.     const UInt64 *unpackSizes,
  356.     const UInt64 *packPositions,
  357.     ILookInStream *inStream, UInt64 startPos,
  358.     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
  359.     Byte *tempBuf[])
  360. {
  361.   UInt32 ci;
  362.   SizeT tempSizes[3] = { 0, 0, 0};
  363.   SizeT tempSize3 = 0;
  364.   Byte *tempBuf3 = 0;
  365.  
  366.   RINOK(CheckSupportedFolder(folder));
  367.  
  368.   for (ci = 0; ci < folder->NumCoders; ci++)
  369.   {
  370.     const CSzCoderInfo *coder = &folder->Coders[ci];
  371.  
  372.     if (IS_MAIN_METHOD((UInt32)coder->MethodID))
  373.     {
  374.       UInt32 si = 0;
  375.       UInt64 offset;
  376.       UInt64 inSize;
  377.       Byte *outBufCur = outBuffer;
  378.       SizeT outSizeCur = outSize;
  379.       if (folder->NumCoders == 4)
  380.       {
  381.         UInt32 indices[] = { 3, 2, 0 };
  382.         UInt64 unpackSize = unpackSizes[ci];
  383.         si = indices[ci];
  384.         if (ci < 2)
  385.         {
  386.           Byte *temp;
  387.           outSizeCur = (SizeT)unpackSize;
  388.           if (outSizeCur != unpackSize)
  389.             return SZ_ERROR_MEM;
  390.           temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
  391.           if (!temp && outSizeCur != 0)
  392.             return SZ_ERROR_MEM;
  393.           outBufCur = tempBuf[1 - ci] = temp;
  394.           tempSizes[1 - ci] = outSizeCur;
  395.         }
  396.         else if (ci == 2)
  397.         {
  398.           if (unpackSize > outSize) /* check it */
  399.             return SZ_ERROR_PARAM;
  400.           tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
  401.           tempSize3 = outSizeCur = (SizeT)unpackSize;
  402.         }
  403.         else
  404.           return SZ_ERROR_UNSUPPORTED;
  405.       }
  406.       offset = packPositions[si];
  407.       inSize = packPositions[si + 1] - offset;
  408.       RINOK(LookInStream_SeekTo(inStream, startPos + offset));
  409.  
  410.       if (coder->MethodID == k_Copy)
  411.       {
  412.         if (inSize != outSizeCur) /* check it */
  413.           return SZ_ERROR_DATA;
  414.         RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
  415.       }
  416.       else if (coder->MethodID == k_LZMA)
  417.       {
  418.         RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
  419.       }
  420.       #ifndef _7Z_NO_METHOD_LZMA2
  421.       else if (coder->MethodID == k_LZMA2)
  422.       {
  423.         RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
  424.       }
  425.       #endif
  426.       #ifdef _7ZIP_PPMD_SUPPPORT
  427.       else if (coder->MethodID == k_PPMD)
  428.       {
  429.         RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
  430.       }
  431.       #endif
  432.       else
  433.         return SZ_ERROR_UNSUPPORTED;
  434.     }
  435.     else if (coder->MethodID == k_BCJ2)
  436.     {
  437.       UInt64 offset = packPositions[1];
  438.       UInt64 s3Size = packPositions[2] - offset;
  439.      
  440.       if (ci != 3)
  441.         return SZ_ERROR_UNSUPPORTED;
  442.      
  443.       tempSizes[2] = (SizeT)s3Size;
  444.       if (tempSizes[2] != s3Size)
  445.         return SZ_ERROR_MEM;
  446.       tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
  447.       if (!tempBuf[2] && tempSizes[2] != 0)
  448.         return SZ_ERROR_MEM;
  449.      
  450.       RINOK(LookInStream_SeekTo(inStream, startPos + offset));
  451.       RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
  452.  
  453.       if ((tempSizes[0] & 3) != 0 ||
  454.           (tempSizes[1] & 3) != 0 ||
  455.           tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
  456.         return SZ_ERROR_DATA;
  457.  
  458.       {
  459.         CBcj2Dec p;
  460.        
  461.         p.bufs[0] = tempBuf3;   p.lims[0] = tempBuf3 + tempSize3;
  462.         p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
  463.         p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
  464.         p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
  465.        
  466.         p.dest = outBuffer;
  467.         p.destLim = outBuffer + outSize;
  468.        
  469.         Bcj2Dec_Init(&p);
  470.         RINOK(Bcj2Dec_Decode(&p));
  471.  
  472.         {
  473.           unsigned i;
  474.           for (i = 0; i < 4; i++)
  475.             if (p.bufs[i] != p.lims[i])
  476.               return SZ_ERROR_DATA;
  477.          
  478.           if (!Bcj2Dec_IsFinished(&p))
  479.             return SZ_ERROR_DATA;
  480.  
  481.           if (p.dest != p.destLim
  482.              || p.state != BCJ2_STREAM_MAIN)
  483.             return SZ_ERROR_DATA;
  484.         }
  485.       }
  486.     }
  487.     #ifndef _7Z_NO_METHODS_FILTERS
  488.     else if (ci == 1)
  489.     {
  490.       if (coder->MethodID == k_Delta)
  491.       {
  492.         if (coder->PropsSize != 1)
  493.           return SZ_ERROR_UNSUPPORTED;
  494.         {
  495.           Byte state[DELTA_STATE_SIZE];
  496.           Delta_Init(state);
  497.           Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
  498.         }
  499.       }
  500.       else
  501.       {
  502.         if (coder->PropsSize != 0)
  503.           return SZ_ERROR_UNSUPPORTED;
  504.         switch (coder->MethodID)
  505.         {
  506.           case k_BCJ:
  507.           {
  508.             UInt32 state;
  509.             x86_Convert_Init(state);
  510.             x86_Convert(outBuffer, outSize, 0, &state, 0);
  511.             break;
  512.           }
  513.           CASE_BRA_CONV(PPC)
  514.           CASE_BRA_CONV(IA64)
  515.           CASE_BRA_CONV(SPARC)
  516.           CASE_BRA_CONV(ARM)
  517.           CASE_BRA_CONV(ARMT)
  518.           default:
  519.             return SZ_ERROR_UNSUPPORTED;
  520.         }
  521.       }
  522.     }
  523.     #endif
  524.     else
  525.       return SZ_ERROR_UNSUPPORTED;
  526.   }
  527.  
  528.   return SZ_OK;
  529. }
  530.  
  531.  
  532. SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
  533.     ILookInStream *inStream, UInt64 startPos,
  534.     Byte *outBuffer, size_t outSize,
  535.     ISzAlloc *allocMain)
  536. {
  537.   SRes res;
  538.   CSzFolder folder;
  539.   CSzData sd;
  540.   CSzData sdSizes;
  541.  
  542.   const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
  543.   sd.Data = data;
  544.   sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
  545.  
  546.   sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex];
  547.   sdSizes.Size =
  548.       p->FoSizesOffsets[folderIndex + 1] -
  549.       p->FoSizesOffsets[folderIndex];
  550.  
  551.   res = SzGetNextFolderItem(&folder, &sd, &sdSizes);
  552.  
  553.   if (res != SZ_OK)
  554.     return res;
  555.  
  556.   if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.UnpackStream])
  557.     return SZ_ERROR_FAIL;
  558.   {
  559.     unsigned i;
  560.     Byte *tempBuf[3] = { 0, 0, 0};
  561.     res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
  562.         p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
  563.         inStream, startPos,
  564.         outBuffer, (SizeT)outSize, allocMain, tempBuf);
  565.     for (i = 0; i < 3; i++)
  566.       IAlloc_Free(allocMain, tempBuf[i]);
  567.     return res;
  568.   }
  569. }
  570.