blob: 47868c982e05d3f1dd63c79fc2f8def096f7674f [file] [log] [blame]
Patrick Williams8e7b46e2023-05-01 14:19:06 -05001From: 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