Backport CVE-2023-40589.
replaced WINPR_ASSERT with plain assert, as this macro is defined only in later versions and if verbose asserting is disabled it will actually do assert() itself.
This commit is contained in:
parent
6ae95183f4
commit
500b4499a7
2
debian/changelog
vendored
2
debian/changelog
vendored
@ -14,7 +14,7 @@ freerdp2 (2.3.0+dfsg1-2~deb10u3) UNRELEASED; urgency=medium
|
||||
CVE-2020-13397 CVE-2020-13398 and
|
||||
CVE-2020-15103 (Closes: #965979)
|
||||
* Backporting remaining issues: (Closes: #1051638)
|
||||
CVE-2023-39350 CVE-2023-39354 CVE-2023-39355
|
||||
CVE-2023-39350 CVE-2023-39354 CVE-2023-39355 CVE-2023-40589
|
||||
|
||||
-- Tobias Frost <tobi@debian.org> Mon, 02 Oct 2023 17:10:48 +0200
|
||||
|
||||
|
||||
324
debian/patches/0040-CVE-2023-40589.patch
vendored
Normal file
324
debian/patches/0040-CVE-2023-40589.patch
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
Description: Upstream fix for CVE-2023-40589 - Global-Buffer-Overflow in ncrush_decompress
|
||||
Origin: https://github.com/FreeRDP/FreeRDP/commit/16141a30f983dd6f7a6e5b0356084171942c9416
|
||||
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-gc34-mw6m-g42x
|
||||
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
|
||||
--- a/libfreerdp/codec/ncrush.c
|
||||
+++ b/libfreerdp/codec/ncrush.c
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/ncrush.h>
|
||||
|
||||
+#include <assert.h>
|
||||
+
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
struct _NCRUSH_CONTEXT
|
||||
@@ -1994,15 +1996,9 @@
|
||||
UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
UINT32 index;
|
||||
- UINT32 bits;
|
||||
- INT32 nbits;
|
||||
- const BYTE* SrcPtr;
|
||||
- const BYTE* SrcEnd;
|
||||
- UINT16 Mask;
|
||||
BYTE Literal;
|
||||
UINT32 IndexLEC;
|
||||
UINT32 BitLength;
|
||||
- UINT32 MaskedBits;
|
||||
UINT32 CopyOffset;
|
||||
UINT32 CopyLength;
|
||||
UINT32 OldCopyOffset;
|
||||
@@ -2010,9 +2006,6 @@
|
||||
UINT32 LengthOfMatch;
|
||||
UINT32 CopyOffsetIndex;
|
||||
UINT32 OffsetCacheIndex;
|
||||
- BYTE* HistoryPtr;
|
||||
- BYTE* HistoryBuffer;
|
||||
- BYTE* HistoryBufferEnd;
|
||||
UINT32 CopyOffsetBits;
|
||||
UINT32 CopyOffsetBase;
|
||||
UINT32 LengthOfMatchBits;
|
||||
@@ -2021,8 +2014,8 @@
|
||||
if (ncrush->HistoryEndOffset != 65535)
|
||||
return -1001;
|
||||
|
||||
- HistoryBuffer = ncrush->HistoryBuffer;
|
||||
- HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
|
||||
+ BYTE* HistoryBuffer = ncrush->HistoryBuffer;
|
||||
+ const BYTE* HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
|
||||
|
||||
if (flags & PACKET_AT_FRONT)
|
||||
{
|
||||
@@ -2041,7 +2034,7 @@
|
||||
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
|
||||
}
|
||||
|
||||
- HistoryPtr = ncrush->HistoryPtr;
|
||||
+ BYTE* HistoryPtr = ncrush->HistoryPtr;
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
@@ -2050,17 +2043,19 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
- SrcEnd = &pSrcData[SrcSize];
|
||||
- nbits = 32;
|
||||
- bits = get_dword(pSrcData);
|
||||
- SrcPtr = pSrcData + 4;
|
||||
+ const BYTE* SrcEnd = &pSrcData[SrcSize];
|
||||
+ const BYTE* SrcPtr = pSrcData + 4;
|
||||
|
||||
+ INT32 nbits = 32;
|
||||
+ UINT32 bits = get_dword(pSrcData);
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
- Mask = get_word(&HuffTableMask[29]);
|
||||
- MaskedBits = bits & Mask;
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[29]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
+ if (MaskedBits >= ARRAYSIZE(HuffTableLEC))
|
||||
+ return -1;
|
||||
IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLEC[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
@@ -2096,8 +2091,10 @@
|
||||
return -1004;
|
||||
|
||||
CopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
|
||||
- Mask = get_word(&HuffTableMask[21]);
|
||||
- MaskedBits = bits & Mask;
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[21]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
+ if (MaskedBits > ARRAYSIZE(HuffTableLOM))
|
||||
+ return -1;
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
@@ -2106,13 +2103,23 @@
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
+ if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
|
||||
+ return -1;
|
||||
+
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
+
|
||||
+ if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
|
||||
+ return -1;
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
- Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
- MaskedBits = bits & Mask;
|
||||
+ const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
|
||||
+ if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
+ return -1;
|
||||
+
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
@@ -2127,15 +2134,28 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
+ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
|
||||
+ return -1;
|
||||
+
|
||||
CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
|
||||
+
|
||||
+ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBaseLUT))
|
||||
+ return -1;
|
||||
CopyOffsetBase = CopyOffsetBaseLUT[CopyOffsetIndex];
|
||||
CopyOffset = CopyOffsetBase - 1;
|
||||
|
||||
if (CopyOffsetBits)
|
||||
{
|
||||
- Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]);
|
||||
- MaskedBits = bits & Mask;
|
||||
- CopyOffset = CopyOffsetBase + MaskedBits - 1;
|
||||
+ const size_t idx = (2ull * CopyOffsetBits) + 3ull;
|
||||
+ if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
+ return -1;
|
||||
+
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
+ const UINT32 tmp = CopyOffsetBase + MaskedBits;
|
||||
+ if (tmp < 1)
|
||||
+ return -1;
|
||||
+ CopyOffset = tmp - 1;
|
||||
bits >>= CopyOffsetBits;
|
||||
nbits -= CopyOffsetBits;
|
||||
|
||||
@@ -2143,8 +2163,11 @@
|
||||
return -1;
|
||||
}
|
||||
|
||||
- Mask = get_word(&HuffTableMask[21]);
|
||||
- MaskedBits = bits & Mask;
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[21]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
+ if (MaskedBits >= ARRAYSIZE(HuffTableLOM))
|
||||
+ return -1;
|
||||
+
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
@@ -2153,13 +2176,23 @@
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
+ if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
|
||||
+ return -1;
|
||||
+
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
+
|
||||
+ if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
|
||||
+ return -1;
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
- Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
- MaskedBits = bits & Mask;
|
||||
+ const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
|
||||
+ if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
+ return -1;
|
||||
+
|
||||
+ const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
+ const UINT32 MaskedBits = bits & Mask;
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
@@ -2583,7 +2616,12 @@
|
||||
}
|
||||
|
||||
IndexLEC = Literal;
|
||||
+ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
+ return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
+
|
||||
+ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
+ return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
@@ -2666,9 +2704,18 @@
|
||||
bits = CopyOffset;
|
||||
|
||||
CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2];
|
||||
+
|
||||
+ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
|
||||
+ return -1;
|
||||
+
|
||||
CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
|
||||
IndexLEC = 257 + CopyOffsetIndex;
|
||||
+ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
+ return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
+
|
||||
+ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
+ return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
@@ -2687,13 +2734,23 @@
|
||||
else
|
||||
IndexCO = ncrush->HuffTableLOM[MatchLength];
|
||||
|
||||
+ if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
|
||||
+ return -1;
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
+
|
||||
+ if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
|
||||
+ return -1;
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
+
|
||||
+ if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
|
||||
+ return -1;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
+ if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
|
||||
+ return -1;
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1010;
|
||||
}
|
||||
@@ -2701,7 +2758,11 @@
|
||||
{
|
||||
/* CopyOffset in OffsetCache */
|
||||
IndexLEC = 289 + OffsetCacheIndex;
|
||||
+ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
+ return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
+ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
+ return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength >= 15)
|
||||
@@ -2714,13 +2775,24 @@
|
||||
else
|
||||
IndexCO = ncrush->HuffTableLOM[MatchLength];
|
||||
|
||||
+ if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
|
||||
+ return -1;
|
||||
+
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
+
|
||||
+ if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
|
||||
+ return -1;
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
+
|
||||
+ if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
|
||||
+ return -1;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
+ if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
|
||||
+ return -1;
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1012;
|
||||
}
|
||||
@@ -2745,6 +2817,10 @@
|
||||
Literal = *SrcPtr++;
|
||||
HistoryPtr++;
|
||||
IndexLEC = Literal;
|
||||
+ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
+ return -1;
|
||||
+ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
+ return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
@@ -2801,6 +2877,9 @@
|
||||
int j, l;
|
||||
k = 0;
|
||||
|
||||
+ assert(context);
|
||||
+ assert(28 < ARRAYSIZE(LOMBitsLUT));
|
||||
+
|
||||
for (i = 0; i < 28; i++)
|
||||
{
|
||||
for (j = 0; j < 1 << LOMBitsLUT[i]; j++)
|
||||
@@ -2817,6 +2896,11 @@
|
||||
else
|
||||
i = context->HuffTableLOM[k];
|
||||
|
||||
+ if (i >= ARRAYSIZE(LOMBitsLUT))
|
||||
+ return -1;
|
||||
+ if (i >= ARRAYSIZE(LOMBaseLUT))
|
||||
+ return -1;
|
||||
+
|
||||
if (((((1 << LOMBitsLUT[i]) - 1) & (k - 2)) + LOMBaseLUT[i]) != k)
|
||||
return -1;
|
||||
}
|
||||
1
debian/patches/series
vendored
1
debian/patches/series
vendored
@ -26,3 +26,4 @@
|
||||
0036-CVE-2023-39350.patch
|
||||
0037-CVE-2023-39354.patch
|
||||
0038-CVE-2023-39355.patch
|
||||
0040-CVE-2023-40589.patch
|
||||
|
||||
Loading…
Reference in New Issue
Block a user