This patch addresses CVE-2018-10115, an arbitrary code execution bug.
Regression tested on amd64 and i386 on current, 6.3, and 6.2. Diffs for all three are attached.
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: Makefile =================================================================== RCS file: /systems/cvs/ports/archivers/p7zip/Makefile,v retrieving revision 1.43 diff -u -p -r1.43 Makefile --- Makefile 25 Nov 2017 13:27:48 -0000 1.43 +++ Makefile 8 May 2018 20:10:35 -0000 @@ -4,8 +4,8 @@ COMMENT-main= file archiver with high co COMMENT-rar= rar modules for p7zip V= 16.02 -REVISION-main= 3 -REVISION-rar= 1 +REVISION-main= 4 +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 20:13:44 -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 20:13:47 -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 20:13:50 -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 20:13:53 -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 20:13:56 -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 20:14:00 -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 20:14:06 -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 20:14:10 -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 20:14:13 -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 20:14:17 -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 20:14:19 -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 20:14:22 -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: Makefile =================================================================== RCS file: /systems/cvs/ports/archivers/p7zip/Makefile,v retrieving revision 1.42 diff -u -p -r1.42 Makefile --- Makefile 26 Jul 2017 22:45:14 -0000 1.42 +++ Makefile 8 May 2018 20:51:40 -0000 @@ -4,8 +4,8 @@ COMMENT-main= file archiver with high co COMMENT-rar= rar modules for p7zip V= 16.02 -REVISION-main= 3 -REVISION-rar= 1 +REVISION-main= 4 +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 20:54:21 -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 20:54:24 -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 20:54:27 -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 20:54:31 -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 20:54:35 -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 20:54:37 -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 20:54:40 -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 20:54:43 -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 20:54:46 -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 20:54:50 -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 20:54:53 -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 20:54:56 -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;