File freerdp-CVE-2024-32039-to-2024-32460.patch of Package freerdp.34872
From bb59568ec12f49a5b3a092696e8fd3819f8f6f3e Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:26:37 +0200
Subject: [PATCH 1/4] [codec,nsc] fix missing check
in nsc_rle_decode abort if there are more bytes to be read then there
are left.
---
libfreerdp/codec/nsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
index 645ca7512..d10fc6bca 100644
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -169,7 +169,7 @@ static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outS
len |= ((UINT32)(*in++)) << 24U;
}
- if (outSize < len)
+ if ((outSize < len) || (left < len))
return FALSE;
outSize -= len;
--
2.45.0
From 7ed269de0d8988d9e8520662c8dc147d6515d7da Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:35:05 +0200
Subject: [PATCH 2/4] [codec,clear] fix integer overflow
reorder check to prevent possible integer overflow
---
libfreerdp/codec/clear.c | 2 +-
libfreerdp/codec/zgfx.c | 14 +++++++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
index 101260770..b8899746e 100644
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -410,7 +410,7 @@ static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, wStream* s,
}
}
- if ((pixelIndex + runLengthFactor) > pixelCount)
+ if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex)))
{
WLog_ERR(TAG,
"pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32
diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
index 841b50860..b7b96ade0 100644
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -230,7 +230,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
BYTE* pbSegment;
size_t cbSegment;
- if (!zgfx || !stream || (segmentSize < 2))
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
+
+ if (segmentSize < 2)
return FALSE;
cbSegment = segmentSize - 1;
@@ -349,8 +352,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
-
- if (count > zgfx->cBitsRemaining / 8)
+ else if (count > zgfx->cBitsRemaining / 8)
+ return FALSE;
+ else if (zgfx->pbInputCurrent + count > zgfx->pbInputEnd)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
@@ -388,8 +392,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
- if (!stream)
- return -1;
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
if (Stream_GetRemainingLength(stream) < 1)
goto fail;
--
2.45.0
From 5767ea77016379ef975039a56c796322ed8e69f1 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:42:52 +0200
Subject: [PATCH 3/4] [codec,planar] fix missing input length checks
---
libfreerdp/codec/planar.c | 54 +++++++++++++++++++++++++++++++--------
1 file changed, 44 insertions(+), 10 deletions(-)
diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
index 0a5ec581c..76f70d6ba 100644
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -689,16 +689,28 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
rawHeights[3] = nSrcHeight;
}
+ const size_t diff = srcp - pSrcData;
+ if (SrcSize < diff)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+
if (!rle) /* RAW */
{
+
UINT32 base = planeSize * 3;
if (cs)
base = planeSize + planeSize / 2;
if (alpha)
{
- if ((SrcSize - (srcp - pSrcData)) < (planeSize + base))
+ if ((SrcSize - diff) < (planeSize + base))
+ {
+ WLog_ERR(TAG, "Alpha plane size mismatch %" PRIuz " < %" PRIu32, SrcSize - diff,
+ (planeSize + base));
return FALSE;
+ }
planes[3] = srcp; /* AlphaPlane */
planes[0] = planes[3] + rawSizes[3]; /* LumaOrRedPlane */
@@ -710,8 +722,11 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
}
else
{
- if ((SrcSize - (srcp - pSrcData)) < base)
+ if ((SrcSize - diff) < base)
+ {
+ WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32, SrcSize - diff, base);
return FALSE;
+ }
planes[0] = srcp; /* LumaOrRedPlane */
planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */
@@ -726,8 +741,8 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
planes[3] = srcp;
- rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData),
- rawWidths[3], rawHeights[3]); /* AlphaPlane */
+ rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - diff, rawWidths[3],
+ rawHeights[3]); /* AlphaPlane */
if (rleSizes[3] < 0)
return FALSE;
@@ -737,22 +752,41 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
else
planes[0] = srcp;
- rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
- rawWidths[0], rawHeights[0]); /* RedPlane */
+ const size_t diff0 = (planes[0] - pSrcData);
+ if (SrcSize < diff0)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff0);
+ return FALSE;
+ }
+ rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - diff0, rawWidths[0],
+ rawHeights[0]); /* RedPlane */
if (rleSizes[0] < 0)
return FALSE;
planes[1] = planes[0] + rleSizes[0];
- rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
- rawWidths[1], rawHeights[1]); /* GreenPlane */
+
+ const size_t diff1 = (planes[1] - pSrcData);
+ if (SrcSize < diff1)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff1);
+ return FALSE;
+ }
+ rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - diff1, rawWidths[1],
+ rawHeights[1]); /* GreenPlane */
if (rleSizes[1] < 1)
return FALSE;
planes[2] = planes[1] + rleSizes[1];
- rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
- rawWidths[2], rawHeights[2]); /* BluePlane */
+ const size_t diff2 = (planes[2] - pSrcData);
+ if (SrcSize < diff2)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+ rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - diff2, rawWidths[2],
+ rawHeights[2]); /* BluePlane */
if (rleSizes[2] < 1)
return FALSE;
--
2.45.0
From 93de1bdd1b4e19dd2a39b8074c7d65f42c0d7624 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:45:03 +0200
Subject: [PATCH 4/4] [codec,ncrush] fix missing input length check
---
libfreerdp/codec/ncrush.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c
index c1d622a9c..199f1ed7c 100644
--- a/libfreerdp/codec/ncrush.c
+++ b/libfreerdp/codec/ncrush.c
@@ -2041,6 +2041,12 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
return 1;
}
+ if (SrcSize < 4)
+ {
+ WLog_ERR(TAG, "Input size short: SrcSize %" PRIu32 " < 4", SrcSize);
+ return -1;
+ }
+
const BYTE* SrcEnd = &pSrcData[SrcSize];
const BYTE* SrcPtr = pSrcData + 4;
--
2.45.0