Details: https://nvd.nist.gov/vuln/detail/CVE-2024-32460

Backport the patch that is marked to resolve this vulnerability
by the relevant Github advisory[1].

[1]: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4rr8-gr65-vqrr

Signed-off-by: Gyorgy Sarvari <[email protected]>
---
 .../freerdp/freerdp/CVE-2024-32460.patch      | 1030 +++++++++++++++++
 .../recipes-support/freerdp/freerdp_2.6.1.bb  |    1 +
 2 files changed, 1031 insertions(+)
 create mode 100644 meta-oe/recipes-support/freerdp/freerdp/CVE-2024-32460.patch

diff --git a/meta-oe/recipes-support/freerdp/freerdp/CVE-2024-32460.patch 
b/meta-oe/recipes-support/freerdp/freerdp/CVE-2024-32460.patch
new file mode 100644
index 0000000000..356e1a99ef
--- /dev/null
+++ b/meta-oe/recipes-support/freerdp/freerdp/CVE-2024-32460.patch
@@ -0,0 +1,1030 @@
+From 86391660a70ac263c21a818c51528c42d01e64c5 Mon Sep 17 00:00:00 2001
+From: Armin Novak <[email protected]>
+Date: Wed, 17 Apr 2024 11:23:52 +0200
+Subject: [PATCH] backport from 3.5.0
+
+CVE: CVE-2024-32460
+Upstream-Status: Backport 
[https://github.com/FreeRDP/FreeRDP/commit/18cef378eae2b63a1a750da242f00da12b5b3881]
+Signed-off-by: Gyorgy Sarvari <[email protected]>
+---
+ libfreerdp/codec/include/bitmap.c | 119 ++++----
+ libfreerdp/codec/interleaved.c    | 448 +++++++++++++++++++++++-------
+ 2 files changed, 413 insertions(+), 154 deletions(-)
+
+diff --git a/libfreerdp/codec/include/bitmap.c 
b/libfreerdp/codec/include/bitmap.c
+index 38bcaa859..af8338711 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, "cBits %d > 8", cBits);
+               return NULL;
++      }
+ 
+       if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
+               return NULL;
+@@ -46,7 +49,6 @@ static INLINE BYTE* WRITEFGBGIMAGE(BYTE* pbDest, const BYTE* 
pbDestEnd, UINT32 r
+                       data = xorPixel;
+ 
+               DESTWRITEPIXEL(pbDest, data);
+-              DESTNEXTPIXEL(pbDest);
+               mask = mask << 1;
+       });
+       return pbDest;
+@@ -62,7 +64,10 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, 
const BYTE* pbDestEnd,
+       BYTE mask = 0x01;
+ 
+       if (cBits > 8)
++      {
++              WLog_ERR(TAG, "cBits %d > 8", cBits);
+               return NULL;
++      }
+ 
+       if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
+               return NULL;
+@@ -76,7 +81,6 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, 
const BYTE* pbDestEnd,
+                       data = BLACK_PIXEL;
+ 
+               DESTWRITEPIXEL(pbDest, data);
+-              DESTNEXTPIXEL(pbDest);
+               mask = mask << 1;
+       });
+       return pbDest;
+@@ -88,6 +92,9 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, 
const BYTE* pbDestEnd,
+ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, 
BYTE* pbDestBuffer,
+                                  UINT32 rowDelta, UINT32 width, UINT32 height)
+ {
++#if defined(WITH_DEBUG_CODECS)
++      char sbuffer[128] = { 0 };
++#endif
+       const BYTE* pbSrc = pbSrcBuffer;
+       const BYTE* pbEnd;
+       const BYTE* pbDestEnd;
+@@ -100,14 +107,22 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* 
pbSrcBuffer, UINT32 cbSrcBuffer, BY
+       PIXEL pixelA, pixelB;
+       UINT32 runLength;
+       UINT32 code;
+-      UINT32 advance;
++      UINT32 advance = 0;
+       RLEEXTRA
+ 
+       if ((rowDelta == 0) || (rowDelta < width))
++      {
++              WLog_ERR(TAG, "Invalid arguments: rowDelta=%" PRIu32 " == 0 || 
< width=%" PRIu32, rowDelta,
++                       width);
+               return FALSE;
++      }
+ 
+       if (!pbSrcBuffer || !pbDestBuffer)
++      {
++              WLog_ERR(TAG, "Invalid arguments: pbSrcBuffer=%p, 
pbDestBuffer=%p", pbSrcBuffer,
++                       pbDestBuffer);
+               return FALSE;
++      }
+ 
+       pbEnd = pbSrcBuffer + cbSrcBuffer;
+       pbDestEnd = pbDestBuffer + rowDelta * height;
+@@ -130,10 +145,17 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* 
pbSrcBuffer, UINT32 cbSrcBuffer, BY
+               */
+               code = ExtractCodeId(*pbSrc);
+ 
++#if defined(WITH_DEBUG_CODECS)
++              WLog_VRB(TAG, "pbSrc=%p code=%s, rem=%" PRIuz, pbSrc,
++                       rle_code_str_buffer(code, sbuffer, sizeof(sbuffer)), 
pbEnd - pbSrc);
++#endif
++
+               /* Handle Background Run Orders. */
+-              if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN)
++              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;
+ 
+                       if (fFirstLine)
+@@ -144,17 +166,13 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* 
pbSrcBuffer, UINT32 cbSrcBuffer, BY
+                                               return FALSE;
+ 
+                                       DESTWRITEPIXEL(pbDest, fgPel);
+-                                      DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+ 
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 
runLength))
+                                       return FALSE;
+ 
+-                              UNROLL(runLength, {
+-                                      DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+-                                      DESTNEXTPIXEL(pbDest);
+-                              });
++                              UNROLL(runLength, { DESTWRITEPIXEL(pbDest, 
BLACK_PIXEL); });
+                       }
+                       else
+                       {
+@@ -166,7 +184,6 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, 
UINT32 cbSrcBuffer, BY
+                                               return FALSE;
+ 
+                                       DESTWRITEPIXEL(pbDest, temp ^ fgPel);
+-                                      DESTNEXTPIXEL(pbDest);
+                                       runLength--;
+                               }
+ 
+@@ -176,7 +193,6 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, 
UINT32 cbSrcBuffer, BY
+                               UNROLL(runLength, {
+                                       DESTREADPIXEL(temp, pbDest - rowDelta);
+                                       DESTWRITEPIXEL(pbDest, temp);
+-                                      DESTNEXTPIXEL(pbDest);
+                               });
+                       }
+ 
+@@ -196,15 +212,16 @@ 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;
+ 
+                               if (code == LITE_SET_FG_FG_RUN || code == 
MEGA_MEGA_SET_FG_RUN)
+                               {
+-                                      if (pbSrc >= pbEnd)
++                                      if (!buffer_within_range(pbSrc, 
PIXEL_SIZE, pbEnd))
+                                               return FALSE;
+                                       SRCREADPIXEL(fgPel, pbSrc);
+-                                      SRCNEXTPIXEL(pbSrc);
+                               }
+ 
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 
runLength))
+@@ -212,17 +229,13 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* 
pbSrcBuffer, UINT32 cbSrcBuffer, BY
+ 
+                               if (fFirstLine)
+                               {
+-                                      UNROLL(runLength, {
+-                                              DESTWRITEPIXEL(pbDest, fgPel);
+-                                              DESTNEXTPIXEL(pbDest);
+-                                      });
++                                      UNROLL(runLength, { 
DESTWRITEPIXEL(pbDest, fgPel); });
+                               }
+                               else
+                               {
+                                       UNROLL(runLength, {
+                                               DESTREADPIXEL(temp, pbDest - 
rowDelta);
+                                               DESTWRITEPIXEL(pbDest, temp ^ 
fgPel);
+-                                              DESTNEXTPIXEL(pbDest);
+                                       });
+                               }
+ 
+@@ -231,45 +244,41 @@ 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;
+-                              if (pbSrc >= pbEnd)
++                              if (!buffer_within_range(pbSrc, PIXEL_SIZE, 
pbEnd))
+                                       return FALSE;
+                               SRCREADPIXEL(pixelA, pbSrc);
+-                              SRCNEXTPIXEL(pbSrc);
+-                              if (pbSrc >= pbEnd)
++                              if (!buffer_within_range(pbSrc, PIXEL_SIZE, 
pbEnd))
+                                       return FALSE;
+                               SRCREADPIXEL(pixelB, pbSrc);
+-                              SRCNEXTPIXEL(pbSrc);
+ 
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 
runLength * 2))
+                                       return FALSE;
+ 
+                               UNROLL(runLength, {
+                                       DESTWRITEPIXEL(pbDest, pixelA);
+-                                      DESTNEXTPIXEL(pbDest);
+                                       DESTWRITEPIXEL(pbDest, pixelB);
+-                                      DESTNEXTPIXEL(pbDest);
+                               });
+                               break;
+ 
+                       /* 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;
+-                              if (pbSrc >= pbEnd)
++                              if (!buffer_within_range(pbSrc, PIXEL_SIZE, 
pbEnd))
+                                       return FALSE;
+                               SRCREADPIXEL(pixelA, pbSrc);
+-                              SRCNEXTPIXEL(pbSrc);
+ 
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 
runLength))
+                                       return FALSE;
+ 
+-                              UNROLL(runLength, {
+-                                      DESTWRITEPIXEL(pbDest, pixelA);
+-                                      DESTNEXTPIXEL(pbDest);
+-                              });
++                              UNROLL(runLength, { DESTWRITEPIXEL(pbDest, 
pixelA); });
+                               break;
+ 
+                       /* Handle Foreground/Background Image Orders. */
+@@ -277,17 +286,20 @@ 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;
+ 
+-                              if (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);
+-                                      SRCNEXTPIXEL(pbSrc);
+                               }
+ 
++                              if (!buffer_within_range(pbSrc, runLength / 8, 
pbEnd))
++                                      return FALSE;
+                               if (fFirstLine)
+                               {
+                                       while (runLength > 8)
+@@ -306,8 +318,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)
+@@ -319,8 +331,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)
+                                       {
+@@ -342,23 +355,25 @@ 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;
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 
runLength))
+                                       return FALSE;
++                              if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
++                                      return FALSE;
+ 
+                               UNROLL(runLength, {
+-                                      if (pbSrc >= pbEnd)
+-                                              return FALSE;
+                                       SRCREADPIXEL(temp, pbSrc);
+-                                      SRCNEXTPIXEL(pbSrc);
+                                       DESTWRITEPIXEL(pbDest, temp);
+-                                      DESTNEXTPIXEL(pbDest);
+                               });
+                               break;
+ 
+                       /* Handle Special Order 1. */
+                       case SPECIAL_FGBG_1:
++                              if (!buffer_within_range(pbSrc, 1, pbEnd))
++                                      return FALSE;
+                               pbSrc = pbSrc + 1;
+ 
+                               if (fFirstLine)
+@@ -379,6 +394,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)
+@@ -399,27 +416,31 @@ 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))
+                                       return FALSE;
+ 
+                               DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
+-                              DESTNEXTPIXEL(pbDest);
+                               break;
+ 
+                       /* Handle Black Order. */
+                       case SPECIAL_BLACK:
++                              if (!buffer_within_range(pbSrc, 1, pbEnd))
++                                      return FALSE;
+                               pbSrc = pbSrc + 1;
+ 
+                               if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
+                                       return FALSE;
+ 
+                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+-                              DESTNEXTPIXEL(pbDest);
+                               break;
+ 
+                       default:
++                              WLog_ERR(TAG, "invalid code 0x%08" PRIx32 ", 
pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
++                                       code, pbSrcBuffer, pbSrc, pbEnd);
+                               return FALSE;
+               }
+       }
+diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
+index b76fe1ca3..abfdc51f9 100644
+--- a/libfreerdp/codec/interleaved.c
++++ b/libfreerdp/codec/interleaved.c
+@@ -21,6 +21,7 @@
+  * limitations under the License.
+  */
+ 
++#include <assert.h>
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+@@ -30,15 +31,16 @@
+ 
+ #define TAG FREERDP_TAG("codec")
+ 
+-#define UNROLL_BODY(_exp, _count)      \
+-      do                                 \
+-      {                                  \
+-              size_t x;                      \
+-              for (x = 0; x < (_count); x++) \
+-              {                              \
+-                      do                         \
+-                              _exp while (FALSE);    \
+-              }                              \
++#define UNROLL_BODY(_exp, _count)             \
++      do                                        \
++      {                                         \
++              for (size_t x = 0; x < (_count); x++) \
++              {                                     \
++                      do                                \
++                      {                                 \
++                              _exp                          \
++                      } while (FALSE);                  \
++              }                                     \
+       } while (FALSE)
+ 
+ #define UNROLL_MULTIPLE(_condition, _exp, _count) \
+@@ -97,6 +99,80 @@ static const BYTE g_MaskSpecialFgBg2 = 0x05;
+ static const BYTE g_MaskRegularRunLength = 0x1F;
+ static const BYTE g_MaskLiteRunLength = 0x0F;
+ 
++static const char* rle_code_str(UINT32 code)
++{
++      switch (code)
++      {
++              case REGULAR_BG_RUN:
++                      return "REGULAR_BG_RUN";
++              case MEGA_MEGA_BG_RUN:
++                      return "MEGA_MEGA_BG_RUN";
++              case REGULAR_FG_RUN:
++                      return "REGULAR_FG_RUN";
++              case MEGA_MEGA_FG_RUN:
++                      return "MEGA_MEGA_FG_RUN";
++              case LITE_SET_FG_FG_RUN:
++                      return "LITE_SET_FG_FG_RUN";
++              case MEGA_MEGA_SET_FG_RUN:
++                      return "MEGA_MEGA_SET_FG_RUN";
++              case LITE_DITHERED_RUN:
++                      return "LITE_DITHERED_RUN";
++              case MEGA_MEGA_DITHERED_RUN:
++                      return "MEGA_MEGA_DITHERED_RUN";
++              case REGULAR_COLOR_RUN:
++                      return "REGULAR_COLOR_RUN";
++              case MEGA_MEGA_COLOR_RUN:
++                      return "MEGA_MEGA_COLOR_RUN";
++              case REGULAR_FGBG_IMAGE:
++                      return "REGULAR_FGBG_IMAGE";
++              case MEGA_MEGA_FGBG_IMAGE:
++                      return "MEGA_MEGA_FGBG_IMAGE";
++              case LITE_SET_FG_FGBG_IMAGE:
++                      return "LITE_SET_FG_FGBG_IMAGE";
++              case MEGA_MEGA_SET_FGBG_IMAGE:
++                      return "MEGA_MEGA_SET_FGBG_IMAGE";
++              case REGULAR_COLOR_IMAGE:
++                      return "REGULAR_COLOR_IMAGE";
++              case MEGA_MEGA_COLOR_IMAGE:
++                      return "MEGA_MEGA_COLOR_IMAGE";
++              case SPECIAL_FGBG_1:
++                      return "SPECIAL_FGBG_1";
++              case SPECIAL_FGBG_2:
++                      return "SPECIAL_FGBG_2";
++              case SPECIAL_WHITE:
++                      return "SPECIAL_WHITE";
++              case SPECIAL_BLACK:
++                      return "SPECIAL_BLACK";
++              default:
++                      return "UNKNOWN";
++      }
++}
++
++static const char* rle_code_str_buffer(UINT32 code, char* buffer, size_t size)
++{
++      const char* str = rle_code_str(code);
++      _snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, code);
++      return buffer;
++}
++
++#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);
++      assert((pbSrc) && "Assert failed: pbSrc");
++      assert((pbEnd) && "Assert failed: pbEnd");
++
++      if ((const char*)pbSrc + size > (const char*)pbEnd)
++      {
++              WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p + %" PRIuz " > 
pbEnd=%p", fkt, line, pbSrc, size,
++                       pbEnd);
++              return FALSE;
++      }
++      return TRUE;
++}
++
+ /**
+  * Reads the supplied order header and extracts the compression
+  * order code ID.
+@@ -127,71 +203,155 @@ 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 UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* 
pbEnd, UINT32* advance)
+ {
+-      UINT32 runLength;
+-      UINT32 ladvance;
+-      ladvance = 1;
+-      runLength = 0;
++      UINT runLength = 0;
+ 
+-      switch (code)
++      assert((pbOrderHdr) && "Assert failed: pbOrderHdr");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
++
++      runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
++      if (runLength == 0)
+       {
+-              case REGULAR_FGBG_IMAGE:
+-                      runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
++              if (!buffer_within_range(pbOrderHdr, 1, pbEnd))
++              {
++                      *advance = 0;
++                      return 0;
++              }
++              runLength = *(pbOrderHdr + 1) + 1;
++              (*advance)++;
++      }
++      else
++              runLength = runLength * 8;
+ 
+-                      if (runLength == 0)
+-                      {
+-                              runLength = (*(pbOrderHdr + 1)) + 1;
+-                              ladvance += 1;
+-                      }
+-                      else
+-                      {
+-                              runLength = runLength * 8;
+-                      }
++      return runLength;
++}
+ 
+-                      break;
++static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* 
pbEnd, UINT32* advance)
++{
++      UINT runLength = 0;
+ 
+-              case LITE_SET_FG_FGBG_IMAGE:
+-                      runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
++      assert((pbOrderHdr) && "Assert failed: pbOrderHdr");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
+ 
+-                      if (runLength == 0)
+-                      {
+-                              runLength = (*(pbOrderHdr + 1)) + 1;
+-                              ladvance += 1;
+-                      }
+-                      else
+-                      {
+-                              runLength = runLength * 8;
+-                      }
++      runLength = *pbOrderHdr & g_MaskLiteRunLength;
++      if (runLength == 0)
++      {
++              if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
++              {
++                      *advance = 0;
++                      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 = 0;
++
++      assert((pbOrderHeader) && "Assert failed: pbOrderHeader");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
++
++      runLength = *pbOrderHdr & g_MaskRegularRunLength;
++      if (runLength == 0)
++      {
++              if (!buffer_within_range(pbOrderHdr, 1, pbEnd))
++              {
++                      *advance = 0;
++                      return 0;
++              }
++              runLength = *(pbOrderHdr + 1) + 32;
++              (*advance)++;
++      }
++
++      return runLength;
++}
++
++static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* 
pbEnd, UINT32* advance)
++{
++      UINT runLength = 0;
++
++      assert((pbOrderHdr) && "Assert failed: pbOrderHdr");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
++
++      if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
++      {
++              *advance = 0;
++              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 = 0;
++
++      assert((pbOrderHdr) && "Assert failed: pbOrderHdr");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
++
++      runLength = *pbOrderHdr & g_MaskLiteRunLength;
++      if (runLength == 0)
++      {
++              if (!buffer_within_range(pbOrderHdr, 1, pbEnd))
++              {
++                      *advance = 0;
++                      return 0;
++              }
++              runLength = *(pbOrderHdr + 1) + 16;
++              (*advance)++;
++      }
++      return runLength;
++}
++
++static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, 
const BYTE* pbEnd,
++                                      UINT32* advance)
++{
++      UINT32 runLength = 0;
++      UINT32 ladvance = 1;
++
++      assert((pbOrderHdr) && "Assert failed: pbOrderHdr");
++      assert((pbEnd) && "Assert failed: pbEnd");
++      assert((advance) && "Assert failed: advance");
++
++      *advance = 0;
++      if (!buffer_within_range(pbOrderHdr, 0, pbEnd))
++              return 0;
++
++      switch (code)
++      {
++              case REGULAR_FGBG_IMAGE:
++                      runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, 
pbEnd, &ladvance);
++                      break;
+ 
++              case LITE_SET_FG_FGBG_IMAGE:
++                      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. */
+-                              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. */
+-                              runLength = (*(pbOrderHdr + 1)) + 16;
+-                              ladvance += 1;
+-                      }
+-
++                      runLength = ExtractRunLengthLite(pbOrderHdr, pbEnd, 
&ladvance);
+                       break;
+ 
+               case MEGA_MEGA_BG_RUN:
+@@ -202,8 +362,12 @@ 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:
+-                      runLength = ((UINT16)pbOrderHdr[1]) | 
((UINT16)(pbOrderHdr[2] << 8));
+-                      ladvance += 2;
++                      runLength = ExtractRunLengthMegaMega(pbOrderHdr, pbEnd, 
&ladvance);
++                      break;
++
++              default:
++                      runLength = 0;
++                      ladvance = 0;
+                       break;
+       }
+ 
+@@ -211,20 +375,32 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, const 
BYTE* pbOrderHdr, UINT3
+       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), __func__, __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)
+ {
++      assert((_buf) && "Assert failed: _buf");
+       *_buf = _pix;
+ }
+ 
+ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
+ {
++      assert((_buf) && "Assert failed: _buf");
+       (_buf)[0] = (BYTE)(_pix);
+       (_buf)[1] = (BYTE)((_pix) >> 8);
+       (_buf)[2] = (BYTE)((_pix) >> 16);
+@@ -232,6 +408,7 @@ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
+ 
+ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
+ {
++      assert((_buf) && "Assert failed: _buf");
+       _buf[0] = _pix & 0xFF;
+       _buf[1] = (_pix >> 8) & 0xFF;
+ }
+@@ -239,19 +416,30 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 
_pix)
+ #undef DESTWRITEPIXEL
+ #undef DESTREADPIXEL
+ #undef SRCREADPIXEL
+-#undef DESTNEXTPIXEL
+-#undef SRCNEXTPIXEL
+ #undef WRITEFGBGIMAGE
+ #undef WRITEFIRSTLINEFGBGIMAGE
+ #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) write_pixel_8(_buf, _pix)
++#define DESTWRITEPIXEL(_buf, _pix) \
++      do                             \
++      {                              \
++              write_pixel_8(_buf, _pix); \
++              _buf += 1;                 \
++      } while (0)
+ #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
+-#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0]
+-#define DESTNEXTPIXEL(_buf) _buf += 1
+-#define SRCNEXTPIXEL(_buf) _buf += 1
++#define SRCREADPIXEL(_pix, _buf) \
++      do                           \
++      {                            \
++              _pix = (_buf)[0];        \
++              _buf += 1;               \
++      } while (0)
++
+ #define WRITEFGBGIMAGE WriteFgBgImage8to8
+ #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
+ #define RLEDECOMPRESS RleDecompress8to8
+@@ -263,19 +451,29 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 
_pix)
+ #undef DESTWRITEPIXEL
+ #undef DESTREADPIXEL
+ #undef SRCREADPIXEL
+-#undef DESTNEXTPIXEL
+-#undef SRCNEXTPIXEL
+ #undef WRITEFGBGIMAGE
+ #undef WRITEFIRSTLINEFGBGIMAGE
+ #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) write_pixel_16(_buf, _pix)
++#define DESTWRITEPIXEL(_buf, _pix)  \
++      do                              \
++      {                               \
++              write_pixel_16(_buf, _pix); \
++              _buf += 2;                  \
++      } while (0)
+ #define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
+-#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8)
+-#define DESTNEXTPIXEL(_buf) _buf += 2
+-#define SRCNEXTPIXEL(_buf) _buf += 2
++#define SRCREADPIXEL(_pix, _buf)             \
++      do                                       \
++      {                                        \
++              _pix = (_buf)[0] | ((_buf)[1] << 8); \
++              _buf += 2;                           \
++      } while (0)
+ #define WRITEFGBGIMAGE WriteFgBgImage16to16
+ #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
+ #define RLEDECOMPRESS RleDecompress16to16
+@@ -287,19 +485,30 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 
_pix)
+ #undef DESTWRITEPIXEL
+ #undef DESTREADPIXEL
+ #undef SRCREADPIXEL
+-#undef DESTNEXTPIXEL
+-#undef SRCNEXTPIXEL
+ #undef WRITEFGBGIMAGE
+ #undef WRITEFIRSTLINEFGBGIMAGE
+ #undef RLEDECOMPRESS
+ #undef RLEEXTRA
+ #undef WHITE_PIXEL
+-#define WHITE_PIXEL 0xFFFFFF
+-#define DESTWRITEPIXEL(_buf, _pix) write_pixel_24(_buf, _pix)
++#undef PIXEL_SIZE
++#undef PIXEL
++#define PIXEL_SIZE 3
++#define PIXEL UINT32
++#define WHITE_PIXEL 0xffffff
++#define DESTWRITEPIXEL(_buf, _pix)  \
++      do                              \
++      {                               \
++              write_pixel_24(_buf, _pix); \
++              _buf += 3;                  \
++      } while (0)
+ #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | 
((_buf)[2] << 16)
+-#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | 
((_buf)[2] << 16)
+-#define DESTNEXTPIXEL(_buf) _buf += 3
+-#define SRCNEXTPIXEL(_buf) _buf += 3
++#define SRCREADPIXEL(_pix, _buf)                                 \
++      do                                                           \
++      {                                                            \
++              _pix = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16); \
++              _buf += 3;                                               \
++      } while (0)
++
+ #define WRITEFGBGIMAGE WriteFgBgImage24to24
+ #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
+ #define RLEDECOMPRESS RleDecompress24to24
+@@ -308,18 +517,32 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 
_pix)
+ #define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, 
_size, 3)
+ #include "include/bitmap.c"
+ 
++struct S_BITMAP_INTERLEAVED_CONTEXT
++{
++      BOOL Compressor;
++
++      UINT32 TempSize;
++      BYTE* TempBuffer;
++
++      wStream* bts;
++};
++
+ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, const 
BYTE* pSrcData,
+                             UINT32 SrcSize, UINT32 nSrcWidth, UINT32 
nSrcHeight, UINT32 bpp,
+                             BYTE* pDstData, UINT32 DstFormat, UINT32 
nDstStep, UINT32 nXDst,
+                             UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
+                             const gdiPalette* palette)
+ {
+-      UINT32 scanline;
+-      UINT32 SrcFormat;
+-      UINT32 BufferSize;
++      UINT32 scanline = 0;
++      UINT32 SrcFormat = 0;
++      UINT32 BufferSize = 0;
+ 
+       if (!interleaved || !pSrcData || !pDstData)
++      {
++              WLog_ERR(TAG, "invalid arguments: interleaved=%p, pSrcData=%p, 
pDstData=%p", interleaved,
++                       pSrcData, pDstData);
+               return FALSE;
++      }
+ 
+       switch (bpp)
+       {
+@@ -352,19 +575,26 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* 
interleaved, const BYTE*
+ 
+       if (BufferSize > interleaved->TempSize)
+       {
+-              interleaved->TempBuffer = 
_aligned_realloc(interleaved->TempBuffer, BufferSize, 16);
++              interleaved->TempBuffer =
++                  _aligned_recalloc(interleaved->TempBuffer, BufferSize, 
sizeof(BYTE), 16);
+               interleaved->TempSize = BufferSize;
+       }
+ 
+       if (!interleaved->TempBuffer)
++      {
++              WLog_ERR(TAG, "interleaved->TempBuffer=%p", 
interleaved->TempBuffer);
+               return FALSE;
++      }
+ 
+       switch (bpp)
+       {
+               case 24:
+                       if (!RleDecompress24to24(pSrcData, SrcSize, 
interleaved->TempBuffer, scanline,
+                                                nSrcWidth, nSrcHeight))
++                      {
++                              WLog_ERR(TAG, "RleDecompress24to24 failed");
+                               return FALSE;
++                      }
+ 
+                       break;
+ 
+@@ -372,24 +602,36 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* 
interleaved, const BYTE*
+               case 15:
+                       if (!RleDecompress16to16(pSrcData, SrcSize, 
interleaved->TempBuffer, scanline,
+                                                nSrcWidth, nSrcHeight))
++                      {
++                              WLog_ERR(TAG, "RleDecompress16to16 failed");
+                               return FALSE;
++                      }
+ 
+                       break;
+ 
+               case 8:
+                       if (!RleDecompress8to8(pSrcData, SrcSize, 
interleaved->TempBuffer, scanline, nSrcWidth,
+                                              nSrcHeight))
++                      {
++                              WLog_ERR(TAG, "RleDecompress8to8 failed");
+                               return FALSE;
++                      }
+ 
+                       break;
+ 
+               default:
++                      WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", 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, "freerdp_image_copy failed");
++              return FALSE;
++      }
++      return TRUE;
+ }
+ 
+ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* 
pDstData, UINT32* pDstSize,
+@@ -397,10 +639,10 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* 
interleaved, BYTE* pDstDat
+                           UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const 
gdiPalette* palette,
+                           UINT32 bpp)
+ {
+-      BOOL status;
+-      wStream* s;
++      BOOL status = 0;
++      wStream* s = NULL;
+       UINT32 DstFormat = 0;
+-      const size_t maxSize = 64 * 64 * 4;
++      const UINT32 maxSize = 64 * 64 * 4;
+ 
+       if (!interleaved || !pDstData || !pSrcData)
+               return FALSE;
+@@ -442,7 +684,7 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* 
interleaved, BYTE* pDstDat
+       }
+ 
+       if (!freerdp_image_copy(interleaved->TempBuffer, DstFormat, 0, 0, 0, 
nWidth, nHeight, pSrcData,
+-                              SrcFormat, nSrcStep, nXSrc, nYSrc, palette, 
FREERDP_FLIP_NONE))
++                              SrcFormat, nSrcStep, nXSrc, nYSrc, palette, 0))
+               return FALSE;
+ 
+       s = Stream_New(pDstData, *pDstSize);
+@@ -474,33 +716,29 @@ BOOL 
bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
+ 
+ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
+ {
+-      BITMAP_INTERLEAVED_CONTEXT* interleaved;
+-      interleaved = (BITMAP_INTERLEAVED_CONTEXT*)calloc(1, 
sizeof(BITMAP_INTERLEAVED_CONTEXT));
++      BITMAP_INTERLEAVED_CONTEXT* interleaved = NULL;
++      interleaved = (BITMAP_INTERLEAVED_CONTEXT*)_aligned_recalloc(
++          NULL, 1, sizeof(BITMAP_INTERLEAVED_CONTEXT), 32);
+ 
+       if (interleaved)
+       {
+               interleaved->TempSize = 64 * 64 * 4;
+-              interleaved->TempBuffer = 
_aligned_malloc(interleaved->TempSize, 16);
++              interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize 
* sizeof(BYTE), 16);
+ 
+               if (!interleaved->TempBuffer)
+-              {
+-                      free(interleaved);
+-                      WLog_ERR(TAG, "_aligned_malloc failed!");
+-                      return NULL;
+-              }
++                      goto fail;
+ 
+               interleaved->bts = Stream_New(NULL, interleaved->TempSize);
+ 
+               if (!interleaved->bts)
+-              {
+-                      _aligned_free(interleaved->TempBuffer);
+-                      free(interleaved);
+-                      WLog_ERR(TAG, "Stream_New failed!");
+-                      return NULL;
+-              }
++                      goto fail;
+       }
+ 
+       return interleaved;
++
++fail:
++      bitmap_interleaved_context_free(interleaved);
++      return NULL;
+ }
+ 
+ void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
+@@ -510,5 +748,5 @@ void 
bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
+ 
+       _aligned_free(interleaved->TempBuffer);
+       Stream_Free(interleaved->bts, TRUE);
+-      free(interleaved);
++      _aligned_free(interleaved);
+ }
diff --git a/meta-oe/recipes-support/freerdp/freerdp_2.6.1.bb 
b/meta-oe/recipes-support/freerdp/freerdp_2.6.1.bb
index 6d98ad36f7..85d24428d4 100644
--- a/meta-oe/recipes-support/freerdp/freerdp_2.6.1.bb
+++ b/meta-oe/recipes-support/freerdp/freerdp_2.6.1.bb
@@ -36,6 +36,7 @@ SRC_URI = 
"git://github.com/FreeRDP/FreeRDP.git;branch=stable-2.0;protocol=https
            file://CVE-2024-32040.patch \
            file://CVE-2024-32458.patch \
            file://CVE-2024-32459.patch \
+           file://CVE-2024-32460.patch \
            "
 
 S = "${WORKDIR}/git"
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#123767): 
https://lists.openembedded.org/g/openembedded-devel/message/123767
Mute This Topic: https://lists.openembedded.org/mt/117414251/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to