From: Robert Luberda Date: Tue, 29 May 2018 23:59:09 +0200 Subject: Fix CVE-2018-10115 Apply "patch" taken from https://landave.io/files/patch_7zip_CVE-2018-10115.txt Bugs-Debian: https://bugs.debian.org/897674 --- CPP/7zip/Compress/Rar1Decoder.cpp | 16 +++++++++++----- CPP/7zip/Compress/Rar1Decoder.h | 3 ++- CPP/7zip/Compress/Rar2Decoder.cpp | 17 +++++++++++++---- CPP/7zip/Compress/Rar2Decoder.h | 3 ++- CPP/7zip/Compress/Rar3Decoder.cpp | 19 +++++++++++++++---- CPP/7zip/Compress/Rar3Decoder.h | 3 ++- CPP/7zip/Compress/Rar5Decoder.cpp | 8 ++++++++ CPP/7zip/Compress/Rar5Decoder.h | 1 + 8 files changed, 54 insertions(+), 16 deletions(-) diff --git CPP/7zip/Compress/Rar1Decoder.cpp CPP/7zip/Compress/Rar1Decoder.cpp index 68030c7..8c890c8 100644 --- CPP/7zip/Compress/Rar1Decoder.cpp +++ CPP/7zip/Compress/Rar1Decoder.cpp @@ -29,7 +29,7 @@ public: }; */ -CDecoder::CDecoder(): m_IsSolid(false), _errorMode(false) { } +CDecoder::CDecoder(): _isSolid(false), _solidAllowed(false), _errorMode(false) { } void CDecoder::InitStructures() { @@ -345,7 +345,7 @@ void CDecoder::GetFlagsBuf() void CDecoder::InitData() { - if (!m_IsSolid) + if (!_isSolid) { AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0; AvrPlc = 0x3500; @@ -391,6 +391,11 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * if (inSize == NULL || outSize == NULL) 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)) @@ -398,13 +403,13 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * m_UnpackSize = (Int64)*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) + if (!_isSolid) { _errorMode = false; InitStructures(); @@ -475,6 +480,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } if (m_UnpackSize < 0) return S_FALSE; + _solidAllowed = true; return m_OutWindowStream.Flush(); } @@ -491,7 +497,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = ((data[0] & 1) != 0); + _isSolid = ((data[0] & 1) != 0); return S_OK; } diff --git CPP/7zip/Compress/Rar1Decoder.h CPP/7zip/Compress/Rar1Decoder.h index 01b606b..8abb3a3 100644 --- CPP/7zip/Compress/Rar1Decoder.h +++ CPP/7zip/Compress/Rar1Decoder.h @@ -38,7 +38,8 @@ public: UInt32 LastLength; Int64 m_UnpackSize; - bool m_IsSolid; + bool _isSolid; + bool _solidAllowed; bool _errorMode; UInt32 ReadBits(int numBits); diff --git CPP/7zip/Compress/Rar2Decoder.cpp CPP/7zip/Compress/Rar2Decoder.cpp index 0580c8d..be8d842 100644 --- CPP/7zip/Compress/Rar2Decoder.cpp +++ 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), m_TablesOK(false) { } @@ -320,6 +321,10 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * if (inSize == NULL || outSize == NULL) 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)) @@ -330,12 +335,12 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * 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) @@ -343,6 +348,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; if (!ReadTables()) return S_FALSE; + _solidAllowed = true; return S_OK; } if (!ReadTables()) @@ -386,6 +392,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * if (!ReadLastTables()) return S_FALSE; + + _solidAllowed = true; + return m_OutWindowStream.Flush(); } @@ -402,7 +411,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = ((data[0] & 1) != 0); + _isSolid = ((data[0] & 1) != 0); return S_OK; } diff --git CPP/7zip/Compress/Rar2Decoder.h CPP/7zip/Compress/Rar2Decoder.h index 0e9005f..370bce2 100644 --- CPP/7zip/Compress/Rar2Decoder.h +++ 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; bool m_TablesOK; void InitStructures(); diff --git CPP/7zip/Compress/Rar3Decoder.cpp CPP/7zip/Compress/Rar3Decoder.cpp index 6cb8a6a..7b85833 100644 --- CPP/7zip/Compress/Rar3Decoder.cpp +++ CPP/7zip/Compress/Rar3Decoder.cpp @@ -92,7 +92,8 @@ CDecoder::CDecoder(): _writtenFileSize(0), _vmData(0), _vmCode(0), - m_IsSolid(false), + _isSolid(false), + _solidAllowed(false), _errorMode(false) { Ppmd7_Construct(&_ppmd); @@ -821,7 +822,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) { _writtenFileSize = 0; _unsupportedFilter = false; - if (!m_IsSolid) + if (!_isSolid) { _lzSize = 0; _winPos = 0; @@ -840,12 +841,15 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) if (_errorMode) return S_FALSE; - if (!m_IsSolid || !TablesRead) + if (!_isSolid || !TablesRead) { bool keepDecompressing; RINOK(ReadTables(keepDecompressing)); if (!keepDecompressing) + { + _solidAllowed = true; return S_OK; + } } for (;;) @@ -870,6 +874,9 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) if (!keepDecompressing) break; } + + _solidAllowed = true; + RINOK(WriteBuf()); UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); @@ -890,6 +897,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (!inSize) return E_INVALIDARG; + if (_isSolid && !_solidAllowed) + return S_FALSE; + _solidAllowed = false; + if (!_vmData) { _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax); @@ -928,7 +939,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = ((data[0] & 1) != 0); + _isSolid = ((data[0] & 1) != 0); return S_OK; } diff --git CPP/7zip/Compress/Rar3Decoder.h CPP/7zip/Compress/Rar3Decoder.h index 2f72d7d..32c8943 100644 --- CPP/7zip/Compress/Rar3Decoder.h +++ CPP/7zip/Compress/Rar3Decoder.h @@ -191,7 +191,8 @@ class CDecoder: CRecordVector _tempFilters; UInt32 _lastFilter; - bool m_IsSolid; + bool _isSolid; + bool _solidAllowed; bool _errorMode; bool _lzMode; diff --git CPP/7zip/Compress/Rar5Decoder.cpp CPP/7zip/Compress/Rar5Decoder.cpp index dc8830f..a826d5a 100644 --- CPP/7zip/Compress/Rar5Decoder.cpp +++ CPP/7zip/Compress/Rar5Decoder.cpp @@ -72,6 +72,7 @@ CDecoder::CDecoder(): _writtenFileSize(0), _dictSizeLog(0), _isSolid(false), + _solidAllowed(false), _wasInit(false), _inputBuf(NULL) { @@ -801,7 +802,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 +825,10 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream { try { + if (_isSolid && !_solidAllowed) + return S_FALSE; + _solidAllowed = false; + if (_dictSizeLog >= sizeof(size_t) * 8) return E_NOTIMPL; diff --git CPP/7zip/Compress/Rar5Decoder.h CPP/7zip/Compress/Rar5Decoder.h index b0a4dd1..3db5018 100644 --- CPP/7zip/Compress/Rar5Decoder.h +++ CPP/7zip/Compress/Rar5Decoder.h @@ -271,6 +271,7 @@ class CDecoder: Byte _dictSizeLog; bool _tableWasFilled; bool _isSolid; + bool _solidAllowed; bool _wasInit; UInt32 _reps[kNumReps];