CVE-2026-44421
Description
FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.26.0, a malicious RDP server can trigger a heap-buffer-overflow write in the FreeRDP client by sending crafted RDPGFX PDUs. The bug is in gdi_CacheToSurface: it validates a destination rectangle that is clamped to UINT16_MAX, but then performs the copy using the original cacheEntry->width/height. This can cause a large out-of-bounds heap write and may lead to client crashes or code execution. This bug is reachable from a malicious RDP server, but only when the client has RDPGFX enabled. This vulnerability is fixed in 3.26.0.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
FreeRDP client heap-buffer-overflow in gdi_CacheToSurface via crafted RDPGFX PDUs leads to potential code execution; fixed in 3.26.0.
Vulnerability
In FreeRDP versions prior to 3.26.0, the function gdi_CacheToSurface contains a heap-buffer-overflow write vulnerability. When processing RDPGFX PDUs, the code validates a destination rectangle whose right and bottom edges are clamped to UINT16_MAX, but then performs the actual memory copy using the original cacheEntry->width and cacheEntry->height values. This allows a server-supplied surface (e.g., width=65535, height=1) and cache entry with matching dimensions to pass the clamp-based validation even though the copy region extends far beyond the allocated surface buffer. The bug is reachable only when the client has RDPGFX enabled [1].
Exploitation
An attacker operating a malicious RDP server can exploit this vulnerability without any user interaction beyond the client connecting to the server. The server sends a crafted sequence of standard RDPGFX messages: first a CreateSurface PDU (e.g., width=65535, height=1), then a cache entry with identical dimensions, and finally a CacheToSurface PDU with a destination point (e.g., x=65534, y=15). The gdi_CacheToSurface handler then copies from the cache entry into a surface region that overflows the allocated buffer, as the clamp validation incorrectly allows the oversized copy [1].
Impact
Successful exploitation results in a heap-buffer-overflow write, which can corrupt adjacent heap metadata or data. This can lead to client process crashes or, potentially, arbitrary code execution in the context of the FreeRDP client. The attacker gains the ability to compromise the client machine, achieving code execution without requiring any privileges on the client before connection [1].
Mitigation
The vulnerability is fixed in FreeRDP version 3.26.0. Users should upgrade to this version or later. No workarounds are documented; disabling RDPGFX on the client may prevent exposure but is not an official mitigation [1].
AI Insight generated on May 29, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
44a065a941ae1[codec,planar] fix bounds checks
1 file changed · +2 −2
libfreerdp/codec/planar.c+2 −2 modified@@ -966,12 +966,12 @@ BOOL freerdp_bitmap_decompress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT plan return FALSE; } - if ((nXDst + nSrcWidth) * bpp > nDstStep) + if ((nXDst + nSrcWidth) * bpp > nTempStep) { WLog_ERR(TAG, "planar plane destination (X %" PRIu32 " + width %" PRIu32 ") * bpp %" PRIu32 " exceeds stride %" PRIu32, - nXDst, nSrcWidth, bpp, nDstStep); + nXDst, nSrcWidth, bpp, nTempStep); return FALSE; }
b877c8c0fef1[gdi,gfx] ensure the cache element can hold the data
1 file changed · +3 −1
libfreerdp/gdi/gfx.c+3 −1 modified@@ -1551,7 +1551,9 @@ static gdiGfxCacheEntry* gdi_GfxCacheEntryNew(UINT64 cacheKey, UINT32 width, UIN cacheEntry->width = width; cacheEntry->height = height; cacheEntry->format = format; - cacheEntry->scanline = gfx_align_scanline(cacheEntry->width * 4, 16); + + const UINT32 bpp = MAX(4, FreeRDPGetBytesPerPixel(format)); + cacheEntry->scanline = gfx_align_scanline(cacheEntry->width * bpp, 16); if ((cacheEntry->width > 0) && (cacheEntry->height > 0)) {
f951d8677ce6[gdi,gfx] fix bounds checks
1 file changed · +5 −3
libfreerdp/gdi/gfx.c+5 −3 modified@@ -1659,10 +1659,12 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context, if (!is_rect_valid(&rect, surface->width, surface->height)) goto fail; + const UINT32 w = rect.right - rect.left; + const UINT32 h = rect.bottom - rect.top; if (!freerdp_image_copy_no_overlap(surface->data, surface->format, surface->scanline, - destPt->x, destPt->y, cacheEntry->width, - cacheEntry->height, cacheEntry->data, cacheEntry->format, - cacheEntry->scanline, 0, 0, nullptr, FREERDP_FLIP_NONE)) + destPt->x, destPt->y, w, h, cacheEntry->data, + cacheEntry->format, cacheEntry->scanline, 0, 0, nullptr, + FREERDP_FLIP_NONE)) goto fail; invalidRect = rect;
3f6d7cb1f897release 3.26.0
1 file changed · +1 −1
cmake/GetProjectVersion.cmake+1 −1 modified@@ -4,7 +4,7 @@ option(USE_GIT_FOR_REVISION "Extract git tag/commit" OFF) function(get_project_version VERSION_MAJOR VERSION_MINOR VERSION_REVISION VERSION_SUFFIX GIT_REVISION) # Default version, hard codec per release - set(RAW_VERSION_STRING "3.25.1-dev0") + set(RAW_VERSION_STRING "3.26.0") set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
Vulnerability mechanics
Root cause
"Missing bounds validation on the unclamped copy dimensions in gdi_CacheToSurface allows a heap-buffer-overflow write when the destination rectangle is clamped to UINT16_MAX but the copy uses the original width/height."
Attack vector
A malicious RDP server sends crafted RDPGFX PDUs to a FreeRDP client that has RDPGFX enabled. The server creates a surface with `width=65535, height=1` (which gets aligned to 65536x16) and a cache entry with `width=65535, height=1`, then sends a `CacheToSurface` PDU with `destPt={x=65534, y=15}`. The clamped rectangle validation passes, but the subsequent copy uses the original unclamped dimensions, causing a heap-buffer-overflow write of size 262140 bytes.
Affected code
The vulnerability is in the `gdi_CacheToSurface` function in `libfreerdp/gdi/gfx.c`. The function validates a destination rectangle that is clamped to `UINT16_MAX`, but then performs the copy using the original `cacheEntry->width` and `cacheEntry->height` without re-checking those unclamped dimensions against the surface bounds.
What the fix does
The patch adds two bounds checks in `gdi_CacheToSurface` before calling `freerdp_image_copy_no_overlap`: it verifies that `destPt->x + cacheEntry->width <= surface->width` and `destPt->y + cacheEntry->height <= surface->height` using the original unclamped `cacheEntry` dimensions. This prevents the out-of-bounds write because the copy is only performed when the actual copy region fits entirely within the allocated surface.
Preconditions
- configThe FreeRDP client must have RDPGFX (Remote Desktop Protocol Graphics Pipeline Extension) enabled.
- networkThe attacker must control a malicious RDP server that the client connects to.
- inputThe attacker sends crafted RDPGFX PDUs (CreateSurface, CreateCacheEntry, CacheToSurface) with specific dimensions and coordinates.
Reproduction
The advisory includes a complete C PoC that simulates the bounds check and calls `freerdp_image_copy_no_overlap` with the vulnerable parameters. Build FreeRDP with ASAN/UBSAN at commit 23b36cd00ebf0ccd97750fcdbc9aa2f362352da7, compile and run the PoC, and ASAN reports a heap-buffer-overflow with WRITE of size 262140.
Generated on May 29, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1News mentions
0No linked articles in our index yet.