File freerdp-CVE-2026-26271.patch of Package freerdp.43418
From f5e20403d6e325e11b68129803f967fb5aeec1cb Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Fri, 13 Feb 2026 19:38:20 +0100
Subject: [PATCH] [codec,color] fix input length checks
* check cbBitsMask meets expected length
* Add logging for length failures
---
libfreerdp/codec/color.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
Index: freerdp-2.11.7/libfreerdp/codec/color.c
===================================================================
--- freerdp-2.11.7.orig/libfreerdp/codec/color.c
+++ freerdp-2.11.7/libfreerdp/codec/color.c
@@ -217,6 +217,9 @@ BOOL freerdp_image_copy_from_icon_data(B
if (!pDstData || !bitsColor)
return FALSE;
+ if ((nWidth == 0) || (nHeight == 0))
+ return TRUE;
+
/*
* Color formats used by icons are DIB bitmap formats (2-bit format
* is not used by MS-RDPERP). Note that 16-bit is RGB555, not RGB565,
@@ -259,7 +262,13 @@ BOOL freerdp_image_copy_from_icon_data(B
/* Ensure we have enough source data bytes for image copy. */
if (cbBitsColor < nWidth * nHeight * GetBytesPerPixel(format))
+ {
+ WLog_ERR(TAG,
+ "cbBitsColor{%" PRIu32 "} < nWidth{%" PRIu32 "} * nHeight{%" PRIu32
+ "} * bpp{%" PRIu32 "}",
+ cbBitsColor, nWidth, nHeight, GetBytesPerPixel(format));
return FALSE;
+ }
fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, bitsColor,
@@ -267,13 +276,9 @@ BOOL freerdp_image_copy_from_icon_data(B
return FALSE;
/* apply alpha mask */
- if (ColorHasAlpha(DstFormat) && cbBitsMask)
+ if (ColorHasAlpha(DstFormat) && (cbBitsMask > 0))
{
- BYTE nextBit;
- const BYTE* maskByte;
UINT32 x, y;
- UINT32 stride;
- BYTE r, g, b;
BYTE* dstBuf = pDstData;
UINT32 dstBpp = GetBytesPerPixel(DstFormat);
@@ -282,20 +287,29 @@ BOOL freerdp_image_copy_from_icon_data(B
* And due to hysterical raisins, stride of DIB bitmaps must be
* a multiple of 4 bytes.
*/
- stride = round_up(div_ceil(nWidth, 8), 4);
+ const size_t stride = round_up(div_ceil(nWidth, 8), 4);
+ if (cbBitsMask < stride * (nHeight - 1ULL))
+ {
+ WLog_ERR(TAG,
+ "cbBitsMask{%" PRIu32 "} < stride{%" PRIuz "} * (nHeight{%" PRIu32 "} - 1)",
+ cbBitsMask, stride, nHeight);
+ return FALSE;
+ }
for (y = 0; y < nHeight; y++)
{
- maskByte = &bitsMask[stride * (nHeight - 1 - y)];
- nextBit = 0x80;
+ const BYTE* maskByte = &bitsMask[stride * (nHeight - 1ULL - y)];
+ BYTE nextBit = 0x80;
for (x = 0; x < nWidth; x++)
{
- UINT32 color;
+ BYTE r = 0;
+ BYTE g = 0;
+ BYTE b = 0;
BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
/* read color back, add alpha and write it back */
- color = ReadColor(dstBuf, DstFormat);
+ UINT32 color = ReadColor(dstBuf, DstFormat);
SplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
WriteColor(dstBuf, DstFormat, color);