Subject: Fix CVE-2018-10115
From: Robert Luberda <[email-masked]>
Date: Tue, 29 May 2018 23:59:09 +0200

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 a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
index 68030c7..8c890c8 100644
--- a/CPP/7zip/Compress/Rar1Decoder.cpp
+++ b/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 a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h
index 01b606b..8abb3a3 100644
--- a/CPP/7zip/Compress/Rar1Decoder.h
+++ b/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 a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
index 0580c8d..be8d842 100644
--- a/CPP/7zip/Compress/Rar2Decoder.cpp
+++ b/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 a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h
index 0e9005f..370bce2 100644
--- a/CPP/7zip/Compress/Rar2Decoder.h
+++ b/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 a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index 6cb8a6a..7b85833 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/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 a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h
index 2f72d7d..32c8943 100644
--- a/CPP/7zip/Compress/Rar3Decoder.h
+++ b/CPP/7zip/Compress/Rar3Decoder.h
@@ -191,7 +191,8 @@ class CDecoder:
   CRecordVector<CTempFilter *>  _tempFilters;
   UInt32 _lastFilter;
 
-  bool m_IsSolid;
+  bool _isSolid;
+  bool _solidAllowed;
   bool _errorMode;
 
   bool _lzMode;
diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp
index dc8830f..a826d5a 100644
--- a/CPP/7zip/Compress/Rar5Decoder.cpp
+++ b/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 a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h
index b0a4dd1..3db5018 100644
--- a/CPP/7zip/Compress/Rar5Decoder.h
+++ b/CPP/7zip/Compress/Rar5Decoder.h
@@ -271,6 +271,7 @@ class CDecoder:
   Byte _dictSizeLog;
   bool _tableWasFilled;
   bool _isSolid;
+  bool _solidAllowed;
   bool _wasInit;
 
   UInt32 _reps[kNumReps];