Patrick Williams | 8e7b46e | 2023-05-01 14:19:06 -0500 | [diff] [blame] | 1 | From: Robert Luberda <robert@debian.org> |
| 2 | Date: Sun, 28 Jan 2018 23:47:40 +0100 |
| 3 | Subject: CVE-2018-5996 |
| 4 | |
| 5 | Hopefully fix Memory Corruptions via RAR PPMd (CVE-2018-5996) by |
| 6 | applying a few changes from 7Zip 18.00-beta. |
| 7 | |
| 8 | Bug-Debian: https://bugs.debian.org/#888314 |
| 9 | |
| 10 | Upstream-Status: Backport [https://sources.debian.org/data/non-free/p/p7zip-rar/16.02-3/debian/patches/06-CVE-2018-5996.patch] |
| 11 | CVE: CVE-2018-5996 |
| 12 | |
| 13 | Signed-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 | |
| 23 | diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp |
| 24 | index 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) |
| 64 | diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h |
| 65 | index 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); |
| 76 | diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp |
| 77 | index 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 | { |
| 118 | diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h |
| 119 | index 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); |
| 130 | diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp |
| 131 | index 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 | } |
| 207 | diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h |
| 208 | index 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 | |