Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP6:Update
freerdp
freerdp-CVE-2024-32658.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File freerdp-CVE-2024-32658.patch of Package freerdp
From cc7e7ab09e67a5940a456b1e6e5e2b64b9116335 Mon Sep 17 00:00:00 2001 From: akallabeth <akallabeth@posteo.net> Date: Fri, 2 Jul 2021 07:42:43 +0200 Subject: [PATCH 1/7] Added bounds checks to ExtractRunLength --- libfreerdp/codec/include/bitmap.c | 12 ++++++------ libfreerdp/codec/interleaved.c | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index 355c697e0..18e94ee8d 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -131,7 +131,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Background Run Orders. */ if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN) { - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; @@ -190,7 +190,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY case MEGA_MEGA_FG_RUN: case LITE_SET_FG_FG_RUN: case MEGA_MEGA_SET_FG_RUN: - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; @@ -222,7 +222,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Dithered Run Orders. */ case LITE_DITHERED_RUN: case MEGA_MEGA_DITHERED_RUN: - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; @@ -245,7 +245,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Color Run Orders. */ case REGULAR_COLOR_RUN: case MEGA_MEGA_COLOR_RUN: - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; @@ -264,7 +264,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY case MEGA_MEGA_FGBG_IMAGE: case LITE_SET_FG_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; @@ -330,7 +330,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Color Image Orders. */ case REGULAR_COLOR_IMAGE: case MEGA_MEGA_COLOR_IMAGE: - runLength = ExtractRunLength(code, pbSrc, &advance); + runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance); if (advance == 0) return FALSE; pbSrc = pbSrc + advance; diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 223cb71fc..d565523bb 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -129,7 +129,8 @@ static INLINE UINT32 ExtractCodeId(BYTE bOrderHdr) /** * Extract the run length of a compression order. */ -static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT32* advance) +static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const BYTE* pbEnd, + UINT32* advance) { UINT32 runLength; UINT32 ladvance; @@ -138,6 +139,8 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 WINPR_ASSERT(pbOrderHdr); WINPR_ASSERT(advance); + if (pbOrderHdr >= pbEnd) + return 0; switch (code) { @@ -146,6 +149,8 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 if (runLength == 0) { + if (pbOrderHdr + 1 >= pbEnd) + return 0; runLength = (*(pbOrderHdr + 1)) + 1; ladvance += 1; } @@ -161,6 +166,9 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 if (runLength == 0) { + if (pbOrderHdr + 1 >= pbEnd) + return 0; + runLength = (*(pbOrderHdr + 1)) + 1; ladvance += 1; } @@ -180,6 +188,9 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 if (runLength == 0) { /* An extended (MEGA) run. */ + if (pbOrderHdr + 1 >= pbEnd) + return 0; + runLength = (*(pbOrderHdr + 1)) + 32; ladvance += 1; } @@ -193,6 +204,9 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 if (runLength == 0) { /* An extended (MEGA) run. */ + if (pbOrderHdr + 1 >= pbEnd) + return 0; + runLength = (*(pbOrderHdr + 1)) + 16; ladvance += 1; } @@ -207,6 +221,9 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, UINT3 case MEGA_MEGA_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: case MEGA_MEGA_COLOR_IMAGE: + if (pbOrderHdr + 2 >= pbEnd) + return 0; + runLength = ((UINT16)pbOrderHdr[1]) | ((UINT16)(pbOrderHdr[2] << 8)); ladvance += 2; break; -- 2.45.0 From 021bd7eadbab8fc61e7434da0e9fd23782f226f5 Mon Sep 17 00:00:00 2001 From: Armin Novak <armin.novak@thincast.com> Date: Mon, 12 Dec 2022 13:28:36 +0100 Subject: [PATCH 2/7] [codec,interleaved] add proper debug logging log reason for decoder to fail --- libfreerdp/codec/include/bitmap.c | 27 ++++++++--- libfreerdp/codec/interleaved.c | 75 ++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index 18e94ee8d..c41c5cb0a 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -31,7 +31,10 @@ static INLINE BYTE* WRITEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd, UINT32 r BYTE mask = 0x01; if (cBits > 8) + { + WLog_ERR(TAG, "[%s] cBits %d > 8", __FUNCTION__, cBits); return NULL; + } if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits)) return NULL; @@ -61,7 +64,10 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, const BYTE* pbDestEnd, BYTE mask = 0x01; if (cBits > 8) + { + WLog_ERR(TAG, "[%s] cBits %d > 8", __FUNCTION__, cBits); return NULL; + } if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits)) return NULL; @@ -102,10 +108,18 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY RLEEXTRA if ((rowDelta == 0) || (rowDelta < width)) + { + WLog_ERR(TAG, "[%s] Invalid arguments: rowDelta=%" PRIu32 " == 0 || < width=%" PRIu32, + __FUNCTION__, rowDelta, width); return FALSE; + } if (!pbSrcBuffer || !pbDestBuffer) + { + WLog_ERR(TAG, "[%s] Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p", __FUNCTION__, + pbSrcBuffer, pbDestBuffer); return FALSE; + } pbEnd = pbSrcBuffer + cbSrcBuffer; pbDestEnd = pbDestBuffer + rowDelta * height; @@ -197,7 +211,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN) { - if (pbSrc + sizeof(fgPel) >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; SRCREADPIXEL(fgPel, pbSrc); } @@ -226,10 +240,10 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (advance == 0) return FALSE; pbSrc = pbSrc + advance; - if (pbSrc + sizeof(pixelA) >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; SRCREADPIXEL(pixelA, pbSrc); - if (pbSrc + sizeof(pixelB) >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; SRCREADPIXEL(pixelB, pbSrc); @@ -249,7 +263,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (advance == 0) return FALSE; pbSrc = pbSrc + advance; - if (pbSrc + sizeof(pixelA) >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; SRCREADPIXEL(pixelA, pbSrc); @@ -269,7 +283,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY return FALSE; pbSrc = pbSrc + advance; - if (pbSrc + sizeof(fgPel) >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE) { @@ -338,7 +352,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY return FALSE; UNROLL(runLength, { - if (pbSrc >= pbEnd) + if (!buffer_within_range(pbSrc, pbEnd)) return FALSE; SRCREADPIXEL(temp, pbSrc); DESTWRITEPIXEL(pbDest, temp); @@ -406,6 +420,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY break; default: + WLog_ERR(TAG, "[%s] invalid code 0x%08" PRIx32, __FUNCTION__, code); return FALSE; } } diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index d565523bb..88484a2e9 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -99,6 +99,20 @@ static const BYTE g_MaskSpecialFgBg2 = 0x05; static const BYTE g_MaskRegularRunLength = 0x1F; static const BYTE g_MaskLiteRunLength = 0x0F; +#define buffer_within_range(pbSrc, pbEnd) \ + buffer_within_range_((pbSrc), (pbEnd), __FUNCTION__, __FILE__, __LINE__) +static INLINE BOOL buffer_within_range_(const void* pbSrc, const void* pbEnd, const char* fkt, + const char* file, size_t line) +{ + WINPR_UNUSED(file); + if (pbSrc >= pbEnd) + { + WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p >= pbEnd=%p", fkt, line, pbSrc, pbEnd); + return FALSE; + } + return TRUE; +} + /** * Reads the supplied order header and extracts the compression * order code ID. @@ -138,8 +152,10 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const runLength = 0; WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (pbOrderHdr >= pbEnd) + + if (!buffer_within_range(pbOrderHdr, pbEnd)) return 0; switch (code) @@ -149,7 +165,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const if (runLength == 0) { - if (pbOrderHdr + 1 >= pbEnd) + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) return 0; runLength = (*(pbOrderHdr + 1)) + 1; ladvance += 1; @@ -166,7 +182,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const if (runLength == 0) { - if (pbOrderHdr + 1 >= pbEnd) + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) return 0; runLength = (*(pbOrderHdr + 1)) + 1; @@ -188,7 +204,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const if (runLength == 0) { /* An extended (MEGA) run. */ - if (pbOrderHdr + 1 >= pbEnd) + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) return 0; runLength = (*(pbOrderHdr + 1)) + 32; @@ -204,7 +220,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const if (runLength == 0) { /* An extended (MEGA) run. */ - if (pbOrderHdr + 1 >= pbEnd) + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) return 0; runLength = (*(pbOrderHdr + 1)) + 16; @@ -221,7 +237,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const case MEGA_MEGA_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: case MEGA_MEGA_COLOR_IMAGE: - if (pbOrderHdr + 2 >= pbEnd) + if (!buffer_within_range(pbOrderHdr + 2, pbEnd)) return 0; runLength = ((UINT16)pbOrderHdr[1]) | ((UINT16)(pbOrderHdr[2] << 8)); @@ -233,20 +249,32 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const return runLength; } -static INLINE BOOL ensure_capacity(const BYTE* start, const BYTE* end, size_t size, size_t base) +#define ensure_capacity(start, end, size, base) \ + ensure_capacity_((start), (end), (size), (base), __FUNCTION__, __FILE__, __LINE__) +static INLINE BOOL ensure_capacity_(const BYTE* start, const BYTE* end, size_t size, size_t base, + const char* fkt, const char* file, size_t line) { const size_t available = (uintptr_t)end - (uintptr_t)start; const BOOL rc = available >= size * base; - return rc && (start <= end); + const BOOL res = rc && (start <= end); + + if (!res) + WLog_ERR(TAG, + "[%s:%" PRIuz "] failed: start=%p <= end=%p, available=%" PRIuz " >= size=%" PRIuz + " * base=%" PRIuz, + fkt, line, start, end, available, size, base); + return res; } static INLINE void write_pixel_8(BYTE* _buf, BYTE _pix) { + WINPR_ASSERT(_buf); *_buf = _pix; } static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix) { + WINPR_ASSERT(_buf); (_buf)[0] = (BYTE)(_pix); (_buf)[1] = (BYTE)((_pix) >> 8); (_buf)[2] = (BYTE)((_pix) >> 16); @@ -254,6 +282,7 @@ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix) static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) { + WINPR_ASSERT(_buf); _buf[0] = _pix & 0xFF; _buf[1] = (_pix >> 8) & 0xFF; } @@ -361,7 +390,11 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE* UINT32 BufferSize; if (!interleaved || !pSrcData || !pDstData) + { + WLog_ERR(TAG, "[%s] invalid arguments: interleaved=%p, pSrcData=%p, pDstData=%p", + __FUNCTION__, interleaved, pSrcData, pDstData); return FALSE; + } switch (bpp) { @@ -386,7 +419,7 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE* break; default: - WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp); + WLog_ERR(TAG, "[%s] Invalid color depth %" PRIu32 "", __FUNCTION__, bpp); return FALSE; } @@ -399,14 +432,20 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE* } if (!interleaved->TempBuffer) + { + WLog_ERR(TAG, "[%s] interleaved->TempBuffer=%p", __FUNCTION__, interleaved->TempBuffer); return FALSE; + } switch (bpp) { case 24: if (!RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth, nSrcHeight)) + { + WLog_ERR(TAG, "[%s] RleDecompress24to24 failed", __FUNCTION__); return FALSE; + } break; @@ -414,24 +453,36 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const BYTE* case 15: if (!RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth, nSrcHeight)) + { + WLog_ERR(TAG, "[%s] RleDecompress16to16 failed", __FUNCTION__); return FALSE; + } break; case 8: if (!RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth, nSrcHeight)) + { + WLog_ERR(TAG, "[%s] RleDecompress8to8 failed", __FUNCTION__); return FALSE; + } break; default: + WLog_ERR(TAG, "[%s] Invalid color depth %" PRIu32 "", __FUNCTION__, bpp); return FALSE; } - return freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight, - interleaved->TempBuffer, SrcFormat, scanline, 0, 0, palette, - FREERDP_FLIP_VERTICAL); + if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight, + interleaved->TempBuffer, SrcFormat, scanline, 0, 0, palette, + FREERDP_FLIP_VERTICAL)) + { + WLog_ERR(TAG, "[%s] freerdp_image_copy failed", __FUNCTION__); + return FALSE; + } + return TRUE; } BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize, -- 2.45.0 From e3b79e812c8781399bc1614e8e813d6e08947af0 Mon Sep 17 00:00:00 2001 From: Armin Novak <armin.novak@thincast.com> Date: Mon, 12 Dec 2022 16:01:59 +0100 Subject: [PATCH 3/7] [codec,interleaved] refactored run length reading --- libfreerdp/codec/interleaved.c | 166 ++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 57 deletions(-) diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 88484a2e9..5b1c55733 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -143,6 +143,106 @@ static INLINE UINT32 ExtractCodeId(BYTE bOrderHdr) /** * Extract the run length of a compression order. */ +static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) +{ + UINT runLength; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = (*pbOrderHdr) & g_MaskRegularRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + return 0; + runLength = *(pbOrderHdr + 1) + 1; + (*advance)++; + } + else + runLength = runLength * 8; + + return runLength; +} + +static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) +{ + UINT runLength; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = *pbOrderHdr & g_MaskLiteRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + return 0; + runLength = *(pbOrderHdr + 1) + 1; + (*advance)++; + } + else + runLength = runLength * 8; + + return runLength; +} + +static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) +{ + UINT runLength; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = *pbOrderHdr & g_MaskRegularRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + return 0; + runLength = *(pbOrderHdr + 1) + 32; + (*advance)++; + } + + return runLength; +} + +static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) +{ + UINT runLength; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + if (!buffer_within_range(pbOrderHdr + 2, pbEnd)) + return 0; + + runLength = ((UINT16)pbOrderHdr[1]) | (((UINT16)pbOrderHdr[2]) << 8); + (*advance) += 2; + + return runLength; +} + +static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) +{ + UINT runLength; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = *pbOrderHdr & g_MaskLiteRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + return 0; + runLength = *(pbOrderHdr + 1) + 16; + (*advance)++; + } + return runLength; +} + static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance) { @@ -161,72 +261,23 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const switch (code) { case REGULAR_FGBG_IMAGE: - runLength = (*pbOrderHdr) & g_MaskRegularRunLength; - - if (runLength == 0) - { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) - return 0; - runLength = (*(pbOrderHdr + 1)) + 1; - ladvance += 1; - } - else - { - runLength = runLength * 8; - } - + runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, pbEnd, &ladvance); break; case LITE_SET_FG_FGBG_IMAGE: - runLength = (*pbOrderHdr) & g_MaskLiteRunLength; - - if (runLength == 0) - { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) - return 0; - - runLength = (*(pbOrderHdr + 1)) + 1; - ladvance += 1; - } - else - { - runLength = runLength * 8; - } - + runLength = ExtractRunLengthLiteFgBg(pbOrderHdr, pbEnd, &ladvance); break; case REGULAR_BG_RUN: case REGULAR_FG_RUN: case REGULAR_COLOR_RUN: case REGULAR_COLOR_IMAGE: - runLength = (*pbOrderHdr) & g_MaskRegularRunLength; - - if (runLength == 0) - { - /* An extended (MEGA) run. */ - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) - return 0; - - runLength = (*(pbOrderHdr + 1)) + 32; - ladvance += 1; - } - + runLength = ExtractRunLengthRegular(pbOrderHdr, pbEnd, &ladvance); break; case LITE_SET_FG_FG_RUN: case LITE_DITHERED_RUN: - runLength = (*pbOrderHdr) & g_MaskLiteRunLength; - - if (runLength == 0) - { - /* An extended (MEGA) run. */ - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) - return 0; - - runLength = (*(pbOrderHdr + 1)) + 16; - ladvance += 1; - } - + runLength = ExtractRunLengthLite(pbOrderHdr, pbEnd, &ladvance); break; case MEGA_MEGA_BG_RUN: @@ -237,11 +288,12 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const case MEGA_MEGA_FGBG_IMAGE: case MEGA_MEGA_SET_FGBG_IMAGE: case MEGA_MEGA_COLOR_IMAGE: - if (!buffer_within_range(pbOrderHdr + 2, pbEnd)) - return 0; + runLength = ExtractRunLengthMegaMega(pbOrderHdr, pbEnd, &ladvance); + break; - runLength = ((UINT16)pbOrderHdr[1]) | ((UINT16)(pbOrderHdr[2] << 8)); - ladvance += 2; + default: + runLength = 0; + ladvance = 0; break; } -- 2.45.0 From 222fc7905b4fd936f47b14e3d856bb2f21e35923 Mon Sep 17 00:00:00 2001 From: Armin Novak <anovak@thincast.com> Date: Thu, 7 Sep 2023 19:49:15 +0200 Subject: [PATCH 4/7] [codec,interleaved] fix type definition --- libfreerdp/codec/include/bitmap.c | 31 ++++++++++++++------- libfreerdp/codec/interleaved.c | 46 +++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index c41c5cb0a..9eed1c439 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -211,7 +211,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN) { - if (!buffer_within_range(pbSrc, pbEnd)) + if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd)) return FALSE; SRCREADPIXEL(fgPel, pbSrc); } @@ -240,10 +240,10 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (advance == 0) return FALSE; pbSrc = pbSrc + advance; - if (!buffer_within_range(pbSrc, pbEnd)) + if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd)) return FALSE; SRCREADPIXEL(pixelA, pbSrc); - if (!buffer_within_range(pbSrc, pbEnd)) + if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd)) return FALSE; SRCREADPIXEL(pixelB, pbSrc); @@ -263,7 +263,7 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (advance == 0) return FALSE; pbSrc = pbSrc + advance; - if (!buffer_within_range(pbSrc, pbEnd)) + if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd)) return FALSE; SRCREADPIXEL(pixelA, pbSrc); @@ -283,13 +283,15 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY return FALSE; pbSrc = pbSrc + advance; - if (!buffer_within_range(pbSrc, pbEnd)) - return FALSE; if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE) { + if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd)) + return FALSE; SRCREADPIXEL(fgPel, pbSrc); } + if (!buffer_within_range(pbSrc, runLength / 8, pbEnd)) + return FALSE; if (fFirstLine) { while (runLength > 8) @@ -308,8 +310,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY { while (runLength > 8) { - bitmask = *pbSrc; - pbSrc = pbSrc + 1; + bitmask = *pbSrc++; + pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8); if (!pbDest) @@ -321,8 +323,9 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (runLength > 0) { - bitmask = *pbSrc; - pbSrc = pbSrc + 1; + if (!buffer_within_range(pbSrc, 1, pbEnd)) + return FALSE; + bitmask = *pbSrc++; if (fFirstLine) { @@ -361,6 +364,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Special Order 1. */ case SPECIAL_FGBG_1: + if (!buffer_within_range(pbSrc, 1, pbEnd)) + return FALSE; pbSrc = pbSrc + 1; if (fFirstLine) @@ -381,6 +386,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Special Order 2. */ case SPECIAL_FGBG_2: + if (!buffer_within_range(pbSrc, 1, pbEnd)) + return FALSE; pbSrc = pbSrc + 1; if (fFirstLine) @@ -401,6 +408,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle White Order. */ case SPECIAL_WHITE: + if (!buffer_within_range(pbSrc, 1, pbEnd)) + return FALSE; pbSrc = pbSrc + 1; if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1)) @@ -411,6 +420,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY /* Handle Black Order. */ case SPECIAL_BLACK: + if (!buffer_within_range(pbSrc, 1, pbEnd)) + return FALSE; pbSrc = pbSrc + 1; if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1)) diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 5b1c55733..e6555ccdc 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -39,7 +39,9 @@ for (x = 0; x < (_count); x++) \ { \ do \ - _exp while (FALSE); \ + { \ + _exp \ + } while (FALSE); \ } \ } while (FALSE) @@ -99,15 +101,19 @@ static const BYTE g_MaskSpecialFgBg2 = 0x05; static const BYTE g_MaskRegularRunLength = 0x1F; static const BYTE g_MaskLiteRunLength = 0x0F; -#define buffer_within_range(pbSrc, pbEnd) \ - buffer_within_range_((pbSrc), (pbEnd), __FUNCTION__, __FILE__, __LINE__) -static INLINE BOOL buffer_within_range_(const void* pbSrc, const void* pbEnd, const char* fkt, - const char* file, size_t line) +#define buffer_within_range(pbSrc, size, pbEnd) \ + buffer_within_range_((pbSrc), (size), (pbEnd), __func__, __FILE__, __LINE__) +static INLINE BOOL buffer_within_range_(const void* pbSrc, size_t size, const void* pbEnd, + const char* fkt, const char* file, size_t line) { WINPR_UNUSED(file); - if (pbSrc >= pbEnd) + WINPR_ASSERT(pbSrc); + WINPR_ASSERT(pbEnd); + + if ((char*)pbSrc + size > pbEnd) { - WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p >= pbEnd=%p", fkt, line, pbSrc, pbEnd); + WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p + %" PRIuz " > pbEnd=%p", fkt, line, pbSrc, size, + pbEnd); return FALSE; } return TRUE; @@ -154,7 +160,7 @@ static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEn runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 1; (*advance)++; @@ -176,7 +182,7 @@ static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, runLength = *pbOrderHdr & g_MaskLiteRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 1; (*advance)++; @@ -198,7 +204,7 @@ static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, U runLength = *pbOrderHdr & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 32; (*advance)++; @@ -215,7 +221,7 @@ static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (!buffer_within_range(pbOrderHdr + 2, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) return 0; runLength = ((UINT16)pbOrderHdr[1]) | (((UINT16)pbOrderHdr[2]) << 8); @@ -235,7 +241,7 @@ static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT runLength = *pbOrderHdr & g_MaskLiteRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr + 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 16; (*advance)++; @@ -255,7 +261,7 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (!buffer_within_range(pbOrderHdr, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 0, pbEnd)) return 0; switch (code) @@ -347,6 +353,10 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) #undef RLEDECOMPRESS #undef RLEEXTRA #undef WHITE_PIXEL +#undef PIXEL_SIZE +#undef PIXEL +#define PIXEL_SIZE 1 +#define PIXEL BYTE #define WHITE_PIXEL 0xFF #define DESTWRITEPIXEL(_buf, _pix) \ do \ @@ -378,6 +388,10 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) #undef RLEDECOMPRESS #undef RLEEXTRA #undef WHITE_PIXEL +#undef PIXEL_SIZE +#undef PIXEL +#define PIXEL_SIZE 2 +#define PIXEL UINT16 #define WHITE_PIXEL 0xFFFF #define DESTWRITEPIXEL(_buf, _pix) \ do \ @@ -408,7 +422,11 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) #undef RLEDECOMPRESS #undef RLEEXTRA #undef WHITE_PIXEL -#define WHITE_PIXEL 0xFFFFFF +#undef PIXEL_SIZE +#undef PIXEL +#define PIXEL_SIZE 3 +#define PIXEL UINT32 +#define WHITE_PIXEL 0xffffff #define DESTWRITEPIXEL(_buf, _pix) \ do \ { \ -- 2.45.0 From d57dcd9ab824274a6fd759a1915df63a717562ad Mon Sep 17 00:00:00 2001 From: akallabeth <akallabeth@posteo.net> Date: Tue, 13 Dec 2022 11:02:55 +0100 Subject: [PATCH 5/7] [codec,interleaved] move length check out of loop --- libfreerdp/codec/include/bitmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index 9eed1c439..9e4ed6f4e 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -353,10 +353,10 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY pbSrc = pbSrc + advance; if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength)) return FALSE; + if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength)) + return FALSE; UNROLL(runLength, { - if (!buffer_within_range(pbSrc, pbEnd)) - return FALSE; SRCREADPIXEL(temp, pbSrc); DESTWRITEPIXEL(pbDest, temp); }); -- 2.45.0 From c91dfc7ac6f7cdc3af4ad599f2f6978a2f778685 Mon Sep 17 00:00:00 2001 From: akallabeth <akallabeth@posteo.net> Date: Sat, 20 Apr 2024 17:59:49 +0200 Subject: [PATCH 6/7] [codec,interleaved] fix offset error --- libfreerdp/codec/interleaved.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index e6555ccdc..a35e0ba4a 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -160,7 +160,7 @@ static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEn runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 1; (*advance)++; @@ -221,7 +221,7 @@ static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 3, pbEnd)) return 0; runLength = ((UINT16)pbOrderHdr[1]) | (((UINT16)pbOrderHdr[2]) << 8); -- 2.45.0 From 855a0f3812291b4b5ae035a0f8b2e021945defce Mon Sep 17 00:00:00 2001 From: akallabeth <akallabeth@posteo.net> Date: Tue, 16 Apr 2024 08:47:31 +0200 Subject: [PATCH 7/7] [codec,interleaved] fix off by one length check --- libfreerdp/codec/interleaved.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index a35e0ba4a..aa29959ef 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -182,7 +182,7 @@ static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, runLength = *pbOrderHdr & g_MaskLiteRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) return 0; runLength = *(pbOrderHdr + 1) + 1; (*advance)++; -- 2.45.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor