Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package freerdp2 for openSUSE:Factory checked in at 2026-04-25 21:36:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/freerdp2 (Old) and /work/SRC/openSUSE:Factory/.freerdp2.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "freerdp2" Sat Apr 25 21:36:43 2026 rev:11 rq:1349072 version:2.11.7 Changes: -------- --- /work/SRC/openSUSE:Factory/freerdp2/freerdp2.changes 2026-04-07 16:49:28.033925360 +0200 +++ /work/SRC/openSUSE:Factory/.freerdp2.new.11940/freerdp2.changes 2026-04-25 21:37:21.393736057 +0200 @@ -1,0 +2,23 @@ +Tue Apr 14 09:09:38 UTC 2026 - Yifan Jiang <[email protected]> + +- Update freerdp-3-macro: + + Add WINPR_ATTR_MALLOC macro from freerdp 3 +- Add patches to fix CVE issues: + + freerdp-CVE-2026-25941.patch (bsc#1258919, CVE-2026-25941) + + freerdp-CVE-2026-25942.patch (bsc#1258920, CVE-2026-25942) + + freerdp-CVE-2026-27951.patch (bsc#1258939, CVE-2026-27951) + + freerdp-CVE-2026-25997.patch (bsc#1258977, CVE-2026-25997) + + freerdp-CVE-2026-26986.patch (bsc#1258967, CVE-2026-26986) + + freerdp-CVE-2026-27015.patch (bsc#1258987, CVE-2026-27015) + + freerdp-CVE-2026-25952_25953_25954.patch (bsc#1258921, + bsc#1258923, bsc#1258924, CVE-2026-25952, CVE-2026-25953, + CVE-2026-25954) + +------------------------------------------------------------------- +Mon Apr 13 01:10:19 UTC 2026 - Yifan Jiang <[email protected]> + +- Add freerdp-fix-use-nsc_process_message.patch: + + Make the calling of nsc_process_message compatible with the fix in + freerdp-CVE-2026-31806.patch (bsc#1261848, bsc#1259653) + +------------------------------------------------------------------- New: ---- freerdp-CVE-2026-25941.patch freerdp-CVE-2026-25942.patch freerdp-CVE-2026-25952_25953_25954.patch freerdp-CVE-2026-25997.patch freerdp-CVE-2026-26986.patch freerdp-CVE-2026-27015.patch freerdp-CVE-2026-27951.patch freerdp-fix-use-nsc_process_message.patch ----------(New B)---------- New:- Add patches to fix CVE issues: + freerdp-CVE-2026-25941.patch (bsc#1258919, CVE-2026-25941) + freerdp-CVE-2026-25942.patch (bsc#1258920, CVE-2026-25942) New: + freerdp-CVE-2026-25941.patch (bsc#1258919, CVE-2026-25941) + freerdp-CVE-2026-25942.patch (bsc#1258920, CVE-2026-25942) + freerdp-CVE-2026-27951.patch (bsc#1258939, CVE-2026-27951) New: + freerdp-CVE-2026-27015.patch (bsc#1258987, CVE-2026-27015) + freerdp-CVE-2026-25952_25953_25954.patch (bsc#1258921, bsc#1258923, bsc#1258924, CVE-2026-25952, CVE-2026-25953, New: + freerdp-CVE-2026-27951.patch (bsc#1258939, CVE-2026-27951) + freerdp-CVE-2026-25997.patch (bsc#1258977, CVE-2026-25997) + freerdp-CVE-2026-26986.patch (bsc#1258967, CVE-2026-26986) New: + freerdp-CVE-2026-25997.patch (bsc#1258977, CVE-2026-25997) + freerdp-CVE-2026-26986.patch (bsc#1258967, CVE-2026-26986) + freerdp-CVE-2026-27015.patch (bsc#1258987, CVE-2026-27015) New: + freerdp-CVE-2026-26986.patch (bsc#1258967, CVE-2026-26986) + freerdp-CVE-2026-27015.patch (bsc#1258987, CVE-2026-27015) + freerdp-CVE-2026-25952_25953_25954.patch (bsc#1258921, New: + freerdp-CVE-2026-25942.patch (bsc#1258920, CVE-2026-25942) + freerdp-CVE-2026-27951.patch (bsc#1258939, CVE-2026-27951) + freerdp-CVE-2026-25997.patch (bsc#1258977, CVE-2026-25997) New: - Add freerdp-fix-use-nsc_process_message.patch: + Make the calling of nsc_process_message compatible with the fix in ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ freerdp2.spec ++++++ --- /var/tmp/diff_new_pack.wrqihv/_old 2026-04-25 21:37:22.425778221 +0200 +++ /var/tmp/diff_new_pack.wrqihv/_new 2026-04-25 21:37:22.425778221 +0200 @@ -112,10 +112,26 @@ Patch37: freerdp-CVE-2026-26955.patch # PATCH-FIX-UPSTREAM freerdp-CVE-2026-26965.patch bsc#1258985 [email protected] -- fix out-of-bounds write Patch38: freerdp-CVE-2026-26965.patch +# PATCH-FIX-UPSTREAM freerdp-fix-use-nsc_process_message.patch bsc#1259653 bsc#1261848 [email protected] -- correct usage of nsc_process_message +Patch39: freerdp-fix-use-nsc_process_message.patch # PATCH-FIX-UPSTREAM freerdp-CVE-2026-31806.patch bsc#1259653 [email protected] -- fix improper validation of server messages -Patch39: freerdp-CVE-2026-31806.patch +Patch40: freerdp-CVE-2026-31806.patch # PATCH-FIX-UPSTREAM freerdp-CVE-2026-31883_31885.patch bsc#1259679 bsc#1259686 [email protected] -- fix array bounds check in IMA-ADPCM and MS-ADPCM audio decoders -Patch40: freerdp-CVE-2026-31883_31885.patch +Patch41: freerdp-CVE-2026-31883_31885.patch +# PATCH-FIX-UPSTREAM freerdp-CVE-2026-25941.patch bsc#1258919 [email protected] -- [channels,rdpgfx] check available stream length +Patch42: freerdp-CVE-2026-25941.patch +# PATCH-FIX-UPSTREAM freerdp-CVE-2026-25942.patch bsc#1258920 [email protected] -- [client,x11] stringfiy functions for RAILS +Patch43: freerdp-CVE-2026-25942.patch +# PATCH-FIX-UPSTREAM freerdp-CVE-2026-25952_25953_25954.patch bsc#1258921, bsc#1258923, bsc#1258924 [email protected] -- [client,x11] lock appWindow +Patch44: freerdp-CVE-2026-25952_25953_25954.patch +# PATCH-FIX-UPSTREAM freerdp-CVE-2026-27951.patch bsc#1258939 [email protected] -- [allocations] fix growth of preallocated buffers +Patch45: freerdp-CVE-2026-27951.patch +# PATCH-FIX-UPSTREAM freerdp-CVE-2026-25997.patch bsc#1258977 [email protected] -- [client,X11] fix clipboard update +Patch47: freerdp-CVE-2026-25997.patch +# # PATCH-FIX-UPSTREAM freerdp-CVE-2026-26986.patch bsc#1258967 [email protected] -- [client,x11] fix xf_rail_window_common cleanup +Patch49: freerdp-CVE-2026-26986.patch +# # PATCH-FIX-UPSTREAM freerdp-CVE-2026-27015.patch bsc#1258987 [email protected] -- [utils,smartcard] check stream length on padding +Patch50: freerdp-CVE-2026-27015.patch BuildRequires: cmake >= 2.8 BuildRequires: cups-devel ++++++ freerdp-3-macro.patch ++++++ --- /var/tmp/diff_new_pack.wrqihv/_old 2026-04-25 21:37:22.489780832 +0200 +++ /var/tmp/diff_new_pack.wrqihv/_new 2026-04-25 21:37:22.501781321 +0200 @@ -44,4 +44,24 @@ #ifdef __cplusplus extern "C" { +Index: freerdp-2.11.7/winpr/include/winpr/winpr.h +=================================================================== +--- freerdp-2.11.7.orig/winpr/include/winpr/winpr.h ++++ freerdp-2.11.7/winpr/include/winpr/winpr.h +@@ -82,6 +82,15 @@ WINPR_API const char* winpr_get_build_da + WINPR_API const char* winpr_get_build_revision(void); + WINPR_API const char* winpr_get_build_config(void); + ++#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ <= 10) ++#define WINPR_ATTR_MALLOC(deallocator, ptrindex) __attribute__((malloc, warn_unused_result)) ++#elif defined(__GNUC__) ++#define WINPR_ATTR_MALLOC(deallocator, ptrindex) \ ++ __attribute__((malloc(deallocator, ptrindex), warn_unused_result)) ++#else ++#define WINPR_ATTR_MALLOC(deallocator, ptrindex) ++#endif ++ + #define WINPR_UNUSED(x) (void)(x) + + #endif /* WINPR_H */ ++++++ freerdp-CVE-2026-25941.patch ++++++ >From 2e3b77e28ac6a398897d28ba464dcc5dfab9c9e2 Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Mon, 9 Feb 2026 13:18:51 +0100 Subject: [PATCH] [channels,rdpgfx] check available stream length --- channels/rdpgfx/client/rdpgfx_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) Index: freerdp-2.11.7/channels/rdpgfx/client/rdpgfx_main.c =================================================================== --- freerdp-2.11.7.orig/channels/rdpgfx/client/rdpgfx_main.c +++ freerdp-2.11.7/channels/rdpgfx/client/rdpgfx_main.c @@ -1065,7 +1065,8 @@ static UINT rdpgfx_recv_wire_to_surface_ Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); - Stream_Seek(s, pdu.bitmapDataLength); + if (!Stream_SafeSeek(s, pdu.bitmapDataLength)) + return ERROR_INVALID_DATA; DEBUG_RDPGFX(gfx->log, "RecvWireToSurface2Pdu: surfaceId: %" PRIu16 " codecId: %s (0x%04" PRIX16 ") " "codecContextId: %" PRIu32 " pixelFormat: 0x%02" PRIX8 ++++++ freerdp-CVE-2026-25942.patch ++++++ >From 9362a0bf8dda04eedbca07d5dfaec1044e67cc6b Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Mon, 9 Feb 2026 13:39:28 +0100 Subject: [PATCH] [client,x11] stringfiy functions for RAILS --- client/X11/xf_rail.c | 68 ++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 18 deletions(-) Index: freerdp-2.11.7/client/X11/xf_rail.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_rail.c +++ freerdp-2.11.7/client/X11/xf_rail.c @@ -33,22 +33,51 @@ #define TAG CLIENT_TAG("x11") -static const char* error_code_names[] = { "RAIL_EXEC_S_OK", - "RAIL_EXEC_E_HOOK_NOT_LOADED", - "RAIL_EXEC_E_DECODE_FAILED", - "RAIL_EXEC_E_NOT_IN_ALLOWLIST", - "RAIL_EXEC_E_FILE_NOT_FOUND", - "RAIL_EXEC_E_FAIL", - "RAIL_EXEC_E_SESSION_LOCKED" }; - -#ifdef WITH_DEBUG_RAIL -static const char* movetype_names[] = { - "(invalid)", "RAIL_WMSZ_LEFT", "RAIL_WMSZ_RIGHT", - "RAIL_WMSZ_TOP", "RAIL_WMSZ_TOPLEFT", "RAIL_WMSZ_TOPRIGHT", - "RAIL_WMSZ_BOTTOM", "RAIL_WMSZ_BOTTOMLEFT", "RAIL_WMSZ_BOTTOMRIGHT", - "RAIL_WMSZ_MOVE", "RAIL_WMSZ_KEYMOVE", "RAIL_WMSZ_KEYSIZE" -}; -#endif +static const char* error_code2str(UINT32 code) +{ +#define EVCASE(x) \ + case x: \ + return #x + switch (code) + { + EVCASE(RAIL_EXEC_S_OK); + EVCASE(RAIL_EXEC_E_HOOK_NOT_LOADED); + EVCASE(RAIL_EXEC_E_DECODE_FAILED); + EVCASE(RAIL_EXEC_E_NOT_IN_ALLOWLIST); + EVCASE(RAIL_EXEC_E_FILE_NOT_FOUND); + EVCASE(RAIL_EXEC_E_FAIL); + EVCASE(RAIL_EXEC_E_SESSION_LOCKED); + default: + return "RAIL_EXEC_E_UNKNOWN"; + } +#undef EVCASE +} + +static const char* movetype2str(UINT32 code) +{ +#define EVCASE(x) \ + case x: \ + return #x + + switch (code) + { + + EVCASE(RAIL_WMSZ_LEFT); + EVCASE(RAIL_WMSZ_RIGHT); + EVCASE(RAIL_WMSZ_TOP); + EVCASE(RAIL_WMSZ_TOPLEFT); + EVCASE(RAIL_WMSZ_TOPRIGHT); + EVCASE(RAIL_WMSZ_BOTTOM); + EVCASE(RAIL_WMSZ_BOTTOMLEFT); + EVCASE(RAIL_WMSZ_BOTTOMRIGHT); + EVCASE(RAIL_WMSZ_MOVE); + EVCASE(RAIL_WMSZ_KEYMOVE); + EVCASE(RAIL_WMSZ_KEYSIZE); + default: + return "RAIL_WMSZ_INVALID"; + } +#undef EVCASE +} struct xf_rail_icon { @@ -808,8 +837,9 @@ static UINT xf_rail_server_execute_resul if (execResult->execResult != RAIL_EXEC_S_OK) { - WLog_ERR(TAG, "RAIL exec error: execResult=%s NtError=0x%X\n", - error_code_names[execResult->execResult], execResult->rawResult); + WLog_ERR(TAG, "RAIL exec error: execResult=%s [0x%08" PRIx32 "] NtError=0x%X\n", + error_code2str(execResult->execResult), execResult->execResult, + execResult->rawResult); freerdp_abort_connect(xfc->context.instance); } else ++++++ freerdp-CVE-2026-25952_25953_25954.patch ++++++ >From 1994e9844212a6dfe0ff12309fef520e888986b5 Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Mon, 9 Feb 2026 16:09:51 +0100 Subject: [PATCH] [client,x11] lock appWindow When using xf_rail_get_window lock the hash talbe until xf_rail_return_window --- client/X11/xf_event.c | 47 +++++++++++++++++++++++------------ client/X11/xf_graphics.c | 10 +++++--- client/X11/xf_rail.c | 53 ++++++++++++++++++++++++++++------------ client/X11/xf_rail.h | 4 +++ client/X11/xf_window.c | 6 +++++ client/X11/xf_window.h | 4 +++ 6 files changed, 89 insertions(+), 35 deletions(-) Index: freerdp-2.11.7/client/X11/xf_event.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_event.c +++ freerdp-2.11.7/client/X11/xf_event.c @@ -388,8 +388,10 @@ BOOL xf_generic_MotionNotify(xfContext* if (app) { /* make sure window exists */ - if (!xf_AppWindowFromX11Window(xfc, window)) - return TRUE; + xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, window); + xf_rail_return_window(appWindow); + if (!appWindow) + return TRUE; /* Translate to desktop coordinates */ XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y, @@ -465,7 +467,9 @@ BOOL xf_generic_ButtonEvent(xfContext* x if (app) { /* make sure window exists */ - if (!xf_AppWindowFromX11Window(xfc, window)) + xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, window); + xf_rail_return_window(appWindow); + if (!appWindow) return TRUE; /* Translate to desktop coordinates */ @@ -577,6 +581,7 @@ static BOOL xf_event_FocusIn(xfContext* { xf_rail_adjust_position(xfc, appWindow); } + xf_rail_return_window(appWindow); } xf_keyboard_focus_in(xfc); @@ -627,11 +632,12 @@ static BOOL xf_event_ClientMessage(xfCon appWindow = xf_AppWindowFromX11Window(xfc, event->window); if (appWindow) - { + { xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_CLOSE); - } + } - return TRUE; + xf_rail_return_window(appWindow); + return TRUE; } else { @@ -665,6 +671,7 @@ static BOOL xf_event_EnterNotify(xfConte /* keep track of which window has focus so that we can apply pointer updates */ xfc->appWindow = appWindow; + xf_rail_return_window(appWindow); } return TRUE; @@ -684,6 +691,7 @@ static BOOL xf_event_LeaveNotify(xfConte /* keep track of which window has focus so that we can apply pointer updates */ if (xfc->appWindow == appWindow) xfc->appWindow = NULL; + xf_rail_return_window(appWindow); } return TRUE; } @@ -774,6 +782,7 @@ static BOOL xf_event_ConfigureNotify(xfC xf_rail_adjust_position(xfc, appWindow); } } + xf_rail_return_window(appWindow); } return xf_pointer_update_scale(xfc); } @@ -798,6 +807,7 @@ static BOOL xf_event_MapNotify(xfContext // xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); appWindow->is_mapped = TRUE; } + xf_rail_return_window(appWindow); } return TRUE; @@ -813,8 +823,7 @@ static BOOL xf_event_UnmapNotify(xfConte xf_keyboard_release_all_keypress(xfc); if (!app) - gdi_send_suppress_output(xfc->context.gdi, TRUE); - else + return gdi_send_suppress_output(xfc->context.gdi, TRUE); { appWindow = xf_AppWindowFromX11Window(xfc, event->window); @@ -822,6 +831,7 @@ static BOOL xf_event_UnmapNotify(xfConte { appWindow->is_mapped = FALSE; } + xf_rail_return_window(appWindow); } return TRUE; @@ -856,7 +866,7 @@ static BOOL xf_event_PropertyNotify(xfCo appWindow = xf_AppWindowFromX11Window(xfc, event->window); if (!appWindow) - return TRUE; + goto fail; } if ((Atom)event->atom == xfc->_NET_WM_STATE) @@ -950,6 +960,9 @@ static BOOL xf_event_PropertyNotify(xfCo } else if (minimizedChanged) gdi_send_suppress_output(xfc->context.gdi, minimized); + + fail: + xf_rail_return_window(appWindow); } return TRUE; Index: freerdp-2.11.7/client/X11/xf_graphics.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_graphics.c +++ freerdp-2.11.7/client/X11/xf_graphics.c @@ -371,12 +371,14 @@ static Window xf_Pointer_get_window(xfCo } if (xfc->remote_app) { + Window w = 0; + HashTable_Lock(xfc->railWindows); if (!xfc->appWindow) - { WLog_WARN(TAG, "xf_Pointer: Invalid appWindow"); - return 0; - } - return xfc->appWindow->handle; + else + w = xfc->appWindow->handle; + HashTable_Unlock(xfc->railWindows); + return w; } else { Index: freerdp-2.11.7/client/X11/xf_rail.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_rail.c +++ freerdp-2.11.7/client/X11/xf_rail.c @@ -132,6 +132,7 @@ void xf_rail_send_activate(xfContext* xf activate.windowId = appWindow->windowId; activate.enabled = enabled; xfc->rail->ClientActivate(xfc->rail, &activate); + xf_rail_return_window(appWindow); } void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command) @@ -691,6 +692,7 @@ static void xf_rail_set_window_icon(xfCo static BOOL xf_rail_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const WINDOW_ICON_ORDER* windowIcon) { + BOOL rc = FALSE; xfContext* xfc = (xfContext*)context; xfAppWindow* railWindow; xfRailIcon* icon; @@ -707,23 +709,25 @@ static BOOL xf_rail_window_icon(rdpConte { WLog_WARN(TAG, "failed to get icon from cache %02X:%04X", windowIcon->iconInfo->cacheId, windowIcon->iconInfo->cacheEntry); - return FALSE; } - - if (!convert_rail_icon(windowIcon->iconInfo, icon)) + else if (!convert_rail_icon(windowIcon->iconInfo, icon)) { WLog_WARN(TAG, "failed to convert icon for window %08X", orderInfo->windowId); - return FALSE; } - - replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW); - xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon); - return TRUE; + else + { + replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW); + xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon); + rc = TRUE; + } + xf_rail_return_window(railWindow); + return rc; } static BOOL xf_rail_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const WINDOW_CACHED_ICON_ORDER* windowCachedIcon) { + BOOL rc = FALSE; xfContext* xfc = (xfContext*)context; xfAppWindow* railWindow; xfRailIcon* icon; @@ -740,12 +744,15 @@ static BOOL xf_rail_window_cached_icon(r { WLog_WARN(TAG, "failed to get icon from cache %02X:%04X", windowCachedIcon->cachedIcon.cacheId, windowCachedIcon->cachedIcon.cacheEntry); - return FALSE; } - - replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW); - xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon); - return TRUE; + else + { + replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW); + xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon); + rc = TRUE; + } + xf_rail_return_window(railWindow); + return rc; } static BOOL xf_rail_notify_icon_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, @@ -1046,6 +1053,7 @@ static UINT xf_rail_server_local_move_si else xf_EndLocalMoveSize(xfc, appWindow); + xf_rail_return_window(appWindow); return CHANNEL_RC_OK; } @@ -1067,6 +1075,7 @@ static UINT xf_rail_server_min_max_info( minMaxInfo->minTrackHeight, minMaxInfo->maxTrackWidth, minMaxInfo->maxTrackHeight); } + xf_rail_return_window(appWindow); return CHANNEL_RC_OK; } @@ -1224,7 +1233,20 @@ xfAppWindow* xf_rail_get_window(xfContex return NULL; if (!xfc->railWindows) - return FALSE; + return NULL; + + HashTable_Lock(xfc->railWindows); + xfAppWindow* window = HashTable_GetItemValue(xfc->railWindows, &id); + if (!window) + HashTable_Unlock(xfc->railWindows); + + return window; +} + +void xf_rail_return_window(xfAppWindow* window) +{ + if (!window) + return; - return HashTable_GetItemValue(xfc->railWindows, &id); + HashTable_Unlock(window->xfc->railWindows); } Index: freerdp-2.11.7/client/X11/xf_rail.h =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_rail.h +++ freerdp-2.11.7/client/X11/xf_rail.h @@ -24,6 +24,7 @@ #include "xfreerdp.h" #include <freerdp/client/rail.h> +#include <winpr/winpr.h> void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom); void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command); @@ -35,6 +36,9 @@ void xf_rail_disable_remoteapp_mode(xfCo xfAppWindow* xf_rail_add_window(xfContext* xfc, UINT64 id, UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 surfaceId); +void xf_rail_return_window(xfAppWindow* window); + +WINPR_ATTR_MALLOC(xf_rail_return_window, 1) xfAppWindow* xf_rail_get_window(xfContext* xfc, UINT64 id); BOOL xf_rail_del_window(xfContext* xfc, UINT64 id); Index: freerdp-2.11.7/client/X11/xf_window.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_window.c +++ freerdp-2.11.7/client/X11/xf_window.c @@ -1122,6 +1122,7 @@ xfAppWindow* xf_AppWindowFromX11Window(x int count; ULONG_PTR* pKeys = NULL; xfAppWindow* appWindow; + HashTable_Lock(xfc->railWindows); count = HashTable_GetKeys(xfc->railWindows, &pKeys); for (index = 0; index < count; index++) @@ -1129,15 +1130,18 @@ xfAppWindow* xf_AppWindowFromX11Window(x appWindow = xf_rail_get_window(xfc, *(UINT64*)pKeys[index]); if (!appWindow) + HashTable_Unlock(xfc->railWindows); return NULL; if (appWindow->handle == wnd) { + HashTable_Unlock(xfc->railWindows); free(pKeys); return appWindow; } } + HashTable_Unlock(xfc->railWindows); free(pKeys); return NULL; } Index: freerdp-2.11.7/client/X11/xf_window.h =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_window.h +++ freerdp-2.11.7/client/X11/xf_window.h @@ -23,6 +23,7 @@ #include <X11/Xlib.h> #include <freerdp/freerdp.h> +#include <winpr/winpr.h> typedef struct xf_app_window xfAppWindow; @@ -187,6 +188,9 @@ void xf_SetWindowMinMaxInfo(xfContext* x int maxTrackWidth, int maxTrackHeight); void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y); void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow); +void xf_rail_return_window(xfAppWindow* window); + +WINPR_ATTR_MALLOC(xf_rail_return_window, 1); xfAppWindow* xf_AppWindowFromX11Window(xfContext* xfc, Window wnd); #endif /* FREERDP_CLIENT_X11_WINDOW_H */ Index: freerdp-2.11.7/winpr/include/winpr/collections.h =================================================================== --- freerdp-2.11.7.orig/winpr/include/winpr/collections.h +++ freerdp-2.11.7/winpr/include/winpr/collections.h @@ -374,6 +374,9 @@ extern "C" WINPR_API wHashTable* HashTable_New(BOOL synchronized); WINPR_API void HashTable_Free(wHashTable* table); + WINPR_API void HashTable_Lock(wHashTable* table); + WINPR_API void HashTable_Unlock(wHashTable* table); + /* BufferPool */ struct _wBufferPoolItem Index: freerdp-2.11.7/winpr/libwinpr/utils/collections/HashTable.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/collections/HashTable.c +++ freerdp-2.11.7/winpr/libwinpr/utils/collections/HashTable.c @@ -22,7 +22,7 @@ #endif #include <winpr/crt.h> - +#include <winpr/assert.h> #include <winpr/collections.h> /** @@ -636,3 +636,15 @@ void HashTable_Free(wHashTable* table) free(table); } } + +void HashTable_Lock(wHashTable* table) +{ + WINPR_ASSERT(table); + EnterCriticalSection(&table->lock); +} + +void HashTable_Unlock(wHashTable* table) +{ + WINPR_ASSERT(table); + LeaveCriticalSection(&table->lock); +} ++++++ freerdp-CVE-2026-25997.patch ++++++ >From 58409406afe7c2a8a71ed2dc8e22075be4f41c0c Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Mon, 9 Feb 2026 12:58:42 +0100 Subject: [PATCH] [client,X11] fix clipboard update Synchronize channel thread with RDP thread when accessing clipboard formats --- client/X11/xf_cliprdr.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) Index: freerdp-2.11.7/client/X11/xf_cliprdr.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_cliprdr.c +++ freerdp-2.11.7/client/X11/xf_cliprdr.c @@ -577,7 +577,11 @@ static BOOL xf_clipboard_changed(xfClipb static void xf_clipboard_formats_free(xfClipboard* clipboard) { + /* Synchronize RDP/X11 thread with channel thread */ + xf_lock_x11(clipboard->xfc); xf_cliprdr_free_formats(clipboard->lastSentFormats, clipboard->lastSentNumFormats); + xf_unlock_x11(clipboard->xfc); + clipboard->lastSentFormats = NULL; clipboard->lastSentNumFormats = 0; } @@ -1254,15 +1258,16 @@ static UINT xf_cliprdr_monitor_ready(Cli const CLIPRDR_MONITOR_READY* monitorReady) { xfClipboard* clipboard = (xfClipboard*)context->custom; - UINT ret; WINPR_UNUSED(monitorReady); - if ((ret = xf_cliprdr_send_client_capabilities(clipboard)) != CHANNEL_RC_OK) + const UINT ret = xf_cliprdr_send_client_capabilities(clipboard); + if (ret != CHANNEL_RC_OK) return ret; - if ((ret = xf_cliprdr_send_client_format_list(clipboard)) != CHANNEL_RC_OK) - return ret; + const UINT ret2 = xf_cliprdr_send_client_format_list(clipboard); + if (ret2 != CHANNEL_RC_OK) + return ret2; clipboard->sync = TRUE; return CHANNEL_RC_OK; ++++++ freerdp-CVE-2026-26986.patch ++++++ >From b4f0f0a18fe53aa8d47d062f91471f4e9c5e0d51 Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Mon, 9 Feb 2026 15:50:19 +0100 Subject: [PATCH] [client,x11] fix xf_rail_window_common cleanup leave the appWindow for later cleanup. --- client/X11/xf_rail.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) Index: FreeRDP-3.10.3/client/X11/xf_rail.c =================================================================== --- FreeRDP-3.10.3.orig/client/X11/xf_rail.c +++ FreeRDP-3.10.3/client/X11/xf_rail.c @@ -338,11 +338,10 @@ static void window_state_log_style_int(w static BOOL xf_rail_window_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, const WINDOW_STATE_ORDER* windowState) { - xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*)context; UINT32 fieldFlags = orderInfo->fieldFlags; BOOL position_or_size_updated = FALSE; - appWindow = xf_rail_get_window(xfc, orderInfo->windowId); + xfAppWindow* appWindow = xf_rail_get_window(xfc, orderInfo->windowId); if (fieldFlags & WINDOW_ORDER_STATE_NEW) { @@ -393,10 +392,7 @@ static BOOL xf_rail_window_common(rdpCon } if (!appWindow->title) - { - free(appWindow); return FALSE; - } xf_AppWindowInit(xfc, appWindow); } ++++++ freerdp-CVE-2026-27015.patch ++++++ >From 65d59d3b3c2f630f2ea862687ecf5f95f8115244 Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Sun, 15 Feb 2026 09:15:20 +0100 Subject: [PATCH] [utils,smartcard] check stream length on padding When reading optional padding in smartcard channel check if padding is actually there. --- libfreerdp/utils/smartcard_operations.c | 3 ++- libfreerdp/utils/smartcard_pack.c | 32 ++++++++++++++----------- 2 files changed, 20 insertions(+), 15 deletions(-) Index: freerdp-2.11.7/channels/smartcard/client/smartcard_operations.c =================================================================== --- freerdp-2.11.7.orig/channels/smartcard/client/smartcard_operations.c +++ freerdp-2.11.7/channels/smartcard/client/smartcard_operations.c @@ -2388,8 +2388,8 @@ LONG smartcard_irp_device_control_decode (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT)) { offset = (RDPDR_DEVICE_IO_REQUEST_LENGTH + RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH); - smartcard_unpack_read_size_align(smartcard, irp->input, - Stream_GetPosition(irp->input) - offset, 8); + if (smartcard_unpack_read_size_align(smartcard, irp->input, Stream_GetPosition(irp->input) - offset, 8) < 0) + return STATUS_INVALID_PARAMETER; } if (Stream_GetPosition(irp->input) < Stream_Length(irp->input)) Index: freerdp-2.11.7/channels/smartcard/client/smartcard_pack.c =================================================================== --- freerdp-2.11.7.orig/channels/smartcard/client/smartcard_pack.c +++ freerdp-2.11.7/channels/smartcard/client/smartcard_pack.c @@ -185,6 +185,11 @@ static LONG smartcard_ndr_read_ex(wStrea return SCARD_E_NO_MEMORY; Stream_Read(s, r, len); const LONG pad = smartcard_unpack_read_size_align(NULL, s, len, 4); + if (pad < 0) + { + free(r); + return STATUS_INVALID_PARAMETER; + } len += (size_t)pad; *data = r; if (plen) @@ -1671,14 +1676,15 @@ void smartcard_pack_private_type_header( LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size, UINT32 alignment) { - size_t pad; WINPR_UNUSED(smartcard); - pad = size; - size = (size + alignment - 1) & ~(alignment - 1); - pad = size - pad; + const size_t padsize = (size + alignment - 1) & ~(alignment - 1); + const size_t pad = padsize - size; - if (pad) - Stream_Seek(s, pad); + if (pad > 0) + { + if (!Stream_SafeSeek(s, pad)) + return -1; + } return (LONG)pad; } @@ -1686,11 +1692,9 @@ LONG smartcard_unpack_read_size_align(SM LONG smartcard_pack_write_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size, UINT32 alignment) { - size_t pad; WINPR_UNUSED(smartcard); - pad = size; - size = (size + alignment - 1) & ~(alignment - 1); - pad = size - pad; + const size_t padsize = (size + alignment - 1) & ~(alignment - 1); + const size_t pad = padsize - size; if (pad) { @@ -3030,7 +3034,8 @@ LONG smartcard_unpack_transmit_call(SMAR call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST)); pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)]; Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes); - smartcard_unpack_read_size_align(smartcard, s, ioSendPci.cbExtraBytes, 4); + if (smartcard_unpack_read_size_align(smartcard, s, ioSendPci.cbExtraBytes, 4) < 0) + return STATUS_INVALID_PARAMETER; } else { @@ -3130,7 +3135,8 @@ LONG smartcard_unpack_transmit_call(SMAR (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST)); pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)]; Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes); - smartcard_unpack_read_size_align(smartcard, s, ioRecvPci.cbExtraBytes, 4); + if (smartcard_unpack_read_size_align(smartcard, s, ioRecvPci.cbExtraBytes, 4) < 0) + return STATUS_INVALID_PARAMETER; } else { ++++++ freerdp-CVE-2026-27951.patch ++++++ >From 118afc0b954ba9d5632b7836ad24e454555ed113 Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Tue, 17 Feb 2026 12:05:42 +0100 Subject: [PATCH] [allocations] fix growth of preallocated buffers * Replace * 2 with * sizeof(WCHAR) for string usages * Grow streams and other buffers reasonably, e.g. add 128 elements per try and check for possible overflows * Add constant postfix to force them to 64bit --- channels/drive/client/drive_file.c | 2 +- channels/remdesk/common/remdesk_common.c | 2 +- channels/remdesk/server/remdesk_main.c | 4 +- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 4 +- channels/tsmf/client/tsmf_media.c | 2 +- .../urbdrc/client/libusb/libusb_udevice.c | 4 +- .../freeRDPCore/src/main/cpp/android_event.c | 14 +++- client/Windows/wf_cliprdr.c | 11 ++- client/X11/xf_event.c | 6 +- libfreerdp/core/gcc.c | 3 +- libfreerdp/core/orders.c | 2 +- libfreerdp/core/proxy.c | 2 +- libfreerdp/crypto/base64.c | 2 +- winpr/libwinpr/clipboard/synthetic_file.c | 2 +- winpr/libwinpr/crt/buffer.c | 2 +- winpr/libwinpr/environment/environment.c | 77 ++++++++++--------- winpr/libwinpr/file/file.c | 2 +- winpr/libwinpr/ncrypt/ncrypt.c | 4 +- winpr/libwinpr/ncrypt/ncrypt_pkcs11.c | 7 +- .../libwinpr/path/include/PathAllocCombine.h | 6 +- winpr/libwinpr/sspi/NTLM/ntlm_message.c | 4 +- winpr/libwinpr/utils/collections/BufferPool.c | 15 +++- .../libwinpr/utils/collections/MessageQueue.c | 19 +++-- winpr/libwinpr/utils/collections/ObjectPool.c | 15 ++-- winpr/libwinpr/utils/collections/PubSub.c | 16 ++-- winpr/libwinpr/utils/collections/Stack.c | 10 ++- winpr/libwinpr/utils/stream.c | 15 ++-- winpr/tools/makecert/makecert.c | 5 +- 28 files changed, 153 insertions(+), 104 deletions(-) Index: freerdp-2.11.7/channels/drive/client/drive_file.c =================================================================== --- freerdp-2.11.7.orig/channels/drive/client/drive_file.c +++ freerdp-2.11.7/channels/drive/client/drive_file.c @@ -808,7 +808,7 @@ BOOL drive_file_query_directory(DRIVE_FI else if (!FindNextFileW(file->find_handle, &file->find_data)) goto out_fail; - length = _wcslen(file->find_data.cFileName) * 2; + length = _wcslen(file->find_data.cFileName) * sizeof(WCHAR); switch (FsInformationClass) { Index: freerdp-2.11.7/channels/remdesk/server/remdesk_main.c =================================================================== --- freerdp-2.11.7.orig/channels/remdesk/server/remdesk_main.c +++ freerdp-2.11.7/channels/remdesk/server/remdesk_main.c @@ -294,7 +294,7 @@ static UINT remdesk_recv_ctl_remote_cont return ERROR_INVALID_DATA; cchStringW++; - cbRaConnectionStringW = cchStringW * 2; + cbRaConnectionStringW = cchStringW * sizeof(WCHAR); pdu.raConnectionString = NULL; status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW, cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); @@ -346,7 +346,7 @@ static UINT remdesk_recv_ctl_authenticat return ERROR_INVALID_DATA; cchStringW++; - cbRaConnectionStringW = cchStringW * 2; + cbRaConnectionStringW = cchStringW * sizeof(WCHAR); pStringW += cchStringW; expertBlobW = pStringW; cchStringW = 0; @@ -361,7 +361,7 @@ static UINT remdesk_recv_ctl_authenticat return ERROR_INVALID_DATA; cchStringW++; - cbExpertBlobW = cchStringW * 2; + cbExpertBlobW = cchStringW * sizeof(WCHAR); pdu.raConnectionString = NULL; status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW, cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); Index: freerdp-2.11.7/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c =================================================================== --- freerdp-2.11.7.orig/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ freerdp-2.11.7/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -461,12 +461,12 @@ static BOOL tsmf_ffmpeg_decode_audio(ITS if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE) { BYTE* tmp_data; - tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2 + 16); + tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2ull + 16ull); if (!tmp_data) return FALSE; - mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16; + mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2ull + 16ull; mdecoder->decoded_data = tmp_data; dst = (BYTE*)(((uintptr_t)mdecoder->decoded_data + 15) & ~0x0F); Index: freerdp-2.11.7/channels/tsmf/client/tsmf_media.c =================================================================== --- freerdp-2.11.7.orig/channels/tsmf/client/tsmf_media.c +++ freerdp-2.11.7/channels/tsmf/client/tsmf_media.c @@ -398,7 +398,7 @@ TSMF_PRESENTATION* tsmf_presentation_fin UINT32 index; UINT32 count; BOOL found = FALSE; - char guid_str[GUID_SIZE * 2 + 1]; + char guid_str[GUID_SIZE * 2ull + 1]; TSMF_PRESENTATION* presentation; ArrayList_Lock(presentation_list); count = ArrayList_Count(presentation_list); Index: freerdp-2.11.7/channels/urbdrc/client/libusb/libusb_udevice.c =================================================================== --- freerdp-2.11.7.orig/channels/urbdrc/client/libusb/libusb_udevice.c +++ freerdp-2.11.7/channels/urbdrc/client/libusb/libusb_udevice.c @@ -889,10 +889,10 @@ static UINT32 libusb_udev_control_query_ * So also check the string length returned as server side does * not honor strings with multi '\0' characters well. */ - const size_t rchar = _wcsnlen((WCHAR*)&data[2], sizeof(data) / 2); + const size_t rchar = _wcsnlen((WCHAR*)&data[2], sizeof(data) / sizeof(WCHAR)); len = MIN((BYTE)ret, slen); len = MIN(len, inSize); - len = MIN(len, rchar * 2 + sizeof(WCHAR)); + len = MIN(len, rchar * sizeof(WCHAR) + sizeof(WCHAR)); memcpy(Buffer, &data[2], len); /* Just as above, the returned WCHAR string should be '\0' Index: freerdp-2.11.7/client/Windows/wf_cliprdr.c =================================================================== --- freerdp-2.11.7.orig/client/Windows/wf_cliprdr.c +++ freerdp-2.11.7/client/Windows/wf_cliprdr.c @@ -1140,10 +1140,13 @@ static void map_ensure_capacity(wfClipbo if (clipboard->map_size >= clipboard->map_capacity) { - size_t new_size; - formatMapping* new_map; - new_size = clipboard->map_capacity * 2; - new_map = + size_t new_size = clipboard->map_capacity; + do + { + WINPR_ASSERT(new_size <= SIZE_MAX - 128ull); + new_size += 128ull; + } while (new_size <= clipboard->map_size); + formatMapping* new_map = (formatMapping*)realloc(clipboard->format_mappings, sizeof(formatMapping) * new_size); if (!new_map) Index: freerdp-2.11.7/client/X11/xf_event.c =================================================================== --- freerdp-2.11.7.orig/client/X11/xf_event.c +++ freerdp-2.11.7/client/X11/xf_event.c @@ -743,9 +743,8 @@ static BOOL xf_event_ConfigureNotify(xfC if (settings->DynamicResolutionUpdate) { - int alignedWidth, alignedHeight; - alignedWidth = (xfc->window->width / 2) * 2; - alignedHeight = (xfc->window->height / 2) * 2; + const int alignedWidth = (xfc->window->width / 2) * 2; + const int alignedHeight = (xfc->window->height / 2) * 2; /* ask the server to resize using the display channel */ xf_disp_handle_configureNotify(xfc, alignedWidth, alignedHeight); } Index: freerdp-2.11.7/libfreerdp/core/gcc.c =================================================================== --- freerdp-2.11.7.orig/libfreerdp/core/gcc.c +++ freerdp-2.11.7/libfreerdp/core/gcc.c @@ -1645,7 +1645,8 @@ BOOL gcc_read_server_network_data(wStrea BOOL gcc_write_server_network_data(wStream* s, rdpMcs* mcs) { UINT32 i; - int payloadLen = 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 : 0); + const size_t payloadLen = + 8ull + mcs->channelCount * 2ull + (mcs->channelCount % 2 == 1 ? 2ull : 0ull); if (!Stream_EnsureRemainingCapacity(s, payloadLen + 4)) return FALSE; Index: freerdp-2.11.7/libfreerdp/core/orders.c =================================================================== --- freerdp-2.11.7.orig/libfreerdp/core/orders.c +++ freerdp-2.11.7/libfreerdp/core/orders.c @@ -3003,7 +3003,7 @@ int update_approximate_create_offscreen_ const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) { const OFFSCREEN_DELETE_LIST* deleteList = &(create_offscreen_bitmap->deleteList); - return 32 + deleteList->cIndices * 2; + return 32ull + deleteList->cIndices * 2ull; } BOOL update_write_create_offscreen_bitmap_order( wStream* s, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) Index: freerdp-2.11.7/winpr/libwinpr/crt/buffer.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/crt/buffer.c +++ freerdp-2.11.7/winpr/libwinpr/crt/buffer.c @@ -41,7 +41,7 @@ errno_t memmove_s(void* dest, size_t num errno_t wmemmove_s(WCHAR* dest, size_t numberOfElements, const WCHAR* src, size_t count) { - if (count * 2 > numberOfElements) + if (count * sizeof(WCHAR) > numberOfElements) return -1; memmove(dest, src, count * 2); Index: freerdp-2.11.7/winpr/libwinpr/environment/environment.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/environment/environment.c +++ freerdp-2.11.7/winpr/libwinpr/environment/environment.c @@ -29,6 +29,11 @@ #include <winpr/environment.h> +#include "../log.h" + +#define TAG WINPR_TAG("environment") + + #ifndef _WIN32 #define stricmp strcasecmp @@ -223,32 +228,36 @@ extern char** environ; LPCH GetEnvironmentStringsA(VOID) { #if !defined(_UWP) - char* p; size_t offset; - size_t length; - char** envp; - DWORD cchEnvironmentBlock; - LPCH lpszEnvironmentBlock; - offset = 0; - envp = environ; + char** envp = environ; + const size_t blocksize = 128; + size_t cchEnvironmentBlock = blocksize; + LPCH lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR)); - cchEnvironmentBlock = 128; - lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR)); if (!lpszEnvironmentBlock) return NULL; while (*envp) { - length = strlen(*envp); + const size_t length = strlen(*envp); + const size_t required = offset + length + 8ull; + if (required > UINT32_MAX) + { + WLog_ERR(TAG, "Environment block too large: %" PRIuz, required); + free(lpszEnvironmentBlock); + return NULL; + } - while ((offset + length + 8) > cchEnvironmentBlock) + if (required > cchEnvironmentBlock) { - DWORD new_size; - LPCH new_blk; + size_t new_size = cchEnvironmentBlock; + do + { + new_size += blocksize; + } while (new_size <= required); + LPCH new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size * sizeof(CHAR)); - new_size = cchEnvironmentBlock * 2; - new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size * sizeof(CHAR)); if (!new_blk) { free(lpszEnvironmentBlock); @@ -259,12 +268,12 @@ LPCH GetEnvironmentStringsA(VOID) cchEnvironmentBlock = new_size; } - p = &(lpszEnvironmentBlock[offset]); + char* p = &(lpszEnvironmentBlock[offset]); CopyMemory(p, *envp, length * sizeof(CHAR)); p[length] = '\0'; - offset += (length + 1); + offset += (length + 1ull); envp++; } Index: freerdp-2.11.7/winpr/libwinpr/file/file.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/file/file.c +++ freerdp-2.11.7/winpr/libwinpr/file/file.c @@ -1246,7 +1246,7 @@ DWORD GetFullPathNameA(LPCSTR lpFileName free(lpFileNameW); free(lpBufferW); - return dwStatus * 2; + return WINPR_ASSERTING_INT_CAST(DWORD, dwStatus * sizeof(WCHAR)); } BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, Index: freerdp-2.11.7/winpr/libwinpr/sspi/NTLM/ntlm_message.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ freerdp-2.11.7/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -1230,11 +1230,11 @@ SECURITY_STATUS ntlm_write_AuthenticateM if (credentials->identity.DomainLength > 0) { message->NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; - message->DomainName.Len = (UINT16)credentials->identity.DomainLength * 2; + message->DomainName.Len = (UINT16)credentials->identity.DomainLength * sizeof(WCHAR); message->DomainName.Buffer = (BYTE*)credentials->identity.Domain; } - message->UserName.Len = (UINT16)credentials->identity.UserLength * 2; + message->UserName.Len = (UINT16)credentials->identity.UserLength * sizeof(WCHAR); message->UserName.Buffer = (BYTE*)credentials->identity.User; message->LmChallengeResponse.Len = (UINT16)context->LmChallengeResponse.cbBuffer; message->LmChallengeResponse.Buffer = (BYTE*)context->LmChallengeResponse.pvBuffer; Index: freerdp-2.11.7/winpr/libwinpr/utils/collections/BufferPool.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/collections/BufferPool.c +++ freerdp-2.11.7/winpr/libwinpr/utils/collections/BufferPool.c @@ -68,9 +68,20 @@ static BOOL BufferPool_ShiftUsed(wBuffer { if (count > 0) { - if (pool->uSize + count > pool->uCapacity) + const SSIZE_T required = pool->uSize + count; + // check for overflow + if ((required < count) || (required < pool->uSize)) + return FALSE; + + if (required > pool->uCapacity) { - int newUCapacity = pool->uCapacity * 2; + SSIZE_T newUCapacity = pool->uCapacity; + do + { + if (newUCapacity > SIZE_MAX - 128ull) + return FALSE; + newUCapacity += 128ull; + } while (newUCapacity <= required); wBufferPoolItem* newUArray = (wBufferPoolItem*)realloc(pool->uArray, sizeof(wBufferPoolItem) * newUCapacity); if (!newUArray) Index: freerdp-2.11.7/winpr/libwinpr/utils/collections/ObjectPool.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/collections/ObjectPool.c +++ freerdp-2.11.7/winpr/libwinpr/utils/collections/ObjectPool.c @@ -72,13 +72,18 @@ void ObjectPool_Return(wObjectPool* pool if (pool->synchronized) EnterCriticalSection(&pool->lock); - if ((pool->size + 1) >= pool->capacity) + WINPR_ASSERT(pool->size < SIZE_MAX); + const size_t required = pool->size + 1ull; + if (required >= pool->capacity) { - size_t new_cap; - void** new_arr; + size_t new_cap = pool->capacity; + do + { + WINPR_ASSERT(new_cap <= SIZE_MAX - 128ull); + new_cap += 128ull; + } while (new_cap <= required); - new_cap = pool->capacity * 2; - new_arr = (void**)realloc(pool->array, sizeof(void*) * new_cap); + void** new_arr = (void**)realloc((void*)pool->array, sizeof(void*) * new_cap); if (!new_arr) goto out; Index: freerdp-2.11.7/winpr/libwinpr/utils/collections/PubSub.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/collections/PubSub.c +++ freerdp-2.11.7/winpr/libwinpr/utils/collections/PubSub.c @@ -78,13 +78,19 @@ void PubSub_AddEventTypes(wPubSub* pubSu if (pubSub->synchronized) PubSub_Lock(pubSub); - while (pubSub->count + count >= pubSub->size) + const size_t required = pubSub->count + count; + WINPR_ASSERT((required >= pubSub->count) && (required >= count)); + + if (required >= pubSub->size) { - int new_size; - wEventType* new_event; + size_t new_size = pubSub->size; + do + { + WINPR_ASSERT(new_size <= SIZE_MAX - 128ull); + new_size += 128ull; + } while (new_size <= required); - new_size = pubSub->size * 2; - new_event = (wEventType*)realloc(pubSub->events, new_size * sizeof(wEventType)); + wEventType* new_event = (wEventType*)realloc(pubSub->events, new_size * sizeof(wEventType)); if (!new_event) return; pubSub->size = new_size; Index: freerdp-2.11.7/winpr/libwinpr/utils/collections/Stack.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/collections/Stack.c +++ freerdp-2.11.7/winpr/libwinpr/utils/collections/Stack.c @@ -125,11 +125,16 @@ void Stack_Push(wStack* stack, void* obj if (stack->synchronized) EnterCriticalSection(&stack->lock); - if ((stack->size + 1) >= stack->capacity) + WINPR_ASSERT(stack->size < SIZE_MAX); + if ((stack->size + 1ull) >= stack->capacity) { - int new_cap; void** new_arr; - new_cap = stack->capacity * 2; + size_t new_cap = stack->capacity; + do + { + WINPR_ASSERT(new_cap <= SIZE_MAX - 128ull); + new_cap += 128ull; + } while (new_cap <= stack->size + 1ull); new_arr = (void**)realloc(stack->array, sizeof(void*) * new_cap); if (!new_arr) Index: freerdp-2.11.7/winpr/libwinpr/utils/stream.c =================================================================== --- freerdp-2.11.7.orig/winpr/libwinpr/utils/stream.c +++ freerdp-2.11.7/winpr/libwinpr/utils/stream.c @@ -30,20 +30,19 @@ BOOL Stream_EnsureCapacity(wStream* s, s { if (s->capacity < size) { - size_t position; - size_t old_capacity; - size_t new_capacity; BYTE* new_buf; - old_capacity = s->capacity; - new_capacity = old_capacity; + size_t old_capacity = s->capacity; + size_t new_capacity = old_capacity; do { - new_capacity *= 2; - } while (new_capacity < size); + if (new_capacity > SIZE_MAX - 128ull) + return FALSE; + new_capacity += 128ull; + } while (new_capacity <= size); - position = Stream_GetPosition(s); + const size_t position = Stream_GetPosition(s); if (!s->isOwner) { Index: freerdp-2.11.7/winpr/tools/makecert/makecert.c =================================================================== --- freerdp-2.11.7.orig/winpr/tools/makecert/makecert.c +++ freerdp-2.11.7/winpr/tools/makecert/makecert.c @@ -77,11 +77,8 @@ static char* makecert_read_str(BIO* bio, while (offset >= length) { - size_t new_len; char* new_str; - new_len = length * 2; - if (new_len == 0) - new_len = 2048; + size_t new_len = length + 2048ull; new_str = (char*)realloc(x509_str, new_len); if (!new_str || (new_len > INT_MAX)) ++++++ freerdp-fix-use-nsc_process_message.patch ++++++ >From 169971607cece48384cb94632b829bd57336af0f Mon Sep 17 00:00:00 2001 From: Armin Novak <[email protected]> Date: Tue, 17 Feb 2026 08:38:04 +0100 Subject: [PATCH] [codec,nsc] fix use of nsc_process_message the second width/height argument should reflect the destination buffer pixel size --- libfreerdp/codec/clear.c | 10 ++++++---- libfreerdp/codec/nsc.c | 12 +++++++----- libfreerdp/gdi/gdi.c | 5 +++-- 3 files changed, 16 insertions(+), 11 deletions(-) Index: freerdp-2.11.7/libfreerdp/codec/clear.c =================================================================== --- freerdp-2.11.7.orig/libfreerdp/codec/clear.c +++ freerdp-2.11.7/libfreerdp/codec/clear.c @@ -103,7 +103,8 @@ static BOOL convert_color(BYTE* dst, UIN static BOOL clear_decompress_nscodec(NSC_CONTEXT* nsc, UINT32 width, UINT32 height, wStream* s, UINT32 bitmapDataByteCount, BYTE* pDstData, UINT32 DstFormat, - UINT32 nDstStep, UINT32 nXDstRel, UINT32 nYDstRel) + UINT32 nDstStep, UINT32 nXDstRel, UINT32 nYDstRel, + UINT32 nDstWidth, UINT32 nDstHeight) { BOOL rc; @@ -115,8 +116,8 @@ static BOOL clear_decompress_nscodec(NSC } rc = nsc_process_message(nsc, 32, width, height, Stream_Pointer(s), bitmapDataByteCount, - pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel, width, height, - FREERDP_FLIP_NONE); + pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel, nDstWidth, + nDstHeight, FREERDP_FLIP_NONE); Stream_Seek(s, bitmapDataByteCount); return rc; } @@ -547,7 +548,8 @@ static BOOL clear_decompress_subcodecs_d case 1: /* NSCodec */ if (!clear_decompress_nscodec(clear->nsc, width, height, s, bitmapDataByteCount, - pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel)) + pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel, + nDstWidth, nDstHeight)) return FALSE; break; Index: freerdp-2.11.7/libfreerdp/gdi/gdi.c =================================================================== --- freerdp-2.11.7.orig/libfreerdp/gdi/gdi.c +++ freerdp-2.11.7/libfreerdp/gdi/gdi.c @@ -1074,8 +1074,9 @@ static BOOL gdi_surface_bits(rdpContext* if (!nsc_process_message( context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, cmd->bmp.height, cmd->bmp.bitmapData, cmd->bmp.bitmapDataLength, gdi->primary_buffer, format, - gdi->stride, cmdRect.left, cmdRect.top, cmdRect.right - cmdRect.left, - cmdRect.bottom - cmdRect.top, FREERDP_FLIP_VERTICAL)) + gdi->stride, cmdRect.left, cmdRect.top, + WINPR_ASSERTING_INT_CAST(UINT32, gdi->width), + WINPR_ASSERTING_INT_CAST(UINT32, gdi->height), FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process NSCodec message"); goto out; Index: freerdp-2.11.7/libfreerdp/codec/nsc.c =================================================================== --- freerdp-2.11.7.orig/libfreerdp/codec/nsc.c +++ freerdp-2.11.7/libfreerdp/codec/nsc.c @@ -448,8 +448,17 @@ BOOL nsc_process_message(NSC_CONTEXT* co { wStream* s; BOOL ret; + + WINPR_ASSERT(context); + WINPR_ASSERT(context->priv); + if (!context || !data || !pDstData) + if (!data || !pDstData) + { + WLog_Print(context->priv->log, WLOG_ERROR, "Invalid argument: data=%p, pDstData=%p", + (const void*)data, (void*)pDstData); return FALSE; + } s = Stream_New((BYTE*)data, length);
