1From: Robert Luberda <robert@debian.org> 2Date: Sun, 28 Jan 2018 23:47:40 +0100 3Subject: CVE-2018-5996 4 5Hopefully fix Memory Corruptions via RAR PPMd (CVE-2018-5996) by 6applying a few changes from 7Zip 18.00-beta. 7 8Bug-Debian: https://bugs.debian.org/#888314 9 10Upstream-Status: Backport [https://sources.debian.org/data/non-free/p/p7zip-rar/16.02-3/debian/patches/06-CVE-2018-5996.patch] 11CVE: CVE-2018-5996 12 13Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com> 14--- 15 CPP/7zip/Compress/Rar1Decoder.cpp | 13 +++++++++---- 16 CPP/7zip/Compress/Rar1Decoder.h | 1 + 17 CPP/7zip/Compress/Rar2Decoder.cpp | 10 +++++++++- 18 CPP/7zip/Compress/Rar2Decoder.h | 1 + 19 CPP/7zip/Compress/Rar3Decoder.cpp | 23 ++++++++++++++++++++--- 20 CPP/7zip/Compress/Rar3Decoder.h | 2 ++ 21 6 files changed, 42 insertions(+), 8 deletions(-) 22 23diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp 24index 1aaedcc..68030c7 100644 25--- a/CPP/7zip/Compress/Rar1Decoder.cpp 26+++ b/CPP/7zip/Compress/Rar1Decoder.cpp 27@@ -29,7 +29,7 @@ public: 28 }; 29 */ 30 31-CDecoder::CDecoder(): m_IsSolid(false) { } 32+CDecoder::CDecoder(): m_IsSolid(false), _errorMode(false) { } 33 34 void CDecoder::InitStructures() 35 { 36@@ -406,9 +406,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * 37 InitData(); 38 if (!m_IsSolid) 39 { 40+ _errorMode = false; 41 InitStructures(); 42 InitHuff(); 43 } 44+ 45+ if (_errorMode) 46+ return S_FALSE; 47+ 48 if (m_UnpackSize > 0) 49 { 50 GetFlagsBuf(); 51@@ -477,9 +482,9 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream 52 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 53 { 54 try { return CodeReal(inStream, outStream, inSize, outSize, progress); } 55- catch(const CInBufferException &e) { return e.ErrorCode; } 56- catch(const CLzOutWindowException &e) { return e.ErrorCode; } 57- catch(...) { return S_FALSE; } 58+ catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; } 59+ catch(const CLzOutWindowException &e) { _errorMode = true; return e.ErrorCode; } 60+ catch(...) { _errorMode = true; return S_FALSE; } 61 } 62 63 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) 64diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h 65index 630f089..01b606b 100644 66--- a/CPP/7zip/Compress/Rar1Decoder.h 67+++ b/CPP/7zip/Compress/Rar1Decoder.h 68@@ -39,6 +39,7 @@ public: 69 70 Int64 m_UnpackSize; 71 bool m_IsSolid; 72+ bool _errorMode; 73 74 UInt32 ReadBits(int numBits); 75 HRESULT CopyBlock(UInt32 distance, UInt32 len); 76diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp 77index b3f2b4b..0580c8d 100644 78--- a/CPP/7zip/Compress/Rar2Decoder.cpp 79+++ b/CPP/7zip/Compress/Rar2Decoder.cpp 80@@ -80,7 +80,8 @@ static const UInt32 kHistorySize = 1 << 20; 81 static const UInt32 kWindowReservSize = (1 << 22) + 256; 82 83 CDecoder::CDecoder(): 84- m_IsSolid(false) 85+ m_IsSolid(false), 86+ m_TablesOK(false) 87 { 88 } 89 90@@ -100,6 +101,8 @@ UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numB 91 92 bool CDecoder::ReadTables(void) 93 { 94+ m_TablesOK = false; 95+ 96 Byte levelLevels[kLevelTableSize]; 97 Byte newLevels[kMaxTableSize]; 98 m_AudioMode = (ReadBits(1) == 1); 99@@ -170,6 +173,8 @@ bool CDecoder::ReadTables(void) 100 } 101 102 memcpy(m_LastLevels, newLevels, kMaxTableSize); 103+ m_TablesOK = true; 104+ 105 return true; 106 } 107 108@@ -344,6 +349,9 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * 109 return S_FALSE; 110 } 111 112+ if (!m_TablesOK) 113+ return S_FALSE; 114+ 115 UInt64 startPos = m_OutWindowStream.GetProcessedSize(); 116 while (pos < unPackSize) 117 { 118diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h 119index 3a0535c..0e9005f 100644 120--- a/CPP/7zip/Compress/Rar2Decoder.h 121+++ b/CPP/7zip/Compress/Rar2Decoder.h 122@@ -139,6 +139,7 @@ class CDecoder : 123 124 UInt64 m_PackSize; 125 bool m_IsSolid; 126+ bool m_TablesOK; 127 128 void InitStructures(); 129 UInt32 ReadBits(unsigned numBits); 130diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp 131index 3bf2513..6cb8a6a 100644 132--- a/CPP/7zip/Compress/Rar3Decoder.cpp 133+++ b/CPP/7zip/Compress/Rar3Decoder.cpp 134@@ -92,7 +92,8 @@ CDecoder::CDecoder(): 135 _writtenFileSize(0), 136 _vmData(0), 137 _vmCode(0), 138- m_IsSolid(false) 139+ m_IsSolid(false), 140+ _errorMode(false) 141 { 142 Ppmd7_Construct(&_ppmd); 143 } 144@@ -545,6 +546,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) 145 return InitPPM(); 146 } 147 148+ TablesRead = false; 149+ TablesOK = false; 150+ 151 _lzMode = true; 152 PrevAlignBits = 0; 153 PrevAlignCount = 0; 154@@ -606,6 +610,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) 155 } 156 } 157 } 158+ if (InputEofError()) 159+ return S_FALSE; 160+ 161 TablesRead = true; 162 163 // original code has check here: 164@@ -623,6 +630,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) 165 RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); 166 167 memcpy(m_LastLevels, newLevels, kTablesSizesSum); 168+ 169+ TablesOK = true; 170+ 171 return S_OK; 172 } 173 174@@ -824,7 +834,12 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) 175 PpmEscChar = 2; 176 PpmError = true; 177 InitFilters(); 178+ _errorMode = false; 179 } 180+ 181+ if (_errorMode) 182+ return S_FALSE; 183+ 184 if (!m_IsSolid || !TablesRead) 185 { 186 bool keepDecompressing; 187@@ -838,6 +853,8 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) 188 bool keepDecompressing; 189 if (_lzMode) 190 { 191+ if (!TablesOK) 192+ return S_FALSE; 193 RINOK(DecodeLZ(keepDecompressing)) 194 } 195 else 196@@ -901,8 +918,8 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream 197 _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1; 198 return CodeReal(progress); 199 } 200- catch(const CInBufferException &e) { return e.ErrorCode; } 201- catch(...) { return S_FALSE; } 202+ catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; } 203+ catch(...) { _errorMode = true; return S_FALSE; } 204 // CNewException is possible here. But probably CNewException is caused 205 // by error in data stream. 206 } 207diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h 208index c130cec..2f72d7d 100644 209--- a/CPP/7zip/Compress/Rar3Decoder.h 210+++ b/CPP/7zip/Compress/Rar3Decoder.h 211@@ -192,6 +192,7 @@ class CDecoder: 212 UInt32 _lastFilter; 213 214 bool m_IsSolid; 215+ bool _errorMode; 216 217 bool _lzMode; 218 bool _unsupportedFilter; 219@@ -200,6 +201,7 @@ class CDecoder: 220 UInt32 PrevAlignCount; 221 222 bool TablesRead; 223+ bool TablesOK; 224 225 CPpmd7 _ppmd; 226 int PpmEscChar; 227 228