File LibVNCServer-CVE-2026-32853.patch of Package LibVNCServer.43386

From 009008e2f4d5a54dd71f422070df3af7b3dbc931 Mon Sep 17 00:00:00 2001
From: Kazuma Matsumoto <269371721+y637F9QQ2x@users.noreply.github.com>
Date: Sun, 22 Mar 2026 20:35:49 +0100
Subject: [PATCH] libvncclient: add bounds checks to UltraZip subrectangle
 parsing

HandleUltraZipBPP() iterates over sub-rectangles using numCacheRects
(derived from the attacker-controlled rect.r.x) without validating
that the pointer stays within the decompressed data buffer. A malicious
server can set a large numCacheRects value, causing heap out-of-bounds
reads via the memcpy calls in the parsing loop.

Add bounds checks before reading the 12-byte subrect header and before
advancing the pointer by the raw pixel data size. Use uint64_t for the
raw data size calculation to prevent integer overflow on 32-bit platforms.
---
 libvncclient/ultra.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

Index: libvncserver-LibVNCServer-0.9.10/libvncclient/ultra.c
===================================================================
--- libvncserver-LibVNCServer-0.9.10.orig/libvncclient/ultra.c
+++ libvncserver-LibVNCServer-0.9.10/libvncclient/ultra.c
@@ -121,6 +121,7 @@ HandleUltraZipBPP (rfbClient* client, in
   int toRead=0;
   int inflateResult=0;
   unsigned char *ptr=NULL;
+  unsigned char *ptr_end=NULL;
   lzo_uint uncompressedBytes = ry + (rw * 65535);
   unsigned int numCacheRects = rx;
 
@@ -184,11 +185,18 @@ HandleUltraZipBPP (rfbClient* client, in
   
   /* Put the uncompressed contents of the update on the screen. */
   ptr = (unsigned char *)client->raw_buffer;
+  ptr_end = ptr + uncompressedBytes;
   for (i=0; i<numCacheRects; i++)
   {
     unsigned short sx, sy, sw, sh;
     unsigned int se;
 
+    /* subrect header: sx(2) + sy(2) + sw(2) + sh(2) + se(4) = 12 bytes */
+    if (ptr + 12 > ptr_end) {
+      rfbClientLog("UltraZip: subrect %d header exceeds decompressed data bounds\n", i);
+      return FALSE;
+    }
+
     memcpy((char *)&sx, ptr, 2); ptr += 2;
     memcpy((char *)&sy, ptr, 2); ptr += 2;
     memcpy((char *)&sw, ptr, 2); ptr += 2;
@@ -203,8 +211,13 @@ HandleUltraZipBPP (rfbClient* client, in
 
     if (se == rfbEncodingRaw)
     {
+        uint64_t rawBytes = (uint64_t)sw * sh * (BPP / 8);
+        if (rawBytes > (size_t)(ptr_end - ptr)) {
+          rfbClientLog("UltraZip: subrect %d raw data exceeds decompressed data bounds\n", i);
+          return FALSE;
+        }
         CopyRectangle(client, (unsigned char *)ptr, sx, sy, sw, sh);
-        ptr += ((sw * sh) * (BPP / 8));
+        ptr += (size_t)rawBytes;
     }
   }  
 
@@ -212,3 +225,4 @@ HandleUltraZipBPP (rfbClient* client, in
 }
 
 #undef CARDBPP
+
openSUSE Build Service is sponsored by