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.1.2/libfreerdp/codec/color.c
===================================================================
--- FreeRDP-2.1.2.orig/libfreerdp/codec/color.c
+++ FreeRDP-2.1.2/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,
@@ -263,13 +266,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);
 
@@ -278,20 +277,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);
