From 1179d6b737b59024e70a0b223652656947a3047c Mon Sep 17 00:00:00 2001
From: matt335672 <30179339+matt335672@users.noreply.github.com>
Date: Wed, 15 Apr 2026 11:35:39 +0100
Subject: [PATCH] CVE-2026-41521: [V0.10] lib_framebuffer_update int overflow

An integer overflow can lead to possible heap info leak and ASLR
bypass.

(cherry picked from commit 2a94fc967465b7b569056d1607d9a98e14291515)
---
 vnc/vnc.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

--- a/vnc/vnc.c
+++ b/vnc/vnc.c
@@ -30,6 +30,7 @@
 #include <config_ac.h>
 #endif
 
+#include <limits.h>
 #include "vnc.h"
 #include "vnc_clip.h"
 #include "rfb.h"
@@ -941,6 +942,21 @@ skip_encoding(struct vnc *v, int x, int
 }
 
 /**************************************************************************//**
+ * Checks the size parameters from a framebuffer update are sane
+ * @param cx Width of update
+ * @param cy height of update
+ * @return 0 if the proposed sizes could result in overflow
+ *
+ * [MS-RDPBCGR] allows for a max desktop size of 32766 x 32766.
+ * Each pixel needs up to 4 bytes
+ */
+static int
+framebuffer_update_size_ok(int cx, int cy)
+{
+    return (cx <= 32766 && cy <= 32766 && (cx * cy) <= (INT_MAX / 4));
+}
+
+/**************************************************************************//**
  * Parses an entire framebuffer update message from the wire, and returns the
  * first matching ExtendedDesktopSize encoding if found.
  *
@@ -1001,9 +1017,14 @@ find_matching_extended_rect(struct vnc *
                 in_uint16_be(s, cy);
                 in_uint32_be(s, encoding);
 
-                if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE &&
-                        match_layout->s == NULL &&
-                        match(x, y, cx, cy))
+                if (!framebuffer_update_size_ok(cx, cy))
+                {
+                    LOG(LOG_LEVEL_ERROR,
+                        "find_matching_extended_rect: Frame buffer too large");
+                    error = 1;
+                }
+                else if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE &&
+                         match(x, y, cx, cy))
                 {
                     LOG(LOG_LEVEL_DEBUG,
                         "VNC matched ExtendedDesktopSize rectangle "
@@ -1338,7 +1359,13 @@ lib_framebuffer_update(struct vnc *v)
             in_uint16_be(s, cy);
             in_uint32_be(s, encoding);
 
-            if (encoding == RFB_ENC_RAW)
+            if (!framebuffer_update_size_ok(cx, cy))
+            {
+                LOG(LOG_LEVEL_ERROR,
+                    "lib_framebuffer_update: Frame buffer too large");
+                error = 1;
+            }
+            else if (encoding == RFB_ENC_RAW)
             {
                 need_size = cx * cy * get_bytes_per_pixel(v->server_bpp);
                 init_stream(pixel_s, need_size);
