On 2018/06/19 05:15, Josh Grosse wrote:
> A patch for CVE-2018-10115 was posted May 8, no comments received.
> 
>    https://marc.info/?l=openbsd-ports&m=152581494615299&w=2
> 
> A patch for CVE-2017-17969 has been added to the attached diff.

It's a bit tricky to review the code changes directly, can you send some
links/information for the CVE-2018-10115 ones like you have for the
CVE-2017-17969 one so we at least have a better idea of provenance?

Seems there is also CVE-2018-5996 which looks fairly nasty.


> Index: Makefile
> ===================================================================
> RCS file: /systems/cvs/ports/archivers/p7zip/Makefile,v
> retrieving revision 1.44
> diff -u -p -r1.44 Makefile
> --- Makefile  9 Apr 2018 15:58:26 -0000       1.44
> +++ Makefile  8 May 2018 19:57:34 -0000
> @@ -4,8 +4,8 @@ COMMENT-main= file archiver with high co
>  COMMENT-rar= rar modules for p7zip
>  
>  V=           16.02
> -REVISION-main=       4
> -REVISION-rar=        1
> +REVISION-main=       5
> +REVISION-rar=        2
>  DISTNAME=    p7zip_${V}_src_all
>  PKGNAME=     p7zip-${V}
>  PKGNAME-main=        p7zip-${V}
> Index: patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_cpp
> diff -N patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_cpp        8 May 2018 
> 19:45:54 -0000
> @@ -0,0 +1,49 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Archive/Rar/Rar5Handler.cpp
> +--- CPP/7zip/Archive/Rar/Rar5Handler.cpp.orig
> ++++ CPP/7zip/Archive/Rar/Rar5Handler.cpp
> +@@ -102,11 +102,11 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSi
> + {
> +   *val = 0;
> + 
> +-  for (unsigned i = 0; i < maxSize;)
> ++  for (unsigned i = 0; i < maxSize && i < 10;)
> +   {
> +     Byte b = p[i];
> +-    if (i < 10)
> +-      *val |= (UInt64)(b & 0x7F) << (7 * i++);
> ++    *val |= (UInt64)(b & 0x7F) << (7 * i);
> ++    i++;
> +     if ((b & 0x80) == 0)
> +       return i;
> +   }
> +@@ -1182,6 +1182,7 @@ static const Byte kProps[] =
> +   kpidSymLink,
> +   kpidHardLink,
> +   kpidCopyLink,
> ++  kpidVolumeIndex
> + };
> + 
> + 
> +@@ -1601,6 +1602,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPI
> + 
> +     case kpidSplitBefore: prop = item.IsSplitBefore(); break;
> +     case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
> ++
> ++    case kpidVolumeIndex:
> ++    {
> ++      if (item.VolIndex < _arcs.Size())
> ++      {
> ++        const CInArcInfo &arcInfo = _arcs[item.VolIndex].Info;
> ++        if (arcInfo.IsVolume())
> ++          prop = (UInt64)arcInfo.GetVolIndex();
> ++      }
> ++      break;
> ++    }
> ++
> +     case kpidCRC:
> +     {
> +       const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
> Index: patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_h
> diff -N patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Archive_Rar_Rar5Handler_h  8 May 2018 19:46:51 
> -0000
> @@ -0,0 +1,16 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Archive/Rar/Rar5Handler.h
> +--- CPP/7zip/Archive/Rar/Rar5Handler.h.orig
> ++++ CPP/7zip/Archive/Rar/Rar5Handler.h
> +@@ -168,7 +168,7 @@ struct CItem
> + 
> +   AString Name;
> + 
> +-  int VolIndex;
> ++  unsigned VolIndex;
> +   int NextItem;
> + 
> +   UInt32 UnixMTime;
> Index: patches/patch-CPP_7zip_Archive_Rar_RarHandler_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Archive_Rar_RarHandler_cpp
> diff -N patches/patch-CPP_7zip_Archive_Rar_RarHandler_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Archive_Rar_RarHandler_cpp 8 May 2018 19:46:59 
> -0000
> @@ -0,0 +1,30 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Archive/Rar/RarHandler.cpp
> +--- CPP/7zip/Archive/Rar/RarHandler.cpp.orig
> ++++ CPP/7zip/Archive/Rar/RarHandler.cpp
> +@@ -768,7 +768,8 @@ static const Byte kProps[] =
> +   kpidCRC,
> +   kpidHostOS,
> +   kpidMethod,
> +-  kpidUnpackVer
> ++  kpidUnpackVer,
> ++  kpidVolumeIndex
> + };
> + 
> + static const Byte kArcProps[] =
> +@@ -989,6 +990,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPI
> +     case kpidCommented: prop = item.IsCommented(); break;
> +     case kpidSplitBefore: prop = item.IsSplitBefore(); break;
> +     case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems 
> - 1].IsSplitAfter(); break;
> ++    
> ++    case kpidVolumeIndex:
> ++      if (_arcInfo.Is_VolNumber_Defined())
> ++        prop = (UInt32)(_arcInfo.VolNumber + refItem.VolumeIndex);
> ++      break;
> ++
> +     case kpidCRC:
> +     {
> +       prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
> Index: patches/patch-CPP_7zip_Archive_Rar_RarHandler_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Archive_Rar_RarHandler_h
> diff -N patches/patch-CPP_7zip_Archive_Rar_RarHandler_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Archive_Rar_RarHandler_h   8 May 2018 19:47:06 
> -0000
> @@ -0,0 +1,16 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Archive/Rar/RarHandler.h
> +--- CPP/7zip/Archive/Rar/RarHandler.h.orig
> ++++ CPP/7zip/Archive/Rar/RarHandler.h
> +@@ -26,7 +26,7 @@ struct CInArcInfo
> +   UInt32 DataCRC;
> +   bool EndOfArchive_was_Read;
> + 
> +-  CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
> ++  CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {}
> + 
> +   UInt64 GetPhySize() const { return EndPos - StartPos; }
> + 
> Index: patches/patch-CPP_7zip_Compress_Rar1Decoder_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar1Decoder_cpp
> diff -N patches/patch-CPP_7zip_Compress_Rar1Decoder_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar1Decoder_cpp   8 May 2018 19:47:23 
> -0000
> @@ -0,0 +1,666 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar1Decoder.cpp
> +--- CPP/7zip/Compress/Rar1Decoder.cpp.orig
> ++++ CPP/7zip/Compress/Rar1Decoder.cpp
> +@@ -1,7 +1,7 @@
> + // Rar1Decoder.cpp
> + // According to unRAR license, this code may not be used to develop
> + // a program that creates RAR archives
> +- 
> ++
> + #include "StdAfx.h"
> + 
> + #include "Rar1Decoder.h"
> +@@ -9,77 +9,83 @@
> + namespace NCompress {
> + namespace NRar1 {
> + 
> +-static const UInt32 PosL1[] = {0,0,0,2,3,5,7,11,16,20,24,32,32, 256};
> +-static const UInt32 PosL2[] = {0,0,0,0,5,7,9,13,18,22,26,34,36, 256};
> +-static const UInt32 PosHf0[] = {0,0,0,0,0,8,16,24,33,33,33,33,33, 257};
> +-static const UInt32 PosHf1[] = {0,0,0,0,0,0,4,44,60,76,80,80,127, 257};
> +-static const UInt32 PosHf2[] = {0,0,0,0,0,0,2,7,53,117,233, 257,0};
> +-static const UInt32 PosHf3[] = {0,0,0,0,0,0,0,2,16,218,251, 257,0};
> +-static const UInt32 PosHf4[] = {0,0,0,0,0,0,0,0,0,255, 257,0,0};
> ++static const unsigned kNumBits = 12;
> + 
> +-static const UInt32 kHistorySize = (1 << 16);
> ++static const Byte kShortLen1[16 * 3] =
> ++{
> ++  0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0,0,
> ++  1,3,4,4,5,6,7,8,8,4,4,5,6,6,0,0,
> ++  1,4,4,4,5,6,7,8,8,4,4,5,6,6,4,0
> ++};
> + 
> +-/*
> +-class CCoderReleaser
> ++static const Byte kShortLen2[16 * 3] =
> + {
> +-  CDecoder *m_Coder;
> +-public:
> +-  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
> +-  ~CCoderReleaser() { m_Coder->ReleaseStreams(); }
> ++  0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0,0,
> ++  2,3,3,3,4,4,5,6,6,4,4,5,6,6,0,0,
> ++  2,3,3,4,4,4,5,6,6,4,4,5,6,6,4,0
> + };
> +-*/
> + 
> +-CDecoder::CDecoder(): m_IsSolid(false) { }
> ++static const Byte PosL1[kNumBits + 1]  = { 0,0,2,1,2,2,4,5,4,4,8,0,224 };
> ++static const Byte PosL2[kNumBits + 1]  = { 0,0,0,5,2,2,4,5,4,4,8,2,220 };
> + 
> +-void CDecoder::InitStructures()
> +-{
> +-  for (int i = 0; i < kNumRepDists; i++)
> +-    m_RepDists[i] = 0;
> +-  m_RepDistPtr = 0;
> +-  LastLength = 0;
> +-  LastDist = 0;
> +-}
> ++static const Byte PosHf0[kNumBits + 1] = { 0,0,0,0,8,8,8,9,0,0,0,0,224 };
> ++static const Byte PosHf1[kNumBits + 1] = { 0,0,0,0,0,4,40,16,16,4,0,47,130 
> };
> ++static const Byte PosHf2[kNumBits + 1] = { 0,0,0,0,0,2,5,46,64,116,24,0,0 };
> ++static const Byte PosHf3[kNumBits + 1] = { 0,0,0,0,0,0,2,14,202,33,6,0,0 };
> ++static const Byte PosHf4[kNumBits + 1] = { 0,0,0,0,0,0,0,0,255,2,0,0,0 };
> + 
> +-UInt32 CDecoder::ReadBits(int numBits) { return 
> m_InBitStream.ReadBits(numBits); }
> ++static const UInt32 kHistorySize = (1 << 16);
> + 
> ++CDecoder::CDecoder():
> ++   _isSolid(false),
> ++   _solidAllowed(false)
> ++   { }
> ++
> ++UInt32 CDecoder::ReadBits(unsigned numBits) { return 
> m_InBitStream.ReadBits(numBits); }
> ++
> + HRESULT CDecoder::CopyBlock(UInt32 distance, UInt32 len)
> + {
> +   if (len == 0)
> +     return S_FALSE;
> ++  if (m_UnpackSize < len)
> ++    return S_FALSE;
> +   m_UnpackSize -= len;
> +   return m_OutWindowStream.CopyBlock(distance, len) ? S_OK : S_FALSE;
> + }
> + 
> +-
> +-UInt32 CDecoder::DecodeNum(const UInt32 *posTab)
> ++UInt32 CDecoder::DecodeNum(const Byte *numTab)
> + {
> +-  UInt32 startPos = 2;
> +-  UInt32 num = m_InBitStream.GetValue(12);
> ++  /*
> ++  {
> ++    // we can check that tables are correct
> ++    UInt32 sum = 0;
> ++    for (unsigned i = 0; i <= kNumBits; i++)
> ++      sum += ((UInt32)numTab[i] << (kNumBits - i));
> ++    if (sum != (1 << kNumBits))
> ++      throw 111;
> ++  }
> ++  */
> ++
> ++  UInt32 val = m_InBitStream.GetValue(kNumBits);
> ++  UInt32 sum = 0;
> ++  unsigned i = 2;
> ++
> +   for (;;)
> +   {
> +-    UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - 
> startPos);
> +-    if (num < cur)
> ++    UInt32 num = numTab[i];
> ++    UInt32 cur = num << (kNumBits - i);
> ++    if (val < cur)
> +       break;
> +-    startPos++;
> +-    num -= cur;
> ++    i++;
> ++    val -= cur;
> ++    sum += num;
> +   }
> +-  m_InBitStream.MovePos(startPos);
> +-  return((num >> (12 - startPos)) + posTab[startPos]);
> ++  m_InBitStream.MovePos(i);
> ++  return ((val >> (kNumBits - i)) + sum);
> + }
> + 
> +-static const Byte kShortLen1 [] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 };
> +-static const Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 };
> +-static const Byte kShortLen2 [] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 };
> +-static const Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 };
> +-static const UInt32 kShortXor1[] = 
> {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
> +-static const UInt32 kShortXor2[] = 
> {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
> +-
> + HRESULT CDecoder::ShortLZ()
> + {
> +-  UInt32 len, saveLen, dist;
> +-  int distancePlace;
> +-  const Byte *kShortLen;
> +-  const UInt32 *kShortXor;
> +   NumHuf = 0;
> + 
> +   if (LCount == 2)
> +@@ -91,20 +97,14 @@ HRESULT CDecoder::ShortLZ()
> + 
> +   UInt32 bitField = m_InBitStream.GetValue(8);
> + 
> +-  if (AvrLn1 < 37)
> ++  UInt32 len, dist;
> +   {
> +-    kShortLen = Buf60 ? kShortLen1a : kShortLen1;
> +-    kShortXor = kShortXor1;
> ++    const Byte *xors = (AvrLn1 < 37) ? kShortLen1 : kShortLen2;
> ++    const Byte *lens = xors + 16 + Buf60;
> ++    for (len = 0; ((bitField ^ xors[len]) >> (8 - lens[len])) != 0; len++);
> ++    m_InBitStream.MovePos(lens[len]);
> +   }
> +-  else
> +-  {
> +-    kShortLen = Buf60 ? kShortLen2a : kShortLen2;
> +-    kShortXor = kShortXor2;
> +-  }
> + 
> +-  for (len = 0; ((bitField ^ kShortXor[len]) & (~(0xff >> kShortLen[len]))) 
> != 0; len++);
> +-  m_InBitStream.MovePos(kShortLen[len]);
> +-
> +   if (len >= 9)
> +   {
> +     if (len == 9)
> +@@ -112,9 +112,11 @@ HRESULT CDecoder::ShortLZ()
> +       LCount++;
> +       return CopyBlock(LastDist, LastLength);
> +     }
> ++
> ++    LCount = 0;
> ++
> +     if (len == 14)
> +     {
> +-      LCount = 0;
> +       len = DecodeNum(PosL2) + 5;
> +       dist = 0x8000 + ReadBits(15) - 1;
> +       LastLength = len;
> +@@ -122,41 +124,46 @@ HRESULT CDecoder::ShortLZ()
> +       return CopyBlock(dist, len);
> +     }
> + 
> +-    LCount = 0;
> +-    saveLen = len;
> ++    UInt32 saveLen = len;
> +     dist = m_RepDists[(m_RepDistPtr - (len - 9)) & 3];
> +-    len = DecodeNum(PosL1) + 2;
> +-    if (len == 0x101 && saveLen == 10)
> ++
> ++    len = DecodeNum(PosL1);
> ++
> ++    if (len == 0xff && saveLen == 10)
> +     {
> +-      Buf60 ^= 1;
> ++      Buf60 ^= 16;
> +       return S_OK;
> +     }
> +     if (dist >= 256)
> ++    {
> +       len++;
> +-    if (dist >= MaxDist3 - 1)
> +-      len++;
> ++      if (dist >= MaxDist3 - 1)
> ++        len++;
> ++    }
> +   }
> +   else
> +   {
> +     LCount = 0;
> +     AvrLn1 += len;
> +     AvrLn1 -= AvrLn1 >> 4;
> +-    
> +-    distancePlace = DecodeNum(PosHf2) & 0xff;
> +-    dist = ChSetA[(unsigned)distancePlace];
> +-    if (--distancePlace != -1)
> ++
> ++    unsigned distancePlace = DecodeNum(PosHf2) & 0xff;
> ++
> ++    dist = ChSetA[distancePlace];
> ++
> ++    if (distancePlace != 0)
> +     {
> +       PlaceA[dist]--;
> +-      UInt32 lastDistance = ChSetA[(unsigned)distancePlace];
> ++      UInt32 lastDistance = ChSetA[(size_t)distancePlace - 1];
> +       PlaceA[lastDistance]++;
> +-      ChSetA[(unsigned)distancePlace + 1] = lastDistance;
> +-      ChSetA[(unsigned)distancePlace] = dist;
> ++      ChSetA[distancePlace] = lastDistance;
> ++      ChSetA[(size_t)distancePlace - 1] = dist;
> +     }
> +-    len += 2;
> +   }
> + 
> +   m_RepDists[m_RepDistPtr++] = dist;
> +   m_RepDistPtr &= 3;
> ++  len += 2;
> +   LastLength = len;
> +   LastDist = dist;
> +   return CopyBlock(dist, len);
> +@@ -177,12 +184,10 @@ HRESULT CDecoder::LongLZ()
> +     Nlzb = 0x90;
> +     Nhfb >>= 1;
> +   }
> +-  oldAvr2=AvrLn2;
> ++  oldAvr2 = AvrLn2;
> + 
> +-  if (AvrLn2 >= 122)
> +-    len = DecodeNum(PosL2);
> +-  else if (AvrLn2 >= 64)
> +-    len = DecodeNum(PosL1);
> ++  if (AvrLn2 >= 64)
> ++    len = DecodeNum(AvrLn2 < 122 ? PosL1 : PosL2);
> +   else
> +   {
> +     UInt32 bitField = m_InBitStream.GetValue(16);
> +@@ -193,8 +198,8 @@ HRESULT CDecoder::LongLZ()
> +     }
> +     else
> +     {
> +-      for (len = 0; ((bitField << len) & 0x8000) == 0; len++)
> +-        ;
> ++      for (len = 0; ((bitField << len) & 0x8000) == 0; len++);
> ++
> +       m_InBitStream.MovePos(len + 1);
> +     }
> +   }
> +@@ -202,24 +207,25 @@ HRESULT CDecoder::LongLZ()
> +   AvrLn2 += len;
> +   AvrLn2 -= AvrLn2 >> 5;
> + 
> +-  if (AvrPlcB > 0x28ff)
> +-    distancePlace = DecodeNum(PosHf2);
> +-  else if (AvrPlcB > 0x6ff)
> +-    distancePlace = DecodeNum(PosHf1);
> +-  else
> +-    distancePlace = DecodeNum(PosHf0);
> +-
> ++  {
> ++    const Byte *tab;
> ++         if (AvrPlcB >= 0x2900) tab = PosHf2;
> ++    else if (AvrPlcB >= 0x0700) tab = PosHf1;
> ++    else                        tab = PosHf0;
> ++    distancePlace = DecodeNum(tab); // [0, 256]
> ++  }
> +   AvrPlcB += distancePlace;
> +   AvrPlcB -= AvrPlcB >> 8;
> +-  
> ++
> ++  distancePlace &= 0xff;
> ++
> +   for (;;)
> +   {
> +-    dist = ChSetB[distancePlace & 0xff];
> ++    dist = ChSetB[distancePlace];
> +     newDistancePlace = NToPlB[dist++ & 0xff]++;
> +-    if (!(dist & 0xff))
> +-      CorrHuff(ChSetB,NToPlB);
> +-    else
> ++    if (dist & 0xff)
> +       break;
> ++    CorrHuff(ChSetB,NToPlB);
> +   }
> + 
> +   ChSetB[distancePlace] = ChSetB[newDistancePlace];
> +@@ -228,34 +234,33 @@ HRESULT CDecoder::LongLZ()
> +   dist = ((dist & 0xff00) >> 1) | ReadBits(7);
> + 
> +   oldAvr3 = AvrLn3;
> +-  
> ++
> +   if (len != 1 && len != 4)
> +     if (len == 0 && dist <= MaxDist3)
> +     {
> +       AvrLn3++;
> +       AvrLn3 -= AvrLn3 >> 8;
> +     }
> +-    else
> +-      if (AvrLn3 > 0)
> ++    else if (AvrLn3 > 0)
> +         AvrLn3--;
> +-  
> ++
> +   len += 3;
> +-  
> ++
> +   if (dist >= MaxDist3)
> +     len++;
> +   if (dist <= 256)
> +     len += 8;
> +-  
> ++
> +   if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40)
> +     MaxDist3 = 0x7f00;
> +   else
> +     MaxDist3 = 0x2001;
> +-  
> ++
> +   m_RepDists[m_RepDistPtr++] = --dist;
> +   m_RepDistPtr &= 3;
> +   LastLength = len;
> +   LastDist = dist;
> +-  
> ++
> +   return CopyBlock(dist, len);
> + }
> + 
> +@@ -265,57 +270,62 @@ HRESULT CDecoder::HuffDecode()
> +   UInt32 curByte, newBytePlace;
> +   UInt32 len;
> +   UInt32 dist;
> +-  int bytePlace;
> ++  unsigned bytePlace;
> ++  {
> ++    const Byte *tab;
> + 
> +-  if      (AvrPlc > 0x75ff)  bytePlace = DecodeNum(PosHf4);
> +-  else if (AvrPlc > 0x5dff)  bytePlace = DecodeNum(PosHf3);
> +-  else if (AvrPlc > 0x35ff)  bytePlace = DecodeNum(PosHf2);
> +-  else if (AvrPlc > 0x0dff)  bytePlace = DecodeNum(PosHf1);
> +-  else                       bytePlace = DecodeNum(PosHf0);
> +-  
> ++    if      (AvrPlc >= 0x7600)  tab = PosHf4;
> ++    else if (AvrPlc >= 0x5e00)  tab = PosHf3;
> ++    else if (AvrPlc >= 0x3600)  tab = PosHf2;
> ++    else if (AvrPlc >= 0x0e00)  tab = PosHf1;
> ++    else                        tab = PosHf0;
> ++
> ++    bytePlace = DecodeNum(tab); // [0, 256]
> ++  }                   bytePlace = DecodeNum(PosHf0);
> ++
> +   if (StMode)
> +   {
> +-    if (--bytePlace == -1)
> ++    if (bytePlace == 0)
> +     {
> +       if (ReadBits(1))
> +       {
> +-        NumHuf = StMode = 0;
> ++        NumHuf = 0;
> ++        StMode = false;
> +         return S_OK;
> +       }
> +-      else
> +-      {
> +-        len = (ReadBits(1)) ? 4 : 3;
> +-        dist = DecodeNum(PosHf2);
> +-        dist = (dist << 5) | ReadBits(5);
> +-        return CopyBlock(dist - 1, len);
> +-      }
> ++      len = ReadBits(1) + 3;
> ++      dist = DecodeNum(PosHf2);
> ++      dist = (dist << 5) | ReadBits(5);
> ++      if (dist == 0)
> ++        return S_FALSE;
> ++      return CopyBlock(dist - 1, len);
> +     }
> ++    bytePlace--; // bytePlace is [0, 255]
> +   }
> +   else if (NumHuf++ >= 16 && FlagsCnt == 0)
> +-    StMode = 1;
> +-  
> ++    StMode = true;
> ++
> +   bytePlace &= 0xff;
> +   AvrPlc += bytePlace;
> +   AvrPlc -= AvrPlc >> 8;
> +-  Nhfb+=16;
> +-  
> ++  Nhfb += 16;
> ++
> +   if (Nhfb > 0xff)
> +   {
> +-    Nhfb=0x90;
> ++    Nhfb = 0x90;
> +     Nlzb >>= 1;
> +   }
> + 
> +-  m_UnpackSize --;
> ++  m_UnpackSize--;
> +   m_OutWindowStream.PutByte((Byte)(ChSet[bytePlace] >> 8));
> + 
> +   for (;;)
> +   {
> +     curByte = ChSet[bytePlace];
> +     newBytePlace = NToPl[curByte++ & 0xff]++;
> +-    if ((curByte & 0xff) > 0xa1)
> +-      CorrHuff(ChSet, NToPl);
> +-    else
> ++    if ((curByte & 0xff) <= 0xa1)
> +       break;
> ++    CorrHuff(ChSet, NToPl);
> +   }
> + 
> +   ChSet[bytePlace] = ChSet[newBytePlace];
> +@@ -327,8 +337,11 @@ HRESULT CDecoder::HuffDecode()
> + void CDecoder::GetFlagsBuf()
> + {
> +   UInt32 flags, newFlagsPlace;
> +-  UInt32 flagsPlace = DecodeNum(PosHf2);
> ++  UInt32 flagsPlace = DecodeNum(PosHf2); // [0, 256]
> + 
> ++  if (flagsPlace >= ARRAY_SIZE(ChSetC))
> ++    return;
> ++
> +   for (;;)
> +   {
> +     flags = ChSetC[flagsPlace];
> +@@ -343,21 +356,6 @@ void CDecoder::GetFlagsBuf()
> +   ChSetC[newFlagsPlace] = flags;
> + }
> + 
> +-void CDecoder::InitData()
> +-{
> +-  if (!m_IsSolid)
> +-  {
> +-    AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;
> +-    AvrPlc = 0x3500;
> +-    MaxDist3 = 0x2001;
> +-    Nhfb = Nlzb = 0x80;
> +-  }
> +-  FlagsCnt = 0;
> +-  FlagBuf = 0;
> +-  StMode = 0;
> +-  LCount = 0;
> +-}
> +-
> + void CDecoder::CorrHuff(UInt32 *CharSet,UInt32 *NumToPlace)
> + {
> +   int i;
> +@@ -369,81 +367,79 @@ void CDecoder::CorrHuff(UInt32 *CharSet,UInt32 *NumToP
> +     NumToPlace[i] = (7 - i) * 32;
> + }
> + 
> +-void CDecoder::InitHuff()
> +-{
> +-  for (UInt32 i = 0; i < 256; i++)
> +-  {
> +-    Place[i] = PlaceA[i] = PlaceB[i] = i;
> +-    PlaceC[i] = (~i + 1) & 0xff;
> +-    ChSet[i] = ChSetB[i] = i << 8;
> +-    ChSetA[i] = i;
> +-    ChSetC[i] = ((~i + 1) & 0xff) << 8;
> +-  }
> +-  memset(NToPl, 0, sizeof(NToPl));
> +-  memset(NToPlB, 0, sizeof(NToPlB));
> +-  memset(NToPlC, 0, sizeof(NToPlC));
> +-  CorrHuff(ChSetB, NToPlB);
> +-}
> +-
> + HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, 
> ISequentialOutStream *outStream,
> +     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo * /* 
> progress */)
> + {
> +-  if (inSize == NULL || outSize == NULL)
> ++  if (!inSize || !outSize)
> +     return E_INVALIDARG;
> + 
> ++  if (_isSolid && !_solidAllowed)
> ++    return S_FALSE;
> ++
> ++  _solidAllowed = false;
> ++
> +   if (!m_OutWindowStream.Create(kHistorySize))
> +     return E_OUTOFMEMORY;
> +   if (!m_InBitStream.Create(1 << 20))
> +     return E_OUTOFMEMORY;
> + 
> +-  m_UnpackSize = (Int64)*outSize;
> ++  m_UnpackSize = *outSize;
> ++
> +   m_OutWindowStream.SetStream(outStream);
> +-  m_OutWindowStream.Init(m_IsSolid);
> ++  m_OutWindowStream.Init(_isSolid);
> +   m_InBitStream.SetStream(inStream);
> +   m_InBitStream.Init();
> + 
> +-  // CCoderReleaser coderReleaser(this);
> +-  InitData();
> +-  if (!m_IsSolid)
> ++  // InitData
> ++
> ++  FlagsCnt = 0;
> ++  FlagBuf = 0;
> ++  StMode = false;
> ++  LCount = 0;
> ++
> ++  if (!_isSolid)
> +   {
> +-    InitStructures();
> +-    InitHuff();
> ++    AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;
> ++    AvrPlc = 0x3500;
> ++    MaxDist3 = 0x2001;
> ++    Nhfb = Nlzb = 0x80;
> ++
> ++    {
> ++      // InitStructures
> ++      for (int i = 0; i < kNumRepDists; i++)
> ++        m_RepDists[i] = 0;
> ++      m_RepDistPtr = 0;
> ++      LastLength = 0;
> ++      LastDist = 0;
> ++    }
> ++
> ++    // InitHuff
> ++
> ++    for (UInt32 i = 0; i < 256; i++)
> ++    {
> ++      Place[i] = PlaceA[i] = PlaceB[i] = i;
> ++      UInt32 c = (~i + 1) & 0xff;
> ++      PlaceC[i] = c;
> ++      ChSet[i] = ChSetB[i] = i << 8;
> ++      ChSetA[i] = i;
> ++      ChSetC[i] = c << 8;
> ++    }
> ++    memset(NToPl, 0, sizeof(NToPl));
> ++    memset(NToPlB, 0, sizeof(NToPlB));
> ++    memset(NToPlC, 0, sizeof(NToPlC));
> ++    CorrHuff(ChSetB, NToPlB);
> +   }
> ++
> +   if (m_UnpackSize > 0)
> +   {
> +     GetFlagsBuf();
> +     FlagsCnt = 8;
> +   }
> + 
> +-  while (m_UnpackSize > 0)
> ++  while (m_UnpackSize != 0)
> +   {
> +-    if (StMode)
> ++    if (!StMode)
> +     {
> +-      RINOK(HuffDecode());
> +-      continue;
> +-    }
> +-
> +-    if (--FlagsCnt < 0)
> +-    {
> +-      GetFlagsBuf();
> +-      FlagsCnt=7;
> +-    }
> +-
> +-    if (FlagBuf & 0x80)
> +-    {
> +-      FlagBuf <<= 1;
> +-      if (Nlzb > Nhfb)
> +-      {
> +-        RINOK(LongLZ());
> +-      }
> +-      else
> +-      {
> +-        RINOK(HuffDecode());
> +-      }
> +-    }
> +-    else
> +-    {
> +-      FlagBuf <<= 1;
> +       if (--FlagsCnt < 0)
> +       {
> +         GetFlagsBuf();
> +@@ -454,22 +450,41 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStre
> +         FlagBuf <<= 1;
> +         if (Nlzb > Nhfb)
> +         {
> +-          RINOK(HuffDecode());
> +-        }
> +-        else
> +-        {
> +           RINOK(LongLZ());
> ++      continue;
> +         }
> +       }
> +       else
> +       {
> +         FlagBuf <<= 1;
> +-        RINOK(ShortLZ());
> ++
> ++        if (--FlagsCnt < 0)
> ++        {
> ++          GetFlagsBuf();
> ++          FlagsCnt = 7;
> ++        }
> ++
> ++        if ((FlagBuf & 0x80) == 0)
> ++        {
> ++          FlagBuf <<= 1;
> ++          RINOK(ShortLZ());
> ++          continue;
> ++        }
> ++
> ++        FlagBuf <<= 1;
> ++
> ++        if (Nlzb <= Nhfb)
> ++        {
> ++          RINOK(LongLZ());
> ++          continue;
> ++        }
> +       }
> +     }
> ++
> ++    RINOK(HuffDecode());
> +   }
> +-  if (m_UnpackSize < 0)
> +-    return S_FALSE;
> ++
> ++  _solidAllowed = true;
> +   return m_OutWindowStream.Flush();
> + }
> + 
> +@@ -486,7 +501,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byt
> + {
> +   if (size < 1)
> +     return E_INVALIDARG;
> +-  m_IsSolid = ((data[0] & 1) != 0);
> ++  _isSolid = ((data[0] & 1) != 0);
> +   return S_OK;
> + }
> + 
> Index: patches/patch-CPP_7zip_Compress_Rar1Decoder_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar1Decoder_h
> diff -N patches/patch-CPP_7zip_Compress_Rar1Decoder_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar1Decoder_h     8 May 2018 19:47:28 
> -0000
> @@ -0,0 +1,90 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar1Decoder.h
> +--- CPP/7zip/Compress/Rar1Decoder.h.orig
> ++++ CPP/7zip/Compress/Rar1Decoder.h
> +@@ -20,48 +20,45 @@ namespace NRar1 {
> + 
> + const UInt32 kNumRepDists = 4;
> + 
> +-typedef NBitm::CDecoder<CInBuffer> CBitDecoder;
> +-
> + class CDecoder :
> +   public ICompressCoder,
> +   public ICompressSetDecoderProperties2,
> +   public CMyUnknownImp
> + {
> +-public:
> +   CLzOutWindow m_OutWindowStream;
> +-  CBitDecoder m_InBitStream;
> ++  NBitm::CDecoder<CInBuffer> m_InBitStream;
> + 
> +-  UInt32 m_RepDists[kNumRepDists];
> +-  UInt32 m_RepDistPtr;
> ++  UInt64 m_UnpackSize;
> + 
> +   UInt32 LastDist;
> +   UInt32 LastLength;
> + 
> +-  Int64 m_UnpackSize;
> +-  bool m_IsSolid;
> ++  UInt32 m_RepDistPtr;
> ++  UInt32 m_RepDists[kNumRepDists];
> + 
> +-  UInt32 ReadBits(int numBits);
> +-  HRESULT CopyBlock(UInt32 distance, UInt32 len);
> ++  bool _isSolid;
> ++  bool _solidAllowed;
> + 
> +-  UInt32 DecodeNum(const UInt32 *posTab);
> ++  bool StMode;
> ++  int FlagsCnt;
> ++  UInt32 FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
> ++  unsigned Buf60, NumHuf, LCount;
> ++  UInt32 Nhfb, Nlzb, MaxDist3;
> ++
> ++  UInt32 ChSet[256], ChSetA[256], ChSetB[256], ChSetC[256];
> ++  UInt32 Place[256], PlaceA[256], PlaceB[256], PlaceC[256];
> ++  UInt32 NToPl[256], NToPlB[256], NToPlC[256];
> ++
> ++  UInt32 ReadBits(unsigned numBits);
> ++  HRESULT CopyBlock(UInt32 distance, UInt32 len);
> ++  UInt32 DecodeNum(const Byte *numTab);
> +   HRESULT ShortLZ();
> +   HRESULT LongLZ();
> +   HRESULT HuffDecode();
> +   void GetFlagsBuf();
> +-  void InitData();
> +-  void InitHuff();
> +   void CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace);
> +   void OldUnpWriteBuf();
> +   
> +-  UInt32 ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
> +-  UInt32 Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
> +-  UInt32 NToPl[256],NToPlB[256],NToPlC[256];
> +-  UInt32 FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
> +-  int Buf60,NumHuf,StMode,LCount,FlagsCnt;
> +-  UInt32 Nhfb,Nlzb,MaxDist3;
> +-
> +-  void InitStructures();
> +-
> +   HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream 
> *outStream,
> +       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo 
> *progress);
> + 
> +@@ -69,14 +66,6 @@ class CDecoder : (public)
> +   CDecoder();
> + 
> +   MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
> +-
> +-  /*
> +-  void ReleaseStreams()
> +-  {
> +-    m_OutWindowStream.ReleaseStream();
> +-    m_InBitStream.ReleaseStream();
> +-  }
> +-  */
> + 
> +   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream 
> *outStream,
> +       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo 
> *progress);
> Index: patches/patch-CPP_7zip_Compress_Rar2Decoder_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar2Decoder_cpp
> diff -N patches/patch-CPP_7zip_Compress_Rar2Decoder_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar2Decoder_cpp   8 May 2018 19:47:32 
> -0000
> @@ -0,0 +1,94 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar2Decoder.cpp
> +--- CPP/7zip/Compress/Rar2Decoder.cpp.orig
> ++++ CPP/7zip/Compress/Rar2Decoder.cpp
> +@@ -80,7 +80,8 @@ static const UInt32 kHistorySize = 1 << 20;
> + static const UInt32 kWindowReservSize = (1 << 22) + 256;
> + 
> + CDecoder::CDecoder():
> +-  m_IsSolid(false)
> ++  _isSolid(false),
> ++  _solidAllowed(false)
> + {
> + }
> + 
> +@@ -199,19 +200,6 @@ bool CDecoder::ReadLastTables()
> +   return true;
> + }
> + 
> +-/*
> +-class CCoderReleaser
> +-{
> +-  CDecoder *m_Coder;
> +-public:
> +-  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
> +-  ~CCoderReleaser()
> +-  {
> +-    m_Coder->ReleaseStreams();
> +-  }
> +-};
> +-*/
> +-
> + bool CDecoder::DecodeMm(UInt32 pos)
> + {
> +   while (pos-- > 0)
> +@@ -312,8 +300,12 @@ bool CDecoder::DecodeLz(Int32 pos)
> + HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, 
> ISequentialOutStream *outStream,
> +     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo 
> *progress)
> + {
> +-  if (inSize == NULL || outSize == NULL)
> +-    return E_INVALIDARG;
> ++  if (!inSize || !outSize)
> ++     return E_INVALIDARG;
> ++ 
> ++  if (_isSolid && !_solidAllowed)
> ++    return S_FALSE;
> ++  _solidAllowed = false;
> + 
> +   if (!m_OutWindowStream.Create(kHistorySize))
> +     return E_OUTOFMEMORY;
> +@@ -325,12 +317,12 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStre
> +   UInt64 pos = 0, unPackSize = *outSize;
> +   
> +   m_OutWindowStream.SetStream(outStream);
> +-  m_OutWindowStream.Init(m_IsSolid);
> ++  m_OutWindowStream.Init(_isSolid);
> +   m_InBitStream.SetStream(inStream);
> +   m_InBitStream.Init();
> + 
> +   // CCoderReleaser coderReleaser(this);
> +-  if (!m_IsSolid)
> ++  if (!_isSolid)
> +   {
> +     InitStructures();
> +     if (unPackSize == 0)
> +@@ -338,6 +330,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStre
> +       if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: 
> probably incorrect;
> +         if (!ReadTables())
> +           return S_FALSE;
> ++      _solidAllowed = true;
> +       return S_OK;
> +     }
> +     if (!ReadTables())
> +@@ -378,6 +371,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStre
> + 
> +   if (!ReadLastTables())
> +     return S_FALSE;
> ++
> ++  _solidAllowed = true;
> ++
> +   return m_OutWindowStream.Flush();
> + }
> + 
> +@@ -394,7 +390,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byt
> + {
> +   if (size < 1)
> +     return E_INVALIDARG;
> +-  m_IsSolid = ((data[0] & 1) != 0);
> ++  _isSolid = ((data[0] & 1) != 0);
> +   return S_OK;
> + }
> + 
> Index: patches/patch-CPP_7zip_Compress_Rar2Decoder_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar2Decoder_h
> diff -N patches/patch-CPP_7zip_Compress_Rar2Decoder_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar2Decoder_h     8 May 2018 19:47:47 
> -0000
> @@ -0,0 +1,32 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar2Decoder.h
> +--- CPP/7zip/Compress/Rar2Decoder.h.orig
> ++++ CPP/7zip/Compress/Rar2Decoder.h
> +@@ -138,7 +138,8 @@ class CDecoder :
> +   Byte m_LastLevels[kMaxTableSize];
> + 
> +   UInt64 m_PackSize;
> +-  bool m_IsSolid;
> ++  bool _isSolid;
> ++  bool _solidAllowed;
> + 
> +   void InitStructures();
> +   UInt32 ReadBits(unsigned numBits);
> +@@ -155,14 +156,6 @@ class CDecoder :
> +   CDecoder();
> + 
> +   MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
> +-
> +-  /*
> +-  void ReleaseStreams()
> +-  {
> +-    m_OutWindowStream.ReleaseStream();
> +-    m_InBitStream.ReleaseStream();
> +-  }
> +-  */
> + 
> +   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream 
> *outStream,
> +       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo 
> *progress);
> Index: patches/patch-CPP_7zip_Compress_Rar3Decoder_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar3Decoder_cpp
> diff -N patches/patch-CPP_7zip_Compress_Rar3Decoder_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar3Decoder_cpp   8 May 2018 19:47:52 
> -0000
> @@ -0,0 +1,85 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar3Decoder.cpp
> +--- CPP/7zip/Compress/Rar3Decoder.cpp.orig
> ++++ CPP/7zip/Compress/Rar3Decoder.cpp
> +@@ -92,7 +92,8 @@ CDecoder::CDecoder():
> +   _writtenFileSize(0),
> +   _vmData(0),
> +   _vmCode(0),
> +-  m_IsSolid(false)
> ++  _isSolid(false),
> ++  _solidAllowed(false)
> + {
> +   Ppmd7_Construct(&_ppmd);
> + }
> +@@ -811,7 +812,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *prog
> + {
> +   _writtenFileSize = 0;
> +   _unsupportedFilter = false;
> +-  if (!m_IsSolid)
> ++  if (!_isSolid)
> +   {
> +     _lzSize = 0;
> +     _winPos = 0;
> +@@ -825,12 +826,15 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *prog
> +     PpmError = true;
> +     InitFilters();
> +   }
> +-  if (!m_IsSolid || !TablesRead)
> ++  if (!_isSolid || !TablesRead)
> +   {
> +     bool keepDecompressing;
> +     RINOK(ReadTables(keepDecompressing));
> +     if (!keepDecompressing)
> +-      return S_OK;
> ++    {
> ++      _solidAllowed = true;
> ++       return S_OK;
> ++    }
> +   }
> + 
> +   for (;;)
> +@@ -853,6 +857,9 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *prog
> +     if (!keepDecompressing)
> +       break;
> +   }
> ++
> ++  _solidAllowed = true;
> ++
> +   RINOK(WriteBuf());
> +   UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
> +   RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
> +@@ -873,6 +880,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStr
> +     if (!inSize)
> +       return E_INVALIDARG;
> + 
> ++    if (_isSolid && !_solidAllowed)
> ++      return S_FALSE;
> ++    _solidAllowed = false;
> ++
> +     if (!_vmData)
> +     {
> +       _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
> +@@ -901,8 +912,8 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStr
> +     _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
> +     return CodeReal(progress);
> +   }
> +-  catch(const CInBufferException &e)  { return e.ErrorCode; }
> +-  catch(...) { return S_FALSE; }
> ++  catch(const CInBufferException &e)  { /* _errorMode = true; */ return 
> e.ErrorCode; }
> ++  catch(...) { /* _errorMode = true; */ return S_FALSE; }
> +   // CNewException is possible here. But probably CNewException is caused
> +   // by error in data stream.
> + }
> +@@ -911,7 +922,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byt
> + {
> +   if (size < 1)
> +     return E_INVALIDARG;
> +-  m_IsSolid = ((data[0] & 1) != 0);
> ++  _isSolid = ((data[0] & 1) != 0);
> +   return S_OK;
> + }
> + 
> Index: patches/patch-CPP_7zip_Compress_Rar3Decoder_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar3Decoder_h
> diff -N patches/patch-CPP_7zip_Compress_Rar3Decoder_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar3Decoder_h     8 May 2018 19:47:56 
> -0000
> @@ -0,0 +1,18 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar3Decoder.h
> +--- CPP/7zip/Compress/Rar3Decoder.h.orig
> ++++ CPP/7zip/Compress/Rar3Decoder.h
> +@@ -191,7 +191,9 @@ class CDecoder:
> +   CRecordVector<CTempFilter *>  _tempFilters;
> +   UInt32 _lastFilter;
> + 
> +-  bool m_IsSolid;
> ++  bool _isSolid;
> ++  bool _solidAllowed;
> ++  // bool _errorMode;
> + 
> +   bool _lzMode;
> +   bool _unsupportedFilter;
> Index: patches/patch-CPP_7zip_Compress_Rar5Decoder_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar5Decoder_cpp
> diff -N patches/patch-CPP_7zip_Compress_Rar5Decoder_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar5Decoder_cpp   8 May 2018 19:48:03 
> -0000
> @@ -0,0 +1,149 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar5Decoder.cpp
> +--- CPP/7zip/Compress/Rar5Decoder.cpp.orig
> ++++ CPP/7zip/Compress/Rar5Decoder.cpp
> +@@ -72,6 +72,7 @@ CDecoder::CDecoder():
> +     _writtenFileSize(0),
> +     _dictSizeLog(0),
> +     _isSolid(false),
> ++    _solidAllowed(false),
> +     _wasInit(false),
> +     _inputBuf(NULL)
> + {
> +@@ -328,59 +329,63 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
> + {
> +   if (_progress)
> +   {
> +-    UInt64 packSize = _bitStream.GetProcessedSize();
> ++    const UInt64 packSize = _bitStream.GetProcessedSize();
> +     RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize));
> +   }
> + 
> +   _bitStream.AlignToByte();
> +   _bitStream.Prepare();
> +   
> +-  unsigned flags = _bitStream.ReadByteInAligned();
> +-  unsigned checkSum = _bitStream.ReadByteInAligned();
> +-  checkSum ^= flags;
> +-
> +-  UInt32 blockSize;
> +   {
> ++    unsigned flags = _bitStream.ReadByteInAligned();
> ++    unsigned checkSum = _bitStream.ReadByteInAligned();
> ++    checkSum ^= flags;
> +     unsigned num = (flags >> 3) & 3;
> +     if (num == 3)
> +       return S_FALSE;
> +-    blockSize = _bitStream.ReadByteInAligned();
> +-    if (num > 0)
> ++    UInt32 blockSize = _bitStream.ReadByteInAligned();
> ++    checkSum ^= blockSize;
> ++
> ++    if (num != 0)
> +     {
> +-      blockSize += (UInt32)_bitStream.ReadByteInAligned() << 8;
> ++      unsigned b = _bitStream.ReadByteInAligned();
> ++      checkSum ^= b;
> ++      blockSize += (UInt32)b << 8;
> +       if (num > 1)
> +-        blockSize += (UInt32)_bitStream.ReadByteInAligned() << 16;
> ++      {
> ++        b = _bitStream.ReadByteInAligned();
> ++        checkSum ^= b;
> ++        blockSize += (UInt32)b << 16;
> ++      }
> +     }
> +-  }
> +-
> +-  checkSum ^= blockSize ^ (blockSize >> 8) ^ (blockSize >> 16);
> +-  if ((Byte)checkSum != 0x5A)
> +-    return S_FALSE;
> +-
> +-  unsigned blockSizeBits7 = (flags & 7) + 1;
> +-
> +-  if (blockSize == 0 && blockSizeBits7 != 8)
> +-    return S_FALSE;
> +-
> +-  blockSize += (blockSizeBits7 >> 3);
> +-  blockSize--;
> +-
> +-  _bitStream._blockEndBits7 = (Byte)(blockSizeBits7 & 7);
> +-  _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
> +-
> +-  _bitStream.SetCheck2();
> +-
> +-  _isLastBlock = ((flags & 0x40) != 0);
> +-
> +-  if ((flags & 0x80) == 0)
> +-  {
> +-    if (!_tableWasFilled && blockSize != 0)
> ++    
> ++    if (checkSum != 0x5A)
> +       return S_FALSE;
> +-    return S_OK;
> ++    unsigned blockSizeBits7 = (flags & 7) + 1;
> ++    blockSize += (blockSizeBits7 >> 3);
> ++    if (blockSize == 0)
> ++      return S_FALSE;
> ++    blockSize--;
> ++    blockSizeBits7 &= 7;
> ++
> ++    _bitStream._blockEndBits7 = (Byte)blockSizeBits7;
> ++    _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
> ++    
> ++    _bitStream.SetCheck2();
> ++    
> ++    _isLastBlock = ((flags & 0x40) != 0);
> ++    
> ++    if ((flags & 0x80) == 0)
> ++    {
> ++      if (!_tableWasFilled)
> ++        if (blockSize != 0 || blockSizeBits7 != 0)
> ++          return S_FALSE;
> ++      return S_OK;
> ++    }
> ++    
> ++    _tableWasFilled = false;
> +   }
> + 
> +-  _tableWasFilled = false;
> +-
> +   {
> +     Byte lens2[kLevelTableSize];
> +     
> +@@ -600,6 +605,10 @@ HRESULT CDecoder::DecodeLZ()
> +           }
> +         }
> +       }
> ++
> ++      // that check is not required, but it can help, if there is BUG in 
> another code
> ++      if (!_tableWasFilled)
> ++        break; // return S_FALSE;
> +     }
> + 
> +     UInt32 sym = m_MainDecoder.Decode(&_bitStream);
> +@@ -801,7 +810,10 @@ HRESULT CDecoder::CodeReal()
> +   */
> + 
> +   if (res == S_OK)
> ++  {
> ++    _solidAllowed = true;
> +     res = res2;
> ++  }
> +      
> +   if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)
> +     return S_FALSE;
> +@@ -821,6 +833,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStr
> + {
> +   try
> +   {
> ++    if (_isSolid && !_solidAllowed)
> ++      return S_FALSE;
> ++    _solidAllowed = false;
> ++
> +     if (_dictSizeLog >= sizeof(size_t) * 8)
> +       return E_NOTIMPL;
> + 
> Index: patches/patch-CPP_7zip_Compress_Rar5Decoder_h
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_Rar5Decoder_h
> diff -N patches/patch-CPP_7zip_Compress_Rar5Decoder_h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_Rar5Decoder_h     8 May 2018 19:48:09 
> -0000
> @@ -0,0 +1,49 @@
> +$OpenBSD$
> +
> +Fix for CVE-2018-10115, from Denisov Denis.
> +
> +Index: CPP/7zip/Compress/Rar5Decoder.h
> +--- CPP/7zip/Compress/Rar5Decoder.h.orig
> ++++ CPP/7zip/Compress/Rar5Decoder.h
> +@@ -157,7 +157,7 @@ class CBitDecoder (public)
> +     return *_buf++;
> +   }
> + 
> +-  UInt32 GetValue(unsigned numBits)
> ++  UInt32 GetValue(unsigned numBits) const
> +   {
> +     UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | 
> (UInt32)_buf[2];
> +     v >>= (24 - numBits - _bitPos);
> +@@ -249,11 +249,19 @@ class CDecoder:
> +   bool _lzError;
> +   bool _writeError;
> +   
> ++  bool _isSolid;
> ++  bool _solidAllowed;
> ++  bool _tableWasFilled;
> ++  bool _wasInit;
> ++
> ++  Byte _dictSizeLog;
> ++
> +   // CBitDecoder _bitStream;
> +   Byte *_window;
> +   size_t _winPos;
> +   size_t _winSize;
> +   size_t _winMask;
> ++  size_t _winSizeAllocated;
> + 
> +   UInt64 _lzSize;
> + 
> +@@ -266,12 +274,6 @@ class CDecoder:
> +   // UInt64 _packSize;
> +   UInt64 _lzEnd;
> +   UInt64 _writtenFileSize;
> +-  size_t _winSizeAllocated;
> +-
> +-  Byte _dictSizeLog;
> +-  bool _tableWasFilled;
> +-  bool _isSolid;
> +-  bool _wasInit;
> + 
> +   UInt32 _reps[kNumReps];
> +   UInt32 _lastLen;
> Index: patches/patch-CPP_7zip_Compress_ShrinkDecoder_cpp
> ===================================================================
> RCS file: patches/patch-CPP_7zip_Compress_ShrinkDecoder_cpp
> diff -N patches/patch-CPP_7zip_Compress_ShrinkDecoder_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-CPP_7zip_Compress_ShrinkDecoder_cpp 19 Jun 2018 09:06:08 
> -0000
> @@ -0,0 +1,22 @@
> +$OpenBSD$
> +
> +For CVE-2017-17969, from https://sourceforge.net/p/p7zip/bugs/204/
> +
> +Index: CPP/7zip/Compress/ShrinkDecoder.cpp
> +--- CPP/7zip/Compress/ShrinkDecoder.cpp.orig
> ++++ CPP/7zip/Compress/ShrinkDecoder.cpp
> +@@ -121,8 +121,13 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStre
> +     {
> +       _stack[i++] = _suffixes[cur];
> +       cur = _parents[cur];
> ++      if (cur >= kNumItems || i >= kNumItems)
> ++        break;
> +     }
> +-    
> ++
> ++    if (cur >= kNumItems || i >= kNumItems)
> ++      break;
> ++
> +     _stack[i++] = (Byte)cur;
> +     lastChar2 = (Byte)cur;
> + 

Reply via email to