Version in base suite: 2.10.0+dfsg1-1 Base version: freerdp2_2.10.0+dfsg1-1 Target version: freerdp2_2.11.7+dfsg1-6~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/f/freerdp2/freerdp2_2.10.0+dfsg1-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/f/freerdp2/freerdp2_2.11.7+dfsg1-6~deb12u1.dsc .clang-format | 1 CMakeLists.txt | 10 ChangeLog | 97 + channels/cliprdr/cliprdr_common.c | 2 channels/rdpdr/client/devman.c | 6 channels/rdpdr/client/irp.c | 10 channels/rdpdr/client/irp.h | 3 channels/rdpdr/client/rdpdr_capabilities.c | 159 +- channels/rdpdr/client/rdpdr_main.c | 543 +++++++--- channels/rdpdr/client/rdpdr_main.h | 49 channels/rdpdr/server/rdpdr_main.h | 7 channels/rdpecam/server/camera_device_main.c | 2 channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 297 ++++- channels/rdpsnd/client/rdpsnd_main.c | 34 channels/rdpsnd/server/rdpsnd_main.c | 2 channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 2 client/Wayland/wlf_input.c | 128 ++ client/Wayland/wlf_input.h | 3 client/Wayland/wlfreerdp.c | 64 - client/Wayland/wlfreerdp.h | 1 client/X11/xf_gdi.c | 2 client/X11/xf_gfx.c | 4 client/X11/xf_graphics.c | 8 client/X11/xf_rail.c | 4 client/common/cmdline.c | 7 client/common/cmdline.h | 1 cmake/ClangDetectTool.cmake | 48 cmake/ClangFormat.cmake | 35 cmake/ConfigOptions.cmake | 24 cmake/FindOpenSSL.cmake | 67 - debian/changelog | 147 ++ debian/control | 16 debian/patches/0001-info-Fix-incompatible-pointer-type.patch | 32 debian/patches/0002-redirection-Fix-incompatible-pointer-type.patch | 38 debian/patches/0003-redirection-Fix-incompatible-pointer-type.patch | 33 debian/patches/0004-X11-fix-pointer-integer-type-mismatch.patch | 24 debian/patches/0005-client-wayland-fix-const-correctness.patch | 22 debian/patches/0006-warnings-fix-Wincompatible-pointer-types.patch | 89 + debian/patches/0007-server-proxy-deactivate-capture-module.patch | 48 debian/patches/1000-ffmpeg7.patch | 114 ++ debian/patches/CVE-2024-32661.patch | 24 debian/patches/series | 9 debian/tests/connect | 22 debian/tests/control | 3 debian/watch | 2 include/freerdp/channels/rdpdr.h | 8 include/freerdp/settings.h | 4 libfreerdp/cache/pointer.c | 3 libfreerdp/codec/clear.c | 82 - libfreerdp/codec/color.c | 16 libfreerdp/codec/dsp_ffmpeg.c | 24 libfreerdp/codec/h264.c | 6 libfreerdp/codec/h264_ffmpeg.c | 2 libfreerdp/codec/include/bitmap.c | 119 +- libfreerdp/codec/interleaved.c | 448 ++++++-- libfreerdp/codec/ncrush.c | 143 ++ libfreerdp/codec/nsc.c | 114 +- libfreerdp/codec/nsc_encode.c | 76 - libfreerdp/codec/nsc_types.h | 1 libfreerdp/codec/planar.c | 77 + libfreerdp/codec/progressive.c | 25 libfreerdp/codec/rfx.c | 40 libfreerdp/codec/rfx_encode.c | 74 - libfreerdp/codec/xcrush.c | 14 libfreerdp/codec/zgfx.c | 97 + libfreerdp/common/settings_getters.c | 7 libfreerdp/common/settings_str.c | 1 libfreerdp/core/orders.c | 100 + libfreerdp/core/server.c | 2 libfreerdp/core/test/settings_property_lists.h | 1 libfreerdp/core/window.c | 48 libfreerdp/crypto/crypto.c | 11 libfreerdp/gdi/bitmap.c | 2 libfreerdp/gdi/gdi.c | 70 - libfreerdp/gdi/gfx.c | 70 - libfreerdp/gdi/graphics.c | 2 libfreerdp/gdi/shape.c | 2 libfreerdp/gdi/video.c | 2 libfreerdp/locale/xkb_layout_ids.c | 2 libfreerdp/primitives/prim_copy.c | 4 libfreerdp/primitives/primitives.c | 2 uwac/CMakeLists.txt | 4 uwac/include/uwac/uwac.h | 23 uwac/libuwac/uwac-input.c | 29 uwac/libuwac/uwac-window.c | 8 winpr/CMakeLists.txt | 2 winpr/include/winpr/wtypes.h.in | 3 winpr/libwinpr/credui/CMakeLists.txt | 8 winpr/libwinpr/crt/CMakeLists.txt | 2 winpr/libwinpr/crt/unicode.c | 39 winpr/libwinpr/crypto/cipher.c | 4 winpr/libwinpr/utils/collections/ArrayList.c | 17 winpr/libwinpr/utils/lodepng/lodepng.c | 14 93 files changed, 3169 insertions(+), 926 deletions(-) diff -Nru freerdp2-2.10.0+dfsg1/.clang-format freerdp2-2.11.7+dfsg1/.clang-format --- freerdp2-2.10.0+dfsg1/.clang-format 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/.clang-format 2024-04-22 09:26:59.000000000 +0000 @@ -104,7 +104,6 @@ ... Language: ObjC PointerBindsToType: false -ObjCSpaceAfterProperty: true SortIncludes: false ObjCBlockIndentWidth: 4 ObjCSpaceAfterProperty: false diff -Nru freerdp2-2.10.0+dfsg1/CMakeLists.txt freerdp2-2.11.7+dfsg1/CMakeLists.txt --- freerdp2-2.10.0+dfsg1/CMakeLists.txt 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/CMakeLists.txt 2024-04-22 09:26:59.000000000 +0000 @@ -34,9 +34,9 @@ set(FREERDP_VENDOR 1) endif() -set(CMAKE_COLOR_MAKEFILE ON) - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) +option(CMAKE_COLOR_MAKEFILE "colorful CMake makefile" ON) +option(CMAKE_VERBOSE_MAKEFILE "verbose CMake makefile" ON) +option(CMAKE_POSITION_INDEPENDENT_CODE "build with position independent code (-fPIC or -fPIE)" ON) # Include our extra modules set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) @@ -85,7 +85,7 @@ endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.10.0") +set(RAW_VERSION_STRING "2.11.7") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -225,7 +225,7 @@ if(MSVC) include(MSVCRuntime) if(NOT DEFINED MSVC_RUNTIME) - set(MSVC_RUNTIME "dynamic") + set(MSVC_RUNTIME "dynamic" CACHE STRING "MSVC runtime type [dynamic|static]") endif() if(MSVC_RUNTIME STREQUAL "static") if(BUILD_SHARED_LIBS) diff -Nru freerdp2-2.10.0+dfsg1/ChangeLog freerdp2-2.11.7+dfsg1/ChangeLog --- freerdp2-2.10.0+dfsg1/ChangeLog 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/ChangeLog 2024-04-22 09:26:59.000000000 +0000 @@ -1,6 +1,97 @@ +# 2024-04-22 Version 2.11.7 + +Noteworthy changes: +* Backported oss-fuzz fixes + +For a complete and detailed change log since the last release run: +git log 2.11.7...2.11.6 + +# 2024-04-17 Version 2.11.6 + +CVE: + CVE-2024-32041 [Low[ OutOfBound Read in zgfx_decompress_segment + CVE-2024-32039 [Moderate] Integer overflow & OutOfBound Write in clear_decompress_residual_data + CVE-2024-32040 [Low] integer underflow in nsc_rle_decode + CVE-2024-32458 [Low] OutOfBound Read in planar_skip_plane_rle + CVE-2024-32459 [Low] OutOfBound Read in ncrush_decompress + CVE-2024-32460 [Low] OutOfBound Read in interleaved_decompress + +Noteworthy changes: +* Backported #10077 + +For a complete and detailed change log since the last release run: +git log 2.11.6...2.11.5 + +# 2024-01-19 Version 2.11.5 + +Noteworthy changes: +* Fix integer overflow in progressive decoder +* Update OpenSSL API usage for compatiblility with newer versions (#9747) +* Prevent NULL dereference for single thread decoder (#9712) + +For a complete and detailed change log since the last release run: +git log 2.11.5...2.11.4 + +# 2023-12-14 Version 2.11.4 + +Notworthy changes: +* fix a typo in unicode commit (#9652) + +For a complete and detailed change log since the last release run: +git log 2.11.4...2.11.3 + +# 2023-12-14 Version 2.11.3 + +Notworthy changes: +* Disabled windows MEDIA FOUNDATION h264 decoder due to reported issues (#9469) +* Fix issues with drive redirection (#9530,9554, #9586, #9617) +* Use endian safe ICU string converter (#9631) +* Improve AAC support (#9577) +* Fix swiss german keyboard layout (#9560) +* Enable rfx-mode:image (#9428) + +For a complete and detailed change log since the last release run: +git log 2.11.3...2.11.2 + +# 2023-09-20 Version 2.11.2 + +Notworthy changes: +* Backported #9378: backported wArrayList (optional) copy on insert +* Backported #9360: backported certificate algorithm detection + +For a complete and detailed change log since the last release run: +git log 2.11.2...2.11.1 + +# 2023-09-04 Version 2.11.1 + +Notworthy changes: +* Backported #9356: Fix issues with order updates + +For a complete and detailed change log since the last release run: +git log 2.11.1..2.11.0 + +# 2023-08-28 Version 2.11.0 + +Noteworthy changes: +* Various input validation fixes +* Added various CMake options #9317 +* LibreSSL build fixes #8709 + +Fixed issues: +* Backported #9233: Big endian support +* Backported #9099: Mouse grabbing support +* Backported #6851: wayland scrolling fix +* Backported #8690: Update h264 to use new FFMPEG API +* Backported #7306: early bail from update_read_window_state_order breaks protocol +* Backported #8903: rdpecam/server: Remove wrong assertion +* Backported #8994: bounds checks for gdi/gfx rectangles +* Backported #9023: enforce rdpdr client side state checks +* Backported #6331: deactivate mouse grabbing by default +* Cherry-pick out of #9172: channels/cliprdr: Fix writing incorrect PDU type for unlock PDUs + # 2023-02-16 Version 2.10.0 -Notewhorth changes: +Noteworthy changes: * Fix android build scripts, use CMake from SDK * Fix connection negotiation with mstsc/msrdc #8426 * [ntlm]: use rfc5929 binding hash algorithm #8430 @@ -23,7 +114,7 @@ # 2022-11-16 Version 2.9.0 -Notewhorth changes: +Noteworthy changes: * Backported #8252: Support sending server redirection PDU * Backported #8406: Ensure X11 client cursor is never smaller 1x1 * Backported #8403: Fixed multiple client side input validation issues @@ -49,7 +140,7 @@ # 2022-10-12 Version 2.8.1 -Notewhorth changes: +Noteworthy changes: * Fixed CVE-2022-39282 * Fixed CVE-2022-39283 * Added missing commit for backported #8041: Remove ALAW/ULAW codecs from linux backends (unreliable) diff -Nru freerdp2-2.10.0+dfsg1/channels/cliprdr/cliprdr_common.c freerdp2-2.11.7+dfsg1/channels/cliprdr/cliprdr_common.c --- freerdp2-2.10.0+dfsg1/channels/cliprdr/cliprdr_common.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/cliprdr/cliprdr_common.c 2024-04-22 09:26:59.000000000 +0000 @@ -138,7 +138,7 @@ if (!unlockClipboardData) return NULL; - s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4); + s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4); if (!s) return NULL; diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/devman.c freerdp2-2.11.7+dfsg1/channels/rdpdr/client/devman.c --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/devman.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/devman.c 2024-04-22 09:26:59.000000000 +0000 @@ -41,6 +41,8 @@ #include "devman.h" +#define TAG CHANNELS_TAG("rdpdr.client") + static void devman_device_free(void* obj) { DEVICE* device = (DEVICE*)obj; @@ -62,7 +64,7 @@ if (!devman) { - WLog_INFO(TAG, "calloc failed!"); + WLog_Print(rdpdr->log, WLOG_INFO, "calloc failed!"); return NULL; } @@ -72,7 +74,7 @@ if (!devman->devices) { - WLog_INFO(TAG, "ListDictionary_New failed!"); + WLog_Print(rdpdr->log, WLOG_INFO, "ListDictionary_New failed!"); free(devman); return NULL; } diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/irp.c freerdp2-2.11.7+dfsg1/channels/rdpdr/client/irp.c --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/irp.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/irp.c 2024-04-22 09:26:59.000000000 +0000 @@ -76,13 +76,13 @@ return irp_free(irp); } -IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) +IRP* irp_new(DEVMAN* devman, wStream* s, wLog* log, UINT* error) { IRP* irp; DEVICE* device; UINT32 DeviceId; - if (Stream_GetRemainingLength(s) < 20) + if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20)) { if (error) *error = ERROR_INVALID_DATA; @@ -94,7 +94,7 @@ if (!device) { - WLog_WARN(TAG, "devman_get_device_by_id failed!"); + WLog_Print(log, WLOG_WARN, "devman_get_device_by_id failed!"); if (error) *error = CHANNEL_RC_OK; @@ -105,7 +105,7 @@ if (!irp) { - WLog_ERR(TAG, "_aligned_malloc failed!"); + WLog_Print(log, WLOG_ERROR, "_aligned_malloc failed!"); if (error) *error = CHANNEL_RC_NO_MEMORY; return NULL; @@ -125,7 +125,7 @@ irp->output = Stream_New(NULL, 256); if (!irp->output) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(log, WLOG_ERROR, "Stream_New failed!"); _aligned_free(irp); if (error) *error = CHANNEL_RC_NO_MEMORY; diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/irp.h freerdp2-2.11.7+dfsg1/channels/rdpdr/client/irp.h --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/irp.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/irp.h 2024-04-22 09:26:59.000000000 +0000 @@ -21,8 +21,9 @@ #ifndef FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H #define FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H +#include #include "rdpdr_main.h" -IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error); +IRP* irp_new(DEVMAN* devman, wStream* s, wLog* log, UINT* error); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H */ diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_capabilities.c freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_capabilities.c --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_capabilities.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_capabilities.c 2024-04-22 09:26:59.000000000 +0000 @@ -35,6 +35,8 @@ #include "rdpdr_main.h" #include "rdpdr_capabilities.h" +#define RDPDR_CAPABILITY_HEADER_LENGTH 8 + /* Output device redirection capability set header */ static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version) @@ -48,39 +50,59 @@ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s) { WINPR_UNUSED(rdpdr); - rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); - Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */ - Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */ - Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */ - Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ - Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */ - Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */ - Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | - RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ - Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */ - Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */ + + const UINT32 ioCode1 = rdpdr->clientIOCode1 & rdpdr->serverIOCode1; + const UINT32 ioCode2 = rdpdr->clientIOCode2 & rdpdr->serverIOCode2; + + rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH + 36, + GENERAL_CAPABILITY_VERSION_02); + Stream_Write_UINT32(s, rdpdr->clientOsType); /* osType, ignored on receipt */ + Stream_Write_UINT32(s, rdpdr->clientOsVersion); /* osVersion, unused and must be set to zero */ + Stream_Write_UINT16(s, rdpdr->clientVersionMajor); /* protocolMajorVersion, must be set to 1 */ + Stream_Write_UINT16(s, rdpdr->clientVersionMinor); /* protocolMinorVersion */ + Stream_Write_UINT32(s, ioCode1); /* ioCode1 */ + Stream_Write_UINT32(s, ioCode2); /* ioCode2, must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, rdpdr->clientExtendedPDU); /* extendedPDU */ + Stream_Write_UINT32(s, rdpdr->clientExtraFlags1); /* extraFlags1 */ Stream_Write_UINT32( - s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ + s, + rdpdr->clientExtraFlags2); /* extraFlags2, must be set to zero, reserved for future use */ + Stream_Write_UINT32( + s, rdpdr->clientSpecialTypeDeviceCap); /* SpecialTypeDeviceCap, number of special devices to + be redirected before logon */ } /* Process device direction general capability set */ -static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s, UINT16 capabilityLength) { - UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) - return ERROR_INVALID_DATA; - - Stream_Read_UINT16(s, capabilityLength); - - if (capabilityLength < 4) + if (capabilityLength != 36) + { + WLog_Print(rdpdr->log, WLOG_ERROR, + "CAP_GENERAL_TYPE::CapabilityLength expected 36, got %" PRIu32, + capabilityLength); return ERROR_INVALID_DATA; + } - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength)) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4U); + Stream_Read_UINT32(s, rdpdr->serverOsType); /* osType, ignored on receipt */ + Stream_Read_UINT32(s, rdpdr->serverOsVersion); /* osVersion, unused and must be set to zero */ + Stream_Read_UINT16(s, rdpdr->serverVersionMajor); /* protocolMajorVersion, must be set to 1 */ + Stream_Read_UINT16(s, rdpdr->serverVersionMinor); /* protocolMinorVersion */ + Stream_Read_UINT32(s, rdpdr->serverIOCode1); /* ioCode1 */ + Stream_Read_UINT32( + s, rdpdr->serverIOCode2); /* ioCode2, must be set to zero, reserved for future use */ + Stream_Read_UINT32(s, rdpdr->serverExtendedPDU); /* extendedPDU */ + Stream_Read_UINT32(s, rdpdr->serverExtraFlags1); /* extraFlags1 */ + Stream_Read_UINT32( + s, + rdpdr->serverExtraFlags2); /* extraFlags2, must be set to zero, reserved for future use */ + Stream_Read_UINT32( + s, rdpdr->serverSpecialTypeDeviceCap); /* SpecialTypeDeviceCap, number of special devices to + be redirected before logon */ return CHANNEL_RC_OK; } @@ -92,23 +114,14 @@ } /* Process printer direction capability set */ -static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s, UINT16 capabilityLength) { - UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength)) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, capabilityLength); - - if (capabilityLength < 4) - return ERROR_INVALID_DATA; - - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) - return ERROR_INVALID_DATA; - - Stream_Seek(s, capabilityLength - 4U); + Stream_Seek(s, capabilityLength); return CHANNEL_RC_OK; } @@ -120,23 +133,14 @@ } /* Process port redirection capability set */ -static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s, UINT16 capabilityLength) { - UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength)) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, capabilityLength); - - if (capabilityLength < 4U) - return ERROR_INVALID_DATA; - - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) - return ERROR_INVALID_DATA; - - Stream_Seek(s, capabilityLength - 4U); + Stream_Seek(s, capabilityLength); return CHANNEL_RC_OK; } @@ -148,23 +152,14 @@ } /* Process drive redirection capability set */ -static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s, UINT16 capabilityLength) { - UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength)) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, capabilityLength); - - if (capabilityLength < 4) - return ERROR_INVALID_DATA; - - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) - return ERROR_INVALID_DATA; - - Stream_Seek(s, capabilityLength - 4U); + Stream_Seek(s, capabilityLength); return CHANNEL_RC_OK; } @@ -176,23 +171,14 @@ } /* Process smartcard redirection capability set */ -static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s, UINT16 capabilityLength) { - UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) - return ERROR_INVALID_DATA; - - Stream_Read_UINT16(s, capabilityLength); - - if (capabilityLength < 4) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength)) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) - return ERROR_INVALID_DATA; - - Stream_Seek(s, capabilityLength - 4U); + Stream_Seek(s, capabilityLength); return CHANNEL_RC_OK; } @@ -201,12 +187,14 @@ UINT status = CHANNEL_RC_OK; UINT16 i; UINT16 numCapabilities; - UINT16 capabilityType; if (!rdpdr || !s) return CHANNEL_RC_NULL_DATA; - if (Stream_GetRemainingLength(s) < 4) + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_SERVER_CAPS); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_CLIENT_CAPS); + + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, numCapabilities); @@ -214,31 +202,44 @@ for (i = 0; i < numCapabilities; i++) { - if (Stream_GetRemainingLength(s) < sizeof(UINT16)) + UINT16 capabilityType; + UINT16 capabilityLength; + UINT32 version = 0; + + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, + 2 * sizeof(UINT16) + sizeof(UINT32))) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityType); + Stream_Read_UINT16(s, capabilityLength); + Stream_Read_UINT32(s, version); + + if (capabilityLength < 8) + { + return ERROR_INVALID_DATA; + } + capabilityLength -= 8; switch (capabilityType) { case CAP_GENERAL_TYPE: - status = rdpdr_process_general_capset(rdpdr, s); + status = rdpdr_process_general_capset(rdpdr, s, capabilityLength); break; case CAP_PRINTER_TYPE: - status = rdpdr_process_printer_capset(rdpdr, s); + status = rdpdr_process_printer_capset(rdpdr, s, capabilityLength); break; case CAP_PORT_TYPE: - status = rdpdr_process_port_capset(rdpdr, s); + status = rdpdr_process_port_capset(rdpdr, s, capabilityLength); break; case CAP_DRIVE_TYPE: - status = rdpdr_process_drive_capset(rdpdr, s); + status = rdpdr_process_drive_capset(rdpdr, s, capabilityLength); break; case CAP_SMARTCARD_TYPE: - status = rdpdr_process_smartcard_capset(rdpdr, s); + status = rdpdr_process_smartcard_capset(rdpdr, s, capabilityLength); break; default: @@ -264,7 +265,7 @@ if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_main.c freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_main.c --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_main.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_main.c 2024-04-22 09:26:59.000000000 +0000 @@ -79,12 +79,142 @@ BOOL automount; }; +static const char* rdpdr_packetid_string(UINT16 packetid) +{ + switch (packetid) + { + case PAKID_CORE_SERVER_ANNOUNCE: + return "PAKID_CORE_SERVER_ANNOUNCE"; + case PAKID_CORE_CLIENTID_CONFIRM: + return "PAKID_CORE_CLIENTID_CONFIRM"; + case PAKID_CORE_CLIENT_NAME: + return "PAKID_CORE_CLIENT_NAME"; + case PAKID_CORE_DEVICELIST_ANNOUNCE: + return "PAKID_CORE_DEVICELIST_ANNOUNCE"; + case PAKID_CORE_DEVICE_REPLY: + return "PAKID_CORE_DEVICE_REPLY"; + case PAKID_CORE_DEVICE_IOREQUEST: + return "PAKID_CORE_DEVICE_IOREQUEST"; + case PAKID_CORE_DEVICE_IOCOMPLETION: + return "PAKID_CORE_DEVICE_IOCOMPLETION"; + case PAKID_CORE_SERVER_CAPABILITY: + return "PAKID_CORE_SERVER_CAPABILITY"; + case PAKID_CORE_CLIENT_CAPABILITY: + return "PAKID_CORE_CLIENT_CAPABILITY"; + case PAKID_CORE_DEVICELIST_REMOVE: + return "PAKID_CORE_DEVICELIST_REMOVE"; + case PAKID_CORE_USER_LOGGEDON: + return "PAKID_CORE_USER_LOGGEDON"; + case PAKID_PRN_CACHE_DATA: + return "PAKID_PRN_CACHE_DATA"; + case PAKID_PRN_USING_XPS: + return "PAKID_PRN_USING_XPS"; + default: + return "UNKNOWN"; + } +} + +static const char* rdpdr_state_str(enum RDPDR_CHANNEL_STATE state) +{ + switch (state) + { + case RDPDR_CHANNEL_STATE_INITIAL: + return "RDPDR_CHANNEL_STATE_INITIAL"; + case RDPDR_CHANNEL_STATE_ANNOUNCE: + return "RDPDR_CHANNEL_STATE_ANNOUNCE"; + case RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY: + return "RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY"; + case RDPDR_CHANNEL_STATE_NAME_REQUEST: + return "RDPDR_CHANNEL_STATE_NAME_REQUEST"; + case RDPDR_CHANNEL_STATE_SERVER_CAPS: + return "RDPDR_CHANNEL_STATE_SERVER_CAPS"; + case RDPDR_CHANNEL_STATE_CLIENT_CAPS: + return "RDPDR_CHANNEL_STATE_CLIENT_CAPS"; + case RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM: + return "RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM"; + case RDPDR_CHANNEL_STATE_READY: + return "RDPDR_CHANNEL_STATE_READY"; + case RDPDR_CHANNEL_STATE_USER_LOGGEDON: + return "RDPDR_CHANNEL_STATE_USER_LOGGEDON"; + default: + return "RDPDR_CHANNEL_STATE_UNKNOWN"; + } +} + +static const char* rdpdr_device_type_string(UINT32 type) +{ + switch (type) + { + case RDPDR_DTYP_SERIAL: + return "serial"; + case RDPDR_DTYP_PRINT: + return "printer"; + case RDPDR_DTYP_FILESYSTEM: + return "drive"; + case RDPDR_DTYP_SMARTCARD: + return "smartcard"; + case RDPDR_DTYP_PARALLEL: + return "parallel"; + default: + return "UNKNOWN"; + } +} + +static const char* support_str(BOOL val) +{ + if (val) + return "supported"; + return "not found"; +} + +static const char* rdpdr_caps_pdu_str(UINT32 flag) +{ + switch (flag) + { + case RDPDR_DEVICE_REMOVE_PDUS: + return "RDPDR_USER_LOGGEDON_PDU"; + case RDPDR_CLIENT_DISPLAY_NAME_PDU: + return "RDPDR_CLIENT_DISPLAY_NAME_PDU"; + case RDPDR_USER_LOGGEDON_PDU: + return "RDPDR_USER_LOGGEDON_PDU"; + default: + return "RDPDR_UNKNONW"; + } +} + +static BOOL rdpdr_check_extended_pdu_flag(rdpdrPlugin* rdpdr, UINT32 flag) +{ + WINPR_ASSERT(rdpdr); + + const BOOL client = (rdpdr->clientExtendedPDU & flag) != 0; + const BOOL server = (rdpdr->serverExtendedPDU & flag) != 0; + + if (!client || !server) + { + WLog_Print(rdpdr->log, WLOG_WARN, "Checking ExtendedPDU::%s, client %s, server %s", + rdpdr_caps_pdu_str(flag), support_str(client), support_str(server)); + return FALSE; + } + return TRUE; +} + +BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next) +{ + WINPR_ASSERT(rdpdr); + + if (next != rdpdr->state) + WLog_Print(rdpdr->log, WLOG_DEBUG, "[RDPDR] transition from %s to %s", + rdpdr_state_str(rdpdr->state), rdpdr_state_str(next)); + rdpdr->state = next; + return TRUE; +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn); +static UINT rdpdr_try_send_device_list_announce_request(rdpdrPlugin* rdpdr); /** * Function description @@ -95,11 +225,21 @@ { UINT32 i; wStream* s; + + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(ids || (count == 0)); + + if (count == 0) + return CHANNEL_RC_OK; + + if (!rdpdr_check_extended_pdu_flag(rdpdr, RDPDR_DEVICE_REMOVE_PDUS)) + return CHANNEL_RC_OK; + s = Stream_New(NULL, count * sizeof(UINT32) + 8); if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -212,7 +352,7 @@ devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext); - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); } } @@ -261,8 +401,8 @@ rdpdr, 1, ids))) { // dont end on error, just report ? - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_remove_request failed " "with error %" PRIu32 "!", error); @@ -358,7 +498,7 @@ if (rdpdr->hotplug_wnd && !PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0)) { error = GetLastError(); - WLog_ERR(TAG, "PostMessage failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "PostMessage failed with error %" PRIu32 "", error); } return error; @@ -475,9 +615,9 @@ if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, - "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", + error); goto cleanup; } } @@ -506,7 +646,7 @@ if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_load_device_service failed!"); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } @@ -540,10 +680,11 @@ { if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", + error); } else - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); return; } @@ -556,7 +697,7 @@ if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -661,14 +802,14 @@ #ifdef __sun #include -static UINT handle_platform_mounts_sun(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_sun(wLog* log, hotplug_dev* dev_array, size_t* size) { FILE* f; struct mnttab ent; f = fopen("/etc/mnttab", "r"); if (f == NULL) { - WLog_ERR(TAG, "fopen failed!"); + WLog_Print(log, WLOG_ERROR, "fopen failed!"); return ERROR_OPEN_FAILED; } while (getmntent(f, &ent) == 0) @@ -682,7 +823,7 @@ #if defined(__FreeBSD__) || defined(__OpenBSD__) #include -static UINT handle_platform_mounts_bsd(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_bsd(wLog* log, hotplug_dev* dev_array, size_t* size) { int mntsize; size_t idx; @@ -692,7 +833,7 @@ if (!mntsize) { /* TODO: handle 'errno' */ - WLog_ERR(TAG, "getmntinfo failed!"); + WLog_Print(log, WLOG_ERROR, "getmntinfo failed!"); return ERROR_OPEN_FAILED; } for (idx = 0; idx < (size_t)mntsize; idx++) @@ -706,14 +847,14 @@ #if defined(__LINUX__) || defined(__linux__) #include -static UINT handle_platform_mounts_linux(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_linux(wLog* log, hotplug_dev* dev_array, size_t* size) { FILE* f; struct mntent* ent; f = fopen("/proc/mounts", "r"); if (f == NULL) { - WLog_ERR(TAG, "fopen failed!"); + WLog_Print(log, WLOG_ERROR, "fopen failed!"); return ERROR_OPEN_FAILED; } while ((ent = getmntent(f)) != NULL) @@ -725,14 +866,14 @@ } #endif -static UINT handle_platform_mounts(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts(wLog* log, hotplug_dev* dev_array, size_t* size) { #ifdef __sun - return handle_platform_mounts_sun(dev_array, size); + return handle_platform_mounts_sun(log, dev_array, size); #elif defined(__FreeBSD__) || defined(__OpenBSD__) - return handle_platform_mounts_bsd(dev_array, size); + return handle_platform_mounts_bsd(log, dev_array, size); #elif defined(__LINUX__) || defined(__linux__) - return handle_platform_mounts_linux(dev_array, size); + return handle_platform_mounts_linux(log, dev_array, size); #endif return ERROR_CALL_NOT_IMPLEMENTED; } @@ -790,7 +931,7 @@ UINT32 ids[1]; UINT error = ERROR_SUCCESS; - error = handle_platform_mounts(dev_array, &size); + error = handle_platform_mounts(rdpdr->log, dev_array, &size); /* delete removed devices */ count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); @@ -834,9 +975,9 @@ if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, - "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", + error); goto cleanup; } } @@ -858,7 +999,7 @@ if (!drive.Name) { - WLog_ERR(TAG, "_strdup failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "_strdup failed!"); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } @@ -866,7 +1007,7 @@ if ((error = devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_load_device_service failed!"); goto cleanup; } } @@ -887,7 +1028,7 @@ if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -905,7 +1046,7 @@ if (mfd < 0) { - WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts."); + WLog_Print(rdpdr->log, WLOG_ERROR, "ERROR: Unable to open /proc/mounts."); error = ERROR_INTERNAL_ERROR; goto out; } @@ -922,7 +1063,8 @@ if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); goto out; } @@ -934,11 +1076,12 @@ /* file /proc/mounts changed, handle this */ if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", + error); goto out; } else - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); } FD_ZERO(&rfds); @@ -978,7 +1121,8 @@ if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); return error; } @@ -1007,7 +1151,7 @@ if (!rdpdr->devman) { - WLog_ERR(TAG, "devman_new failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_new failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1036,7 +1180,7 @@ if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { - WLog_ERR(TAG, "CreateEvent failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateEvent failed!"); return ERROR_INTERNAL_ERROR; } @@ -1045,7 +1189,7 @@ if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, drive_hotplug_thread_func, rdpdr, 0, NULL))) { - WLog_ERR(TAG, "CreateThread failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); #ifndef _WIN32 CloseHandle(rdpdr->stopEvent); rdpdr->stopEvent = NULL; @@ -1059,7 +1203,8 @@ if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "devman_load_device_service failed with error %" PRIu32 "!", error); return error; } } @@ -1072,10 +1217,19 @@ if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, rdpdr->versionMajor); - Stream_Read_UINT16(s, rdpdr->versionMinor); + Stream_Read_UINT16(s, rdpdr->serverVersionMajor); + Stream_Read_UINT16(s, rdpdr->serverVersionMinor); Stream_Read_UINT32(s, rdpdr->clientID); rdpdr->sequenceId++; + + rdpdr->clientVersionMajor = MIN(RDPDR_VERSION_MAJOR, rdpdr->serverVersionMajor); + rdpdr->clientVersionMinor = MIN(RDPDR_VERSION_MINOR_RDP10X, rdpdr->serverVersionMinor); + WLog_Print(rdpdr->log, WLOG_DEBUG, + "[rdpdr] server announces version %" PRIu32 ".%" PRIu32 ", client uses %" PRIu32 + ".%" PRIu32, + rdpdr->serverVersionMajor, rdpdr->serverVersionMinor, rdpdr->clientVersionMajor, + rdpdr->clientVersionMinor); + return CHANNEL_RC_OK; } @@ -1087,18 +1241,23 @@ static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) { wStream* s; + + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_ANNOUNCE); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY); + s = Stream_New(NULL, 12); if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM); /* PacketId (2 bytes) */ - Stream_Write_UINT16(s, rdpdr->versionMajor); - Stream_Write_UINT16(s, rdpdr->versionMinor); + Stream_Write_UINT16(s, rdpdr->clientVersionMajor); + Stream_Write_UINT16(s, rdpdr->clientVersionMinor); Stream_Write_UINT32(s, (UINT32)rdpdr->clientID); return rdpdr_send(rdpdr, s); } @@ -1114,6 +1273,10 @@ WCHAR* computerNameW = NULL; size_t computerNameLenW; + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_NAME_REQUEST); + if (!rdpdr->computerName[0]) { DWORD size = sizeof(rdpdr->computerName) - 1; @@ -1126,7 +1289,7 @@ if (!s) { free(computerNameW); - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1147,17 +1310,20 @@ UINT16 versionMinor; UINT32 clientID; - if (Stream_GetRemainingLength(s) < 8) + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(s); + + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, versionMajor); Stream_Read_UINT16(s, versionMinor); Stream_Read_UINT32(s, clientID); - if (versionMajor != rdpdr->versionMajor || versionMinor != rdpdr->versionMinor) + if (versionMajor != rdpdr->clientVersionMajor || versionMinor != rdpdr->clientVersionMinor) { - rdpdr->versionMajor = versionMajor; - rdpdr->versionMinor = versionMinor; + rdpdr->clientVersionMajor = versionMajor; + rdpdr->clientVersionMinor = versionMinor; } if (clientID != rdpdr->clientID) @@ -1184,11 +1350,15 @@ DEVICE* device; int keyCount; ULONG_PTR* pKeys = NULL; + + if (userLoggedOn) + rdpdr->userLoggedOn = TRUE; + s = Stream_New(NULL, 256); if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1211,8 +1381,8 @@ * 3. other devices are sent only after user_loggedon */ - if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || - userLoggedOn) + if ((rdpdr->clientVersionMinor == RDPDR_VERSION_MINOR_RDP51) || + (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) { data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data)); @@ -1220,7 +1390,7 @@ { free(pKeys); Stream_Free(s, TRUE); - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INVALID_DATA; } @@ -1244,8 +1414,9 @@ Stream_Write(s, Stream_Buffer(device->data), data_len); count++; - WLog_INFO(TAG, "registered device #%" PRIu32 ": %s (type=%" PRIu32 " id=%" PRIu32 ")", - count, device->name, device->type, device->id); + WLog_Print(rdpdr->log, WLOG_INFO, + "registered device #%" PRIu32 ": %s (type=%" PRIu32 " id=%" PRIu32 ")", + count, device->name, device->type, device->id); } } @@ -1258,6 +1429,19 @@ return rdpdr_send(rdpdr, s); } +UINT rdpdr_try_send_device_list_announce_request(rdpdrPlugin* rdpdr) +{ + WINPR_ASSERT(rdpdr); + if (rdpdr->state != RDPDR_CHANNEL_STATE_USER_LOGGEDON) + { + WLog_Print(rdpdr->log, WLOG_DEBUG, + "hotplug event received, but channel [RDPDR] is not ready (state %s), ignoring.", + rdpdr_state_str(rdpdr->state)); + return CHANNEL_RC_OK; + } + return rdpdr_send_device_list_announce_request(rdpdr, TRUE); +} + static UINT dummy_irp_response(rdpdrPlugin* rdpdr, wStream* s) { @@ -1268,7 +1452,7 @@ wStream* output = Stream_New(NULL, 256); // RDPDR_DEVICE_IO_RESPONSE_LENGTH if (!output) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1301,11 +1485,11 @@ { IRP* irp; UINT error = CHANNEL_RC_OK; - irp = irp_new(rdpdr->devman, s, &error); + irp = irp_new(rdpdr->devman, s, rdpdr->log, &error); if (!irp) { - WLog_ERR(TAG, "irp_new failed with %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "irp_new failed with %" PRIu32 "!", error); if (error == CHANNEL_RC_OK) { @@ -1317,8 +1501,11 @@ IFCALLRET(irp->device->IRPRequest, error, irp->device, irp); - if (error) - WLog_ERR(TAG, "device->IRPRequest failed with error %" PRIu32 "", error); + if (error != CHANNEL_RC_OK) + { + WLog_Print(rdpdr->log, WLOG_ERROR, "device->IRPRequest failed with error %" PRIu32 "", + error); + } return error; } @@ -1360,6 +1547,8 @@ DEVICE* device; ULONG_PTR* pKeys = NULL; UINT error = CHANNEL_RC_OK; + + rdpdr->userLoggedOn = FALSE; /* reset possible received state */ pKeys = NULL; keyCount = ListDictionary_GetKeys(rdpdr->devman->devices, &pKeys); @@ -1370,7 +1559,7 @@ if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Init failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Init failed!"); free(pKeys); return error; } @@ -1380,6 +1569,97 @@ return CHANNEL_RC_OK; } +static BOOL state_match(enum RDPDR_CHANNEL_STATE state, size_t count, va_list ap) +{ + for (size_t x = 0; x < count; x++) + { + enum RDPDR_CHANNEL_STATE cur = va_arg(ap, enum RDPDR_CHANNEL_STATE); + if (state == cur) + return TRUE; + } + return FALSE; +} + +static const char* state_str(size_t count, va_list ap, char* buffer, size_t size) +{ + for (size_t x = 0; x < count; x++) + { + enum RDPDR_CHANNEL_STATE cur = va_arg(ap, enum RDPDR_CHANNEL_STATE); + const char* curstr = rdpdr_state_str(cur); + winpr_str_append(curstr, buffer, size, "|"); + } + return buffer; +} + +static BOOL rdpdr_state_check(rdpdrPlugin* rdpdr, UINT16 packetid, enum RDPDR_CHANNEL_STATE next, + size_t count, ...) +{ + va_list ap; + WINPR_ASSERT(rdpdr); + + va_start(ap, count); + BOOL rc = state_match(rdpdr->state, count, ap); + va_end(ap); + + if (!rc) + { + const char* strstate = rdpdr_state_str(rdpdr->state); + char buffer[256] = { 0 }; + + va_start(ap, count); + state_str(count, ap, buffer, sizeof(buffer)); + va_end(ap); + + WLog_Print(rdpdr->log, WLOG_ERROR, + "channel [RDPDR] received %s, expected states [%s] but have state %s, aborting.", + rdpdr_packetid_string(packetid), buffer, strstate); + + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_INITIAL); + return FALSE; + } + return rdpdr_state_advance(rdpdr, next); +} + +static BOOL rdpdr_check_channel_state(rdpdrPlugin* rdpdr, UINT16 packetid) +{ + WINPR_ASSERT(rdpdr); + + switch (packetid) + { + case PAKID_CORE_SERVER_ANNOUNCE: + /* windows servers sometimes send this message. + * it seems related to session login (e.g. first initialization for RDP/TLS style login, + * then reinitialize the channel after login successful + */ + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_INITIAL); + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_ANNOUNCE, 1, + RDPDR_CHANNEL_STATE_INITIAL); + case PAKID_CORE_SERVER_CAPABILITY: + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_SERVER_CAPS, 6, + RDPDR_CHANNEL_STATE_NAME_REQUEST, + RDPDR_CHANNEL_STATE_SERVER_CAPS, RDPDR_CHANNEL_STATE_READY, + RDPDR_CHANNEL_STATE_CLIENT_CAPS, PAKID_CORE_CLIENTID_CONFIRM, + PAKID_CORE_USER_LOGGEDON); + case PAKID_CORE_CLIENTID_CONFIRM: + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, 3, + RDPDR_CHANNEL_STATE_CLIENT_CAPS, RDPDR_CHANNEL_STATE_READY, + RDPDR_CHANNEL_STATE_USER_LOGGEDON); + case PAKID_CORE_USER_LOGGEDON: + if (!rdpdr_check_extended_pdu_flag(rdpdr, RDPDR_USER_LOGGEDON_PDU)) + return FALSE; + + return rdpdr_state_check( + rdpdr, packetid, RDPDR_CHANNEL_STATE_USER_LOGGEDON, 4, + RDPDR_CHANNEL_STATE_NAME_REQUEST, RDPDR_CHANNEL_STATE_CLIENT_CAPS, + RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, RDPDR_CHANNEL_STATE_READY); + default: + { + enum RDPDR_CHANNEL_STATE state = RDPDR_CHANNEL_STATE_READY; + return rdpdr_state_check(rdpdr, packetid, state, 1, state); + } + } +} + /** * Function description * @@ -1403,6 +1683,9 @@ if (component == RDPDR_CTYP_CORE) { + if (!rdpdr_check_channel_state(rdpdr, packetId)) + return CHANNEL_RC_OK; + switch (packetId) { case PAKID_CORE_SERVER_ANNOUNCE: @@ -1411,19 +1694,20 @@ } else if ((error = rdpdr_send_client_announce_reply(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_client_announce_reply failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_client_announce_reply failed with error %" PRIu32 "", + error); } else if ((error = rdpdr_send_client_name_request(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_client_name_request failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_client_name_request failed with error %" PRIu32 "", + error); } else if ((error = rdpdr_process_init(rdpdr))) { - WLog_ERR(TAG, "rdpdr_process_init failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_init failed with error %" PRIu32 "", error); } break; @@ -1434,9 +1718,9 @@ } else if ((error = rdpdr_send_capability_response(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_capability_response failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_capability_response failed with error %" PRIu32 "", + error); } break; @@ -1447,22 +1731,29 @@ } else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) { - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error); } - + else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY)) + { + error = ERROR_INTERNAL_ERROR; + } break; case PAKID_CORE_USER_LOGGEDON: if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) { - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error); } + else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY)) + { + error = ERROR_INTERNAL_ERROR; + } break; @@ -1481,7 +1772,8 @@ case PAKID_CORE_DEVICE_IOREQUEST: if ((error = rdpdr_process_irp(rdpdr, s))) { - WLog_ERR(TAG, "rdpdr_process_irp failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_irp failed with error %" PRIu32 "", error); return error; } else @@ -1490,7 +1782,8 @@ break; default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04" PRIX16 "", packetId); + WLog_Print(rdpdr->log, WLOG_ERROR, + "RDPDR_CTYP_CORE unknown PacketId: 0x%04" PRIX16 "", packetId); error = ERROR_INVALID_DATA; break; } @@ -1501,9 +1794,10 @@ if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, - "Unknown message: Component: 0x%04" PRIX16 " PacketId: 0x%04" PRIX16 "", - component, packetId); + WLog_Print(rdpdr->log, WLOG_ERROR, + "Unknown message: Component: [0x%04" PRIX16 "] PacketId: [0x%04" PRIX16 + "]", + component, packetId); } } } @@ -1543,8 +1837,8 @@ if (status != CHANNEL_RC_OK) { Stream_Free(s, TRUE); - WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(status), status); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); } return status; @@ -1581,7 +1875,7 @@ if (!rdpdr->data_in) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } } @@ -1590,7 +1884,7 @@ if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INVALID_DATA; } @@ -1600,7 +1894,8 @@ { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { - WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received: read error"); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_data_received: read error"); return ERROR_INTERNAL_ERROR; } @@ -1610,7 +1905,7 @@ if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*)data_in, NULL)) { - WLog_ERR(TAG, "MessageQueue_Post failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } @@ -1631,14 +1926,15 @@ case CHANNEL_EVENT_DATA_RECEIVED: if (!rdpdr || !pData || (rdpdr->OpenHandle != openHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_Print(rdpdr->log, WLOG_ERROR, "error no match"); return; } if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_data_received failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_data_received failed with error %" PRIu32 + "!", + error); break; @@ -1676,7 +1972,8 @@ if ((error = rdpdr_process_connect(rdpdr))) { - WLog_ERR(TAG, "rdpdr_process_connect failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "rdpdr_process_connect failed with error %" PRIu32 "!", + error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, @@ -1702,7 +1999,8 @@ if ((error = rdpdr_process_receive(rdpdr, data))) { - WLog_ERR(TAG, "rdpdr_process_receive failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_receive failed with error %" PRIu32 "!", error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, @@ -1740,8 +2038,8 @@ if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(status), status); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); return status; } @@ -1749,7 +2047,7 @@ if (!rdpdr->queue) { - WLog_ERR(TAG, "MessageQueue_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1758,7 +2056,7 @@ if (!(rdpdr->thread = CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL))) { - WLog_ERR(TAG, "CreateThread failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); return ERROR_INTERNAL_ERROR; } @@ -1781,7 +2079,8 @@ (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); return error; } @@ -1792,7 +2091,8 @@ if ((error = drive_hotplug_thread_terminate(rdpdr))) { - WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error); return error; } @@ -1800,8 +2100,8 @@ if (CHANNEL_RC_OK != error) { - WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(error), error); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(error), error); } rdpdr->OpenHandle = 0; @@ -1835,7 +2135,7 @@ if (!rdpdr || (rdpdr->InitHandle != pInitHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_Print(rdpdr->log, WLOG_ERROR, "error no match"); return; } @@ -1846,17 +2146,18 @@ case CHANNEL_EVENT_CONNECTED: if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_connected failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_connected failed with error %" PRIu32 "!", + error); break; case CHANNEL_EVENT_DISCONNECTED: if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_disconnected failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_disconnected failed with error %" PRIu32 + "!", + error); break; @@ -1867,7 +2168,7 @@ case CHANNEL_EVENT_ATTACHED: case CHANNEL_EVENT_DETACHED: default: - WLog_ERR(TAG, "unknown event %" PRIu32 "!", event); + WLog_Print(rdpdr->log, WLOG_ERROR, "unknown event %" PRIu32 "!", event); break; } @@ -1877,6 +2178,7 @@ } /* rdpdr is always built-in */ +#define TAG CHANNELS_TAG("rdpdr.client") #define VirtualChannelEntryEx rdpdr_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) @@ -1884,13 +2186,30 @@ UINT rc; rdpdrPlugin* rdpdr; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; + + WINPR_ASSERT(pEntryPoints); + WINPR_ASSERT(pInitHandle); + rdpdr = (rdpdrPlugin*)calloc(1, sizeof(rdpdrPlugin)); if (!rdpdr) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "calloc failed!"); return FALSE; } + rdpdr->log = WLog_Get(TAG); + + rdpdr->clientExtendedPDU = + RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU; + rdpdr->clientIOCode1 = + RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ | + RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN | + RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION | + RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION | + RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL | + RDPDR_IRP_MJ_QUERY_SECURITY | RDPDR_IRP_MJ_SET_SECURITY; + + rdpdr->clientExtraFlags1 = ENABLE_ASYNCIO; rdpdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; @@ -1912,8 +2231,8 @@ if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), - rc); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(rc), rc); free(rdpdr); return FALSE; } diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_main.h freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_main.h --- freerdp2-2.10.0+dfsg1/channels/rdpdr/client/rdpdr_main.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/client/rdpdr_main.h 2024-04-22 09:26:59.000000000 +0000 @@ -42,15 +42,33 @@ #include #endif -#define TAG CHANNELS_TAG("rdpdr.client") +#if !defined(Stream_CheckAndLogRequiredLengthWLog) +#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \ + Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ + __FILE__, __LINE__) +#endif typedef struct rdpdr_plugin rdpdrPlugin; +enum RDPDR_CHANNEL_STATE +{ + RDPDR_CHANNEL_STATE_INITIAL = 0, + RDPDR_CHANNEL_STATE_ANNOUNCE, + RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY, + RDPDR_CHANNEL_STATE_NAME_REQUEST, + RDPDR_CHANNEL_STATE_SERVER_CAPS, + RDPDR_CHANNEL_STATE_CLIENT_CAPS, + RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, + RDPDR_CHANNEL_STATE_READY, + RDPDR_CHANNEL_STATE_USER_LOGGEDON +}; + struct rdpdr_plugin { CHANNEL_DEF channelDef; CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints; + enum RDPDR_CHANNEL_STATE state; HANDLE thread; wStream* data_in; void* InitHandle; @@ -59,12 +77,33 @@ DEVMAN* devman; - UINT16 versionMajor; - UINT16 versionMinor; - UINT16 clientID; + UINT32 serverOsType; + UINT32 serverOsVersion; + UINT16 serverVersionMajor; + UINT16 serverVersionMinor; + UINT32 serverExtendedPDU; + UINT32 serverIOCode1; + UINT32 serverIOCode2; + UINT32 serverExtraFlags1; + UINT32 serverExtraFlags2; + UINT32 serverSpecialTypeDeviceCap; + + UINT32 clientOsType; + UINT32 clientOsVersion; + UINT16 clientVersionMajor; + UINT16 clientVersionMinor; + UINT32 clientExtendedPDU; + UINT32 clientIOCode1; + UINT32 clientIOCode2; + UINT32 clientExtraFlags1; + UINT32 clientExtraFlags2; + UINT32 clientSpecialTypeDeviceCap; + + UINT32 clientID; char computerName[256]; UINT32 sequenceId; + BOOL userLoggedOn; /* hotplug support */ HANDLE hotplugThread; @@ -78,8 +117,10 @@ HANDLE stopEvent; #endif rdpContext* rdpcontext; + wLog* log; }; +BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next); UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_MAIN_H */ diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpdr/server/rdpdr_main.h freerdp2-2.11.7+dfsg1/channels/rdpdr/server/rdpdr_main.h --- freerdp2-2.10.0+dfsg1/channels/rdpdr/server/rdpdr_main.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpdr/server/rdpdr_main.h 2024-04-22 09:26:59.000000000 +0000 @@ -57,13 +57,6 @@ }; typedef struct _RDPDR_HEADER RDPDR_HEADER; -#define RDPDR_VERSION_MAJOR 0x0001 - -#define RDPDR_VERSION_MINOR_RDP50 0x0002 -#define RDPDR_VERSION_MINOR_RDP51 0x0005 -#define RDPDR_VERSION_MINOR_RDP52 0x000A -#define RDPDR_VERSION_MINOR_RDP6X 0x000C - #define RDPDR_CAPABILITY_HEADER_LENGTH 8 struct _RDPDR_CAPABILITY_HEADER diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpecam/server/camera_device_main.c freerdp2-2.11.7+dfsg1/channels/rdpecam/server/camera_device_main.c --- freerdp2-2.10.0+dfsg1/channels/rdpecam/server/camera_device_main.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpecam/server/camera_device_main.c 2024-04-22 09:26:59.000000000 +0000 @@ -686,8 +686,6 @@ { wStream* s; - WINPR_ASSERT(size > 0); - /* Allocate what we need plus header bytes */ s = Stream_New(NULL, size + CAM_HEADER_SIZE); if (!s) diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpsnd/client/pulse/rdpsnd_pulse.c freerdp2-2.11.7+dfsg1/channels/rdpsnd/client/pulse/rdpsnd_pulse.c --- freerdp2-2.10.0+dfsg1/channels/rdpsnd/client/pulse/rdpsnd_pulse.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpsnd/client/pulse/rdpsnd_pulse.c 2024-04-22 09:26:59.000000000 +0000 @@ -23,11 +23,15 @@ #include "config.h" #endif +#include + #include #include #include +#include #include +#include #include #include @@ -51,8 +55,39 @@ pa_stream* stream; UINT32 latency; UINT32 volume; + time_t reconnect_delay_seconds; + time_t reconnect_time; }; +static BOOL rdpsnd_check_pulse(rdpsndPulsePlugin* pulse, BOOL haveStream) +{ + BOOL rc = TRUE; + WINPR_ASSERT(pulse); + + if (!pulse->context) + { + WLog_WARN(TAG, "pulse->context=%p", pulse->context); + rc = FALSE; + } + + if (haveStream) + { + if (!pulse->stream) + { + WLog_WARN(TAG, "pulse->stream=%p", pulse->stream); + rc = FALSE; + } + } + + if (!pulse->mainloop) + { + WLog_WARN(TAG, "pulse->mainloop=%p", pulse->mainloop); + rc = FALSE; + } + + return rc; +} + static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format); static void rdpsnd_pulse_get_sink_info(pa_context* c, const pa_sink_info* i, int eol, @@ -65,7 +100,8 @@ ; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; - if (!pulse || !c || !i) + WINPR_ASSERT(c); + if (!rdpsnd_check_pulse(pulse, FALSE) || !i) return; for (x = 0; x < i->volume.channels; x++) @@ -97,6 +133,10 @@ { pa_context_state_t state; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + + WINPR_ASSERT(context); + WINPR_ASSERT(pulse); + state = pa_context_get_state(context); switch (state) @@ -106,6 +146,14 @@ break; case PA_CONTEXT_FAILED: + // Destroy context now, create new one for next connection attempt + pa_context_unref(pulse->context); + pulse->context = NULL; + if (pulse->reconnect_delay_seconds >= 0) + pulse->reconnect_time = time(NULL) + pulse->reconnect_delay_seconds; + pa_threaded_mainloop_signal(pulse->mainloop, 0); + break; + case PA_CONTEXT_TERMINATED: pa_threaded_mainloop_signal(pulse->mainloop, 0); break; @@ -117,21 +165,17 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) { + BOOL rc; pa_operation* o; pa_context_state_t state; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse->context) + if (!rdpsnd_check_pulse(pulse, FALSE)) return FALSE; - if (pa_context_connect(pulse->context, NULL, 0, NULL)) - { - return FALSE; - } - pa_threaded_mainloop_lock(pulse->mainloop); - if (pa_threaded_mainloop_start(pulse->mainloop) < 0) + if (pa_context_connect(pulse->context, NULL, 0, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); return FALSE; @@ -157,27 +201,35 @@ if (o) pa_operation_unref(o); - pa_threaded_mainloop_unlock(pulse->mainloop); - if (state == PA_CONTEXT_READY) { - return TRUE; + rc = TRUE; } else { pa_context_disconnect(pulse->context); - return FALSE; + rc = FALSE; } + + pa_threaded_mainloop_unlock(pulse->mainloop); + return rc; } static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + + if (!rdpsnd_check_pulse(pulse, TRUE)) + return; + pa_threaded_mainloop_signal(pulse->mainloop, 0); } static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operation* operation) { + if (!rdpsnd_check_pulse(pulse, TRUE)) + return; + if (!operation) return; @@ -193,6 +245,11 @@ { pa_stream_state_t state; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + + WINPR_ASSERT(stream); + if (!rdpsnd_check_pulse(pulse, TRUE)) + return; + state = pa_stream_get_state(stream); switch (state) @@ -203,6 +260,8 @@ case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: + // Stream object is about to be destroyed, clean up our pointer + pulse->stream = NULL; pa_threaded_mainloop_signal(pulse->mainloop, 0); break; @@ -214,6 +273,11 @@ static void rdpsnd_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + + WINPR_ASSERT(stream); + if (!rdpsnd_check_pulse(pulse, TRUE)) + return; + pa_threaded_mainloop_signal(pulse->mainloop, 0); } @@ -221,15 +285,20 @@ { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse->context || !pulse->stream) + WINPR_ASSERT(pulse); + + if (!rdpsnd_check_pulse(pulse, FALSE)) return; pa_threaded_mainloop_lock(pulse->mainloop); - rdpsnd_pulse_wait_for_operation( - pulse, pa_stream_drain(pulse->stream, rdpsnd_pulse_stream_success_callback, pulse)); - pa_stream_disconnect(pulse->stream); - pa_stream_unref(pulse->stream); - pulse->stream = NULL; + if (pulse->stream) + { + rdpsnd_pulse_wait_for_operation( + pulse, pa_stream_drain(pulse->stream, rdpsnd_pulse_stream_success_callback, pulse)); + pa_stream_disconnect(pulse->stream); + pa_stream_unref(pulse->stream); + pulse->stream = NULL; + } pa_threaded_mainloop_unlock(pulse->mainloop); } @@ -237,7 +306,9 @@ { pa_sample_spec sample_spec = { 0 }; - if (!pulse->context) + WINPR_ASSERT(format); + + if (!rdpsnd_check_pulse(pulse, FALSE)) return FALSE; if (!rdpsnd_pulse_format_supported(&pulse->device, format)) @@ -281,30 +352,52 @@ return TRUE; } -static BOOL rdpsnd_pulse_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, - UINT32 latency) +static BOOL rdpsnd_pulse_context_connect(rdpsndDevicePlugin* device) { - pa_stream_state_t state; - pa_stream_flags_t flags; - pa_buffer_attr buffer_attr = { 0 }; - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse->context || pulse->stream) - return TRUE; + pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); - if (!rdpsnd_pulse_set_format_spec(pulse, format)) + if (!pulse->context) return FALSE; - pulse->latency = latency; + pa_context_set_state_callback(pulse->context, rdpsnd_pulse_context_state_callback, pulse); + + if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) + return FALSE; + + return TRUE; +} + +static BOOL rdpsnd_pulse_open_stream(rdpsndDevicePlugin* device) +{ + pa_stream_state_t state; + pa_stream_flags_t flags; + pa_buffer_attr buffer_attr = { 0 }; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = { 0 }; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); - return TRUE; + return FALSE; } pa_threaded_mainloop_lock(pulse->mainloop); + if (!pulse->context) + { + pa_threaded_mainloop_unlock(pulse->mainloop); + if (pulse->reconnect_delay_seconds >= 0 && time(NULL) - pulse->reconnect_time >= 0) + rdpsnd_pulse_context_connect(device); + pa_threaded_mainloop_lock(pulse->mainloop); + } + + if (!rdpsnd_check_pulse(pulse, FALSE)) + { + pa_threaded_mainloop_unlock(pulse->mainloop); + return FALSE; + } + pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); if (!pulse->stream) @@ -320,19 +413,22 @@ if (pulse->latency > 0) { - buffer_attr.maxlength = pa_usec_to_bytes(pulse->latency * 2 * 1000, &pulse->sample_spec); + buffer_attr.maxlength = UINT32_MAX; buffer_attr.tlength = pa_usec_to_bytes(pulse->latency * 1000, &pulse->sample_spec); - buffer_attr.prebuf = (UINT32)-1; - buffer_attr.minreq = (UINT32)-1; - buffer_attr.fragsize = (UINT32)-1; + buffer_attr.prebuf = UINT32_MAX; + buffer_attr.minreq = UINT32_MAX; + buffer_attr.fragsize = UINT32_MAX; flags |= PA_STREAM_ADJUST_LATENCY; } if (pa_stream_connect_playback(pulse->stream, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { + WLog_ERR(TAG, "error connecting playback stream"); + pa_stream_unref(pulse->stream); + pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); - return TRUE; + return FALSE; } for (;;) @@ -359,6 +455,24 @@ return FALSE; } +static BOOL rdpsnd_pulse_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, + UINT32 latency) +{ + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + + WINPR_ASSERT(format); + + if (!rdpsnd_check_pulse(pulse, FALSE)) + return TRUE; + + if (!rdpsnd_pulse_set_format_spec(pulse, format)) + return FALSE; + + pulse->latency = latency; + + return rdpsnd_pulse_open_stream(device); +} + static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; @@ -369,9 +483,7 @@ rdpsnd_pulse_close(device); if (pulse->mainloop) - { pa_threaded_mainloop_stop(pulse->mainloop); - } if (pulse->context) { @@ -394,6 +506,7 @@ AUDIO_FORMAT* defaultFormat) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + if (!pulse || !defaultFormat) return FALSE; @@ -415,6 +528,9 @@ BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format) { + WINPR_ASSERT(device); + WINPR_ASSERT(format); + switch (format->wFormatTag) { case WAVE_FORMAT_PCM: @@ -439,39 +555,51 @@ pa_operation* o; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse) - return 0; - - if (!pulse->context || !pulse->mainloop) + if (!rdpsnd_check_pulse(pulse, FALSE)) return 0; pa_threaded_mainloop_lock(pulse->mainloop); o = pa_context_get_sink_info_by_index(pulse->context, 0, rdpsnd_pulse_get_sink_info, pulse); - pa_operation_unref(o); + if (o) + pa_operation_unref(o); pa_threaded_mainloop_unlock(pulse->mainloop); return pulse->volume; } +static void rdpsnd_set_volume_success_cb(pa_context* c, int success, void* userdata) +{ + rdpsndPulsePlugin* pulse = userdata; + + if (!rdpsnd_check_pulse(pulse, TRUE)) + return; + WINPR_ASSERT(c); + + WLog_INFO(TAG, "%s: %d", __FUNCTION__, success); +} + static BOOL rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value) { - pa_cvolume cv; + pa_cvolume cv = { 0 }; pa_volume_t left; pa_volume_t right; pa_operation* operation; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse->context || !pulse->stream) + if (!rdpsnd_check_pulse(pulse, TRUE)) + { + WLog_WARN(TAG, "%s called before pulse backend was initialized"); return FALSE; + } left = (pa_volume_t)(value & 0xFFFF); right = (pa_volume_t)((value >> 16) & 0xFFFF); pa_cvolume_init(&cv); cv.channels = 2; - cv.values[0] = PA_VOLUME_MUTED + (left * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / 0xFFFF; - cv.values[1] = PA_VOLUME_MUTED + (right * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / 0xFFFF; + cv.values[0] = PA_VOLUME_MUTED + (left * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / PA_VOLUME_NORM; + cv.values[1] = PA_VOLUME_MUTED + (right * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / PA_VOLUME_NORM; pa_threaded_mainloop_lock(pulse->mainloop); operation = pa_context_set_sink_input_volume(pulse->context, pa_stream_get_index(pulse->stream), - &cv, NULL, NULL); + &cv, rdpsnd_set_volume_success_cb, pulse); if (operation) pa_operation_unref(operation); @@ -483,28 +611,38 @@ static UINT rdpsnd_pulse_play(rdpsndDevicePlugin* device, const BYTE* data, size_t size) { size_t length; + void* pa_data; int status; pa_usec_t latency; int negative; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - if (!pulse->stream || !data) + if (!data) return 0; pa_threaded_mainloop_lock(pulse->mainloop); + if (!rdpsnd_check_pulse(pulse, TRUE)) + { + pa_threaded_mainloop_unlock(pulse->mainloop); + // Discard this playback request and just attempt to reconnect the stream + WLog_DBG(TAG, "reconnecting playback stream"); + rdpsnd_pulse_open_stream(device); + return 0; + } + while (size > 0) { - while ((length = pa_stream_writable_size(pulse->stream)) == 0) - pa_threaded_mainloop_wait(pulse->mainloop); + length = size; - if (length == (size_t)-1) + status = pa_stream_begin_write(pulse->stream, &pa_data, &length); + + if (status < 0) break; - if (length > size) - length = size; + memcpy(pa_data, data, length); - status = pa_stream_write(pulse->stream, data, length, NULL, 0LL, PA_SEEK_RELATIVE); + status = pa_stream_write(pulse->stream, pa_data, length, NULL, 0LL, PA_SEEK_RELATIVE); if (status < 0) { @@ -522,22 +660,24 @@ return latency / 1000; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args) { int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; - COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, - "", NULL, NULL, -1, NULL, "device" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] = { + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, + { "reconnect_delay_seconds", COMMAND_LINE_VALUE_REQUIRED, "", NULL, + NULL, -1, NULL, "reconnect_delay_seconds" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } + }; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + + WINPR_ASSERT(pulse); + WINPR_ASSERT(args); + status = CommandLineParseArgumentsA(args->argc, args->argv, rdpsnd_pulse_args, flags, pulse, NULL, NULL); @@ -558,6 +698,15 @@ if (!pulse->device_name) return ERROR_OUTOFMEMORY; } + CommandLineSwitchCase(arg, "reconnect_delay_seconds") + { + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > INT32_MAX)) + return ERROR_INVALID_DATA; + + pulse->reconnect_delay_seconds = val; + } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); @@ -570,16 +719,14 @@ #define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; rdpsndPulsePlugin* pulse; UINT ret; + + WINPR_ASSERT(pEntryPoints); + pulse = (rdpsndPulsePlugin*)calloc(1, sizeof(rdpsndPulsePlugin)); if (!pulse) @@ -605,6 +752,8 @@ goto error; } } + pulse->reconnect_delay_seconds = 5; + pulse->reconnect_time = time(NULL); ret = CHANNEL_RC_NO_MEMORY; pulse->mainloop = pa_threaded_mainloop_new(); @@ -612,15 +761,17 @@ if (!pulse->mainloop) goto error; - pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); + pa_threaded_mainloop_lock(pulse->mainloop); - if (!pulse->context) - goto error; + if (pa_threaded_mainloop_start(pulse->mainloop) < 0) + { + pa_threaded_mainloop_unlock(pulse->mainloop); + return FALSE; + } - pa_context_set_state_callback(pulse->context, rdpsnd_pulse_context_state_callback, pulse); - ret = ERROR_INVALID_OPERATION; + pa_threaded_mainloop_unlock(pulse->mainloop); - if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) + if (!rdpsnd_pulse_context_connect((rdpsndDevicePlugin*)pulse)) goto error; pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)pulse); diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c freerdp2-2.11.7+dfsg1/channels/rdpsnd/client/rdpsnd_main.c --- freerdp2-2.10.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpsnd/client/rdpsnd_main.c 2024-04-22 09:26:59.000000000 +0000 @@ -126,6 +126,10 @@ HANDLE thread; wMessageQueue* queue; BOOL initialized; + + UINT16 wVersion; + UINT32 volume; + BOOL applyVolume; }; static const char* rdpsnd_is_dyn_str(BOOL dynamic) @@ -268,9 +272,9 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s) { UINT16 index; - UINT16 wVersion; UINT16 wNumberOfFormats; UINT ret = ERROR_BAD_LENGTH; + audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); rdpsnd->NumberOfServerFormats = 0; rdpsnd->ServerFormats = NULL; @@ -285,7 +289,7 @@ Stream_Seek_UINT16(s); /* wDGramPort */ Stream_Read_UINT16(s, wNumberOfFormats); Stream_Read_UINT8(s, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ - Stream_Read_UINT16(s, wVersion); /* wVersion */ + Stream_Read_UINT16(s, rdpsnd->wVersion); /* wVersion */ Stream_Seek_UINT8(s); /* bPad */ rdpsnd->NumberOfServerFormats = wNumberOfFormats; @@ -312,7 +316,7 @@ if (ret == CHANNEL_RC_OK) { - if (wVersion >= CHANNEL_VERSION_WIN_7) + if (rdpsnd->wVersion >= CHANNEL_VERSION_WIN_7) ret = rdpsnd_send_quality_mode_pdu(rdpsnd); } @@ -373,6 +377,20 @@ return rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize); } +static BOOL rdpsnd_apply_volume(rdpsndPlugin* rdpsnd) +{ + WINPR_ASSERT(rdpsnd); + + if (rdpsnd->isOpen && rdpsnd->applyVolume && rdpsnd->device) + { + BOOL rc = IFCALLRESULT(TRUE, rdpsnd->device->SetVolume, rdpsnd->device, rdpsnd->volume); + if (!rc) + return FALSE; + rdpsnd->applyVolume = FALSE; + } + return TRUE; +} + static BOOL rdpsnd_ensure_device_is_open(rdpsndPlugin* rdpsnd, UINT32 wFormatNo, const AUDIO_FORMAT* format) { @@ -421,7 +439,7 @@ rdpsnd->totalPlaySize = 0; } - return TRUE; + return rdpsnd_apply_volume(rdpsnd); } /** @@ -710,7 +728,7 @@ */ static UINT rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s) { - BOOL rc = FALSE; + BOOL rc = TRUE; UINT32 dwVolume; if (Stream_GetRemainingLength(s) < 4) @@ -719,8 +737,10 @@ Stream_Read_UINT32(s, dwVolume); WLog_Print(rdpsnd->log, WLOG_DEBUG, "%s Volume: 0x%08" PRIX32 "", rdpsnd_is_dyn_str(rdpsnd->dynamic), dwVolume); - if (rdpsnd->device) - rc = IFCALLRESULT(FALSE, rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); + + rdpsnd->volume = dwVolume; + rdpsnd->applyVolume = TRUE; + rc = rdpsnd_apply_volume(rdpsnd); if (!rc) { diff -Nru freerdp2-2.10.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.c freerdp2-2.11.7+dfsg1/channels/rdpsnd/server/rdpsnd_main.c --- freerdp2-2.10.0+dfsg1/channels/rdpsnd/server/rdpsnd_main.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/rdpsnd/server/rdpsnd_main.c 2024-04-22 09:26:59.000000000 +0000 @@ -523,7 +523,7 @@ Stream_Seek(s, 3); /* bPad */ start = Stream_GetPosition(s); src = context->priv->out_buffer; - length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame * 1ULL; + length = 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame; if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s)) return ERROR_INTERNAL_ERROR; diff -Nru freerdp2-2.10.0+dfsg1/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c freerdp2-2.11.7+dfsg1/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c --- freerdp2-2.10.0+dfsg1/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c 2024-04-22 09:26:59.000000000 +0000 @@ -235,8 +235,10 @@ } } +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED; +#endif return TRUE; } diff -Nru freerdp2-2.10.0+dfsg1/client/Wayland/wlf_input.c freerdp2-2.11.7+dfsg1/client/Wayland/wlf_input.c --- freerdp2-2.10.0+dfsg1/client/Wayland/wlf_input.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/Wayland/wlf_input.c 2024-04-22 09:26:59.000000000 +0000 @@ -135,25 +135,43 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev) { + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); + return TRUE; +} + +BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev) +{ + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); + return TRUE; +} + +static BOOL wlf_handle_wheel(freerdp* instance, uint32_t x, uint32_t y, uint32_t axis, + int32_t value) +{ rdpInput* input; UINT16 flags = 0; int32_t direction; - uint32_t x, y; - uint32_t i; - - if (!instance || !ev || !instance->input) - return FALSE; + uint32_t avalue = abs(value); - x = ev->x; - y = ev->y; + input = instance->input; if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) return FALSE; input = instance->input; - direction = ev->value; - switch (ev->axis) + direction = value; + switch (axis) { case WL_POINTER_AXIS_VERTICAL_SCROLL: flags |= PTR_FLAGS_WHEEL; @@ -176,16 +194,102 @@ * positive: 0 ... 0xFF -> slow ... fast * negative: 0 ... 0xFF -> fast ... slow */ - for (i = 0; i < abs(direction); i++) + + while (avalue > 0) { - uint32_t cflags = flags | 0x78; + const uint32_t cval = avalue > 0xFF ? 0xFF : avalue; + uint32_t cflags = flags | cval; /* Convert negative values to 9bit twos complement */ if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - cflags = (flags & 0xFF00) | (0x100 - (cflags & 0xFF)); + cflags = (flags & 0xFF00) | (0x100 - cval); if (!freerdp_input_send_mouse_event(input, cflags, (UINT16)x, (UINT16)y)) return FALSE; + + avalue -= cval; } + return TRUE; +} + +BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev) +{ + BOOL success = TRUE; + BOOL handle = FALSE; + size_t x; + wlfContext* context; + enum wl_pointer_axis_source source; + + if (!instance || !ev || !instance->input || !instance->context) + return FALSE; + + context = (wlfContext*)instance->context; + + for (x = 0; x < ArrayList_Count(context->events); x++) + { + UwacEvent* ev = ArrayList_GetItem(context->events, x); + if (!ev) + continue; + if (ev->type == UWAC_EVENT_POINTER_SOURCE) + { + handle = TRUE; + source = ev->mouse_source.axis_source; + } + } + + /* We need source events to determine how to interpret the data */ + if (handle) + { + for (x = 0; x < ArrayList_Count(context->events); x++) + { + UwacEvent* ev = ArrayList_GetItem(context->events, x); + if (!ev) + continue; + + switch (source) + { + /* If we have a mouse wheel, just use discrete data */ + case WL_POINTER_AXIS_SOURCE_WHEEL: +#if defined(WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION) + case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: +#endif + if (ev->type == UWAC_EVENT_POINTER_AXIS_DISCRETE) + { + /* Get the number of steps, multiply by default step width of 120 */ + int32_t val = ev->mouse_axis.value * 0x78; + /* No wheel event received, success! */ + if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y, + ev->mouse_axis.axis, val)) + success = FALSE; + } + break; + /* If we have a touch pad we get actual data, scale */ + case WL_POINTER_AXIS_SOURCE_FINGER: + case WL_POINTER_AXIS_SOURCE_CONTINUOUS: + if (ev->type == UWAC_EVENT_POINTER_AXIS) + { + double dval = wl_fixed_to_double(ev->mouse_axis.value); + int32_t val = dval * 0x78 / 10.0; + if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y, + ev->mouse_axis.axis, val)) + success = FALSE; + } + break; + default: + break; + } + } + } + ArrayList_Clear(context->events); + return success; +} + +BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev) +{ + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); return TRUE; } diff -Nru freerdp2-2.10.0+dfsg1/client/Wayland/wlf_input.h freerdp2-2.11.7+dfsg1/client/Wayland/wlf_input.h --- freerdp2-2.10.0+dfsg1/client/Wayland/wlf_input.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/Wayland/wlf_input.h 2024-04-22 09:26:59.000000000 +0000 @@ -30,6 +30,9 @@ BOOL wlf_handle_pointer_motion(freerdp* instance, const UwacPointerMotionEvent* ev); BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent* ev); BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev); +BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev); +BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev); +BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev); BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev); BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev); BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev); diff -Nru freerdp2-2.10.0+dfsg1/client/Wayland/wlfreerdp.c freerdp2-2.11.7+dfsg1/client/Wayland/wlfreerdp.c --- freerdp2-2.10.0+dfsg1/client/Wayland/wlfreerdp.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/Wayland/wlfreerdp.c 2024-04-22 09:26:59.000000000 +0000 @@ -362,12 +362,22 @@ break; case UWAC_EVENT_POINTER_AXIS: + if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + return FALSE; break; case UWAC_EVENT_POINTER_AXIS_DISCRETE: - if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + if (!wlf_handle_pointer_axis_discrete(instance, &event.mouse_axis)) return FALSE; + break; + case UWAC_EVENT_POINTER_FRAME: + if (!wlf_handle_pointer_frame(instance, &event.mouse_frame)) + return FALSE; + break; + case UWAC_EVENT_POINTER_SOURCE: + if (!wlf_handle_pointer_source(instance, &event.mouse_source)) + return FALSE; break; case UWAC_EVENT_KEY: @@ -561,8 +571,37 @@ return 1; } +static void wlf_client_free(freerdp* instance, rdpContext* context) +{ + wlfContext* wlf = (wlfContext*)instance->context; + + if (!context) + return; + + if (wlf->display) + UwacCloseDisplay(&wlf->display); + + if (wlf->displayHandle) + CloseHandle(wlf->displayHandle); + ArrayList_Free(wlf->events); + DeleteCriticalSection(&wlf->critical); +} + +static void* uwac_event_clone(const void* val) +{ + UwacEvent* copy; + UwacEvent* ev = (UwacEvent*)val; + + copy = calloc(1, sizeof(UwacEvent)); + if (!copy) + return NULL; + *copy = *ev; + return copy; +} + static BOOL wlf_client_new(freerdp* instance, rdpContext* context) { + wObject* obj; UwacReturnCode status; wlfContext* wfl = (wlfContext*)context; @@ -590,24 +629,17 @@ if (!wfl->displayHandle) return FALSE; - InitializeCriticalSection(&wfl->critical); - - return TRUE; -} - -static void wlf_client_free(freerdp* instance, rdpContext* context) -{ - wlfContext* wlf = (wlfContext*)instance->context; + wfl->events = ArrayList_New(FALSE); + if (!wfl->events) + return FALSE; - if (!context) - return; + obj = ArrayList_Object(wfl->events); + obj->fnObjectNew = uwac_event_clone; + obj->fnObjectFree = free; - if (wlf->display) - UwacCloseDisplay(&wlf->display); + InitializeCriticalSection(&wfl->critical); - if (wlf->displayHandle) - CloseHandle(wlf->displayHandle); - DeleteCriticalSection(&wlf->critical); + return TRUE; } static int wfl_client_start(rdpContext* context) diff -Nru freerdp2-2.10.0+dfsg1/client/Wayland/wlfreerdp.h freerdp2-2.11.7+dfsg1/client/Wayland/wlfreerdp.h --- freerdp2-2.10.0+dfsg1/client/Wayland/wlfreerdp.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/Wayland/wlfreerdp.h 2024-04-22 09:26:59.000000000 +0000 @@ -53,6 +53,7 @@ wlfDispContext* disp; wLog* log; CRITICAL_SECTION critical; + wArrayList* events; }; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); diff -Nru freerdp2-2.10.0+dfsg1/client/X11/xf_gdi.c freerdp2-2.11.7+dfsg1/client/X11/xf_gdi.c --- freerdp2-2.10.0+dfsg1/client/X11/xf_gdi.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/X11/xf_gdi.c 2024-04-22 09:26:59.000000000 +0000 @@ -1066,7 +1066,7 @@ case RDP_CODEC_ID_NONE: pSrcData = cmd->bmp.bitmapData; format = gdi_get_pixel_format(cmd->bmp.bpp); - size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL; + size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format); if (size > cmd->bmp.bitmapDataLength) { WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz, diff -Nru freerdp2-2.10.0+dfsg1/client/X11/xf_gfx.c freerdp2-2.11.7+dfsg1/client/X11/xf_gfx.c --- freerdp2-2.10.0+dfsg1/client/X11/xf_gfx.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/X11/xf_gfx.c 2024-04-22 09:26:59.000000000 +0000 @@ -288,7 +288,7 @@ surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format); surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad); - size = surface->gdi.scanline * surface->gdi.height * 1ULL; + size = 1ull * surface->gdi.scanline * surface->gdi.height; surface->gdi.data = (BYTE*)_aligned_malloc(size, 16); if (!surface->gdi.data) @@ -312,7 +312,7 @@ UINT32 bytes = GetBytesPerPixel(gdi->dstFormat); surface->stageScanline = width * bytes; surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad); - size = surface->stageScanline * surface->gdi.height * 1ULL; + size = 1ull * surface->stageScanline * surface->gdi.height; surface->stage = (BYTE*)_aligned_malloc(size, 16); if (!surface->stage) diff -Nru freerdp2-2.10.0+dfsg1/client/X11/xf_graphics.c freerdp2-2.11.7+dfsg1/client/X11/xf_graphics.c --- freerdp2-2.10.0+dfsg1/client/X11/xf_graphics.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/X11/xf_graphics.c 2024-04-22 09:26:59.000000000 +0000 @@ -311,7 +311,7 @@ ci.height = yTargetSize; ci.xhot = pointer->xPos * xscale; ci.yhot = pointer->yPos * yscale; - size = ci.height * ci.width * GetBytesPerPixel(CursorFormat) * 1ULL; + size = 1ull * ci.height * ci.width * GetBytesPerPixel(CursorFormat); if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16))) { @@ -421,7 +421,7 @@ xpointer->nCursors = 0; xpointer->mCursors = 0; - size = pointer->height * pointer->width * GetBytesPerPixel(CursorFormat) * 1ULL; + size = 1ull * pointer->height * pointer->width * GetBytesPerPixel(CursorFormat); if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16))) goto fail; @@ -560,7 +560,7 @@ } WLog_DBG(TAG, "%s: %" PRIu32 "x%" PRIu32, __func__, x, y); - if (xfc->remote_app && !xfc->focused) + if (!xfc->focused) return TRUE; xf_adjust_coordinates_to_screen(xfc, &x, &y); @@ -583,7 +583,7 @@ goto out; } - rc = XWarpPointer(xfc->display, None, handle, 0, 0, 0, 0, x, y); + rc = XWarpPointer(xfc->display, handle, handle, 0, 0, 0, 0, x, y); if (rc == 0) WLog_WARN(TAG, "%s: XWarpPointer==%d", __func__, rc); tmp.event_mask = current.your_event_mask; diff -Nru freerdp2-2.10.0+dfsg1/client/X11/xf_rail.c freerdp2-2.11.7+dfsg1/client/X11/xf_rail.c --- freerdp2-2.10.0+dfsg1/client/X11/xf_rail.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/X11/xf_rail.c 2024-04-22 09:26:59.000000000 +0000 @@ -544,7 +544,7 @@ cache->numCaches = settings->RemoteAppNumIconCaches; cache->numCacheEntries = settings->RemoteAppNumIconCacheEntries; - cache->entries = calloc(cache->numCaches * cache->numCacheEntries * 1ULL, sizeof(xfRailIcon)); + cache->entries = calloc(1ull * cache->numCaches * cache->numCacheEntries, sizeof(xfRailIcon)); if (!cache->entries) { @@ -614,7 +614,7 @@ long* pixels; int i; int nelements; - argbPixels = calloc(iconInfo->width * iconInfo->height * 1ULL, 4); + argbPixels = calloc(1ull * iconInfo->width * iconInfo->height, 4); if (!argbPixels) goto error; diff -Nru freerdp2-2.10.0+dfsg1/client/common/cmdline.c freerdp2-2.11.7+dfsg1/client/common/cmdline.c --- freerdp2-2.10.0+dfsg1/client/common/cmdline.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/common/cmdline.c 2024-04-22 09:26:59.000000000 +0000 @@ -2728,7 +2728,10 @@ if (strcmp(arg->Value, "video") == 0) settings->RemoteFxCodecMode = 0x00; else if (strcmp(arg->Value, "image") == 0) + { + settings->RemoteFxImageCodec = TRUE; settings->RemoteFxCodecMode = 0x02; + } } CommandLineSwitchCase(arg, "frame-ack") { @@ -2996,6 +2999,10 @@ { settings->GrabKeyboard = enable; } + CommandLineSwitchCase(arg, "grab-mouse") + { + settings->GrabMouse = enable; + } CommandLineSwitchCase(arg, "unmap-buttons") { settings->UnmapButtons = enable; diff -Nru freerdp2-2.10.0+dfsg1/client/common/cmdline.h freerdp2-2.11.7+dfsg1/client/common/cmdline.h --- freerdp2-2.10.0+dfsg1/client/common/cmdline.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/client/common/cmdline.h 2024-04-22 09:26:59.000000000 +0000 @@ -184,6 +184,7 @@ { "gp", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway password" }, { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab keyboard" }, + { "grab-mouse", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab mouse" }, { "gt", COMMAND_LINE_VALUE_REQUIRED, "[rpc|http[,no-websockets]|auto[,no-websockets]]", NULL, NULL, -1, NULL, "Gateway transport type" }, { "gu", COMMAND_LINE_VALUE_REQUIRED, "[[\\]|[@]]", NULL, NULL, -1, diff -Nru freerdp2-2.10.0+dfsg1/cmake/ClangDetectTool.cmake freerdp2-2.11.7+dfsg1/cmake/ClangDetectTool.cmake --- freerdp2-2.10.0+dfsg1/cmake/ClangDetectTool.cmake 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/cmake/ClangDetectTool.cmake 2024-04-22 09:26:59.000000000 +0000 @@ -0,0 +1,48 @@ +function (clang_detect_tool VAR NAME OPTS) + set(NAMES "") + foreach(CNT RANGE 12 22) + list(APPEND NAMES "${NAME}-${CNT}") + endforeach() + list(REVERSE NAMES) + list(APPEND NAMES ${NAME}) + + find_program(${VAR} + NAMES ${NAMES} + ${OPTS} + ) + if (NOT ${VAR}) + message(WARNING "clang tool ${NAME} (${VAR}) not detected, skipping") + unset(${VAR}) + return() + endif() + + execute_process( + COMMAND ${${VAR}} "--version" + OUTPUT_VARIABLE _CLANG_TOOL_VERSION + RESULT_VARIABLE _CLANG_TOOL_VERSION_FAILED + ) + + if (_CLANG_TOOL_VERSION_FAILED) + message(WARNING "A problem was encounterd with ${${VAR}}") + message(WARNING "${_CLANG_TOOL_VERSION_FAILED}") + unset(${VAR}) + return() + endif() + + string(REGEX MATCH "([7-9]|[1-9][0-9])\\.[0-9]\\.[0-9]" CLANG_TOOL_VERSION + "${_CLANG_TOOL_VERSION}") + + if (NOT CLANG_TOOL_VERSION) + message(WARNING "problem parsing ${NAME} version for ${${VAR}}") + unset(${VAR}) + return() + endif() + + set(_CLANG_TOOL_MINIMUM_VERSION "12.0.0") + if (${CLANG_TOOL_VERSION} VERSION_LESS ${_CLANG_TOOL_MINIMUM_VERSION}) + message(WARNING "clang-format version ${CLANG_TOOL_VERSION} not supported") + message(WARNING "Minimum version required: ${_CLANG_TOOL_MINIMUM_VERSION}") + unset(${VAR}) + return() + endif() +endfunction() diff -Nru freerdp2-2.10.0+dfsg1/cmake/ClangFormat.cmake freerdp2-2.11.7+dfsg1/cmake/ClangFormat.cmake --- freerdp2-2.10.0+dfsg1/cmake/ClangFormat.cmake 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/cmake/ClangFormat.cmake 2024-04-22 09:26:59.000000000 +0000 @@ -1,43 +1,12 @@ # get all project files file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.c *.h *.m *.java) -# minimum version required -set(_CLANG_FORMAT_MINIMUM_VERSION 7.0.0) -find_program(CLANG_FORMAT - NAMES - clang-format-8 - clang-format-7 - clang-format - ) +include(ClangDetectTool) +clang_detect_tool(CLANG_FORMAT clang-format "") if (NOT CLANG_FORMAT) message(WARNING "clang-format not found in path! code format target not available.") else() - execute_process( - COMMAND ${CLANG_FORMAT} "--version" - OUTPUT_VARIABLE _CLANG_FORMAT_VERSION - RESULT_VARIABLE _CLANG_FORMAT_VERSION_FAILED - ) - - if (_CLANG_FORMAT_VERSION_FAILED) - message(WARNING "A problem was encounterd with ${CLANG_FORMAT}") - return() - endif() - - string(REGEX MATCH "([7-9]|[1-9][0-9])\\.[0-9]\\.[0-9]" CLANG_FORMAT_VERSION - "${_CLANG_FORMAT_VERSION}") - - if (NOT CLANG_FORMAT_VERSION) - message(WARNING "problem parsing clang-fromat version for ${CLANG_FORMAT}") - return() - endif() - - if (${CLANG_FORMAT_VERSION} VERSION_LESS ${_CLANG_FORMAT_MINIMUM_VERSION}) - message(WARNING "clang-format version ${CLANG_FORMAT_VERSION} not supported") - message(WARNING "Minimum version required: ${_CLANG_FORMAT_MINIMUM_VERSION}") - return() - endif() - add_custom_target( clangformat COMMAND ${CLANG_FORMAT} diff -Nru freerdp2-2.10.0+dfsg1/cmake/ConfigOptions.cmake freerdp2-2.11.7+dfsg1/cmake/ConfigOptions.cmake --- freerdp2-2.10.0+dfsg1/cmake/ConfigOptions.cmake 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/cmake/ConfigOptions.cmake 2024-04-22 09:26:59.000000000 +0000 @@ -47,12 +47,12 @@ CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_ADDRESS "Compile with gcc/clang address sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_MEMORY; NOT WITH_SANITIZE_THREAD" OFF) CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_MEMORY "Compile with gcc/clang memory sanitizer." OFF - "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_THREAD" OFF) + "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_THREAD" OFF) CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_THREAD "Compile with gcc/clang thread sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_MEMORY" OFF) else() if(NOT UWP) - option(WITH_MEDIA_FOUNDATION "Enable H264 media foundation decoder." ON) + option(WITH_MEDIA_FOUNDATION "Enable H264 media foundation decoder." OFF) endif() endif() @@ -98,7 +98,7 @@ option(WITH_DEBUG_ALL "Print all debug messages." OFF) if(WITH_DEBUG_ALL) - message(WARNING "WITH_DEBUG_ALL=ON, the build will be slow and might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_ALL=ON, the build will be slow and might leak sensitive information, do not use with release builds!") set(DEFAULT_DEBUG_OPTION "ON") else() set(DEFAULT_DEBUG_OPTION "OFF") @@ -106,7 +106,7 @@ option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." ${DEFAULT_DEBUG_OPTION}) if(WITH_DEBUG_CERTIFICATE) - message(WARNING "WITH_DEBUG_CERTIFICATE=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_CERTIFICATE=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION}) @@ -116,23 +116,23 @@ CMAKE_DEPENDENT_OPTION(WITH_DEBUG_TSMF "Print TSMF virtual channel debug messages." ${DEFAULT_DEBUG_OPTION} "CHANNEL_TSMF" OFF) option(WITH_DEBUG_KBD "Print keyboard related debug messages." OFF) if(WITH_DEBUG_KBD) - message(WARNING "WITH_DEBUG_KBD=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_KBD=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_LICENSE "Print license debug messages." OFF) if(WITH_DEBUG_LICENSE) - message(WARNING "WITH_DEBUG_LICENSE=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_LICENSE=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_NEGO "Print negotiation related debug messages." OFF) if(WITH_DEBUG_NEGO) - message(WARNING "WITH_DEBUG_NEGO=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_NEGO=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_NLA "Print authentication related debug messages." OFF) if(WITH_DEBUG_NLA) - message(WARNING "WITH_DEBUG_NLA=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_NLA=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_NTLM "Print NTLM debug messages" OFF) if(WITH_DEBUG_NTLM) - message(WARNING "WITH_DEBUG_NTLM=ON, the build might leak sensitive information, do not use with release builds!") + message(WARNING "WITH_DEBUG_NTLM=ON, the build might leak sensitive information, do not use with release builds!") endif() option(WITH_DEBUG_TSG "Print Terminal Server Gateway debug messages" ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_RAIL "Print RemoteApp debug messages" ${DEFAULT_DEBUG_OPTION}) @@ -163,13 +163,13 @@ option(WITH_DSP_EXPERIMENTAL "Enable experimental sound encoder/decoder formats" OFF) if (WITH_FFMPEG) - option(WITH_DSP_FFMPEG "Use FFMPEG for audio encoding/decoding" OFF) - option(WITH_VAAPI "Use FFMPEG VAAPI (EXPERIMENTAL)" OFF) + option(WITH_DSP_FFMPEG "Use FFMPEG for audio encoding/decoding" OFF) + option(WITH_VAAPI "Use FFMPEG VAAPI (EXPERIMENTAL)" OFF) endif(WITH_FFMPEG) option(USE_VERSION_FROM_GIT_TAG "Extract FreeRDP version from git tag." OFF) -option(WITH_CAIRO "Use CAIRO image library for screen resizing" OFF) +option(WITH_CAIRO "Use CAIRO image library for screen resizing" OFF) option(WITH_SWSCALE "Use SWScale image library for screen resizing" OFF) option(DEFINE_NO_DEPRECATED "Compile without legacy functions and symbols" OFF) diff -Nru freerdp2-2.10.0+dfsg1/cmake/FindOpenSSL.cmake freerdp2-2.11.7+dfsg1/cmake/FindOpenSSL.cmake --- freerdp2-2.10.0+dfsg1/cmake/FindOpenSSL.cmake 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/cmake/FindOpenSSL.cmake 2024-04-22 09:26:59.000000000 +0000 @@ -55,7 +55,7 @@ NAMES openssl/ssl.h PATH_SUFFIXES - "include" + "include" HINTS ${_OPENSSL_INCLUDEDIR} ${_OPENSSL_ROOT_HINTS_AND_PATHS} @@ -172,8 +172,8 @@ ) set( OPENSSL_DEBUG_LIBRARIES ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} ) - set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) - set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} ) + set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) + set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} ) MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE) MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE) @@ -313,25 +313,50 @@ string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$" "\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}") - list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR) - list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR) - from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR) - list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX) - from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX) - list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH) - - if (NOT OPENSSL_VERSION_PATCH STREQUAL "00") - from_hex("${OPENSSL_VERSION_PATCH}" _tmp) - # 96 is the ASCII code of 'a' minus 1 - math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96") - unset(_tmp) - # Once anyone knows how OpenSSL would call the patch versions beyond 'z' - # this should be updated to handle that, too. This has not happened yet - # so it is simply ignored here for now. - string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING) - endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00") + if (OPENSSL_VERSION_LIST) + list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR) + list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR) + from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR) + list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX) + from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX) + list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH) + + if (NOT OPENSSL_VERSION_PATCH STREQUAL "00") + from_hex("${OPENSSL_VERSION_PATCH}" _tmp) + # 96 is the ASCII code of 'a' minus 1 + math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96") + unset(_tmp) + # Once anyone knows how OpenSSL would call the patch versions beyond 'z' + # this should be updated to handle that, too. This has not happened yet + # so it is simply ignored here for now. + string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING) + endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00") - set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}") + set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}") + endif() + + if (NOT OPENSSL_VERSION_LIST) + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]\"([0-9a-fA-F]+)\\.([0-9a-fA-F]+)\\.([0-9a-fA-F]+).*\".*$") + string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9a-fA-F]+)\\.([0-9a-fA-F]+)\\.([0-9a-fA-F]+).*\".*$" + "\\1.\\2.\\3" OPENSSL_VERSION "${openssl_version_str_str}") + endif() + + if (NOT OPENSSL_VERSION_LIST) + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_major_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_MAJOR[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_MAJOR[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_MAJOR "${openssl_version_major_str}") + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_minor_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_MINOR[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_MINOR[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_MINOR "${openssl_version_minor_str}") + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_patch_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_PATCH[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_PATCH[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_PATCH "${openssl_version_patch_str}") + set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_PATCH}") + endif() endif (_OPENSSL_VERSION) endif (OPENSSL_INCLUDE_DIR) diff -Nru freerdp2-2.10.0+dfsg1/debian/changelog freerdp2-2.11.7+dfsg1/debian/changelog --- freerdp2-2.10.0+dfsg1/debian/changelog 2023-02-26 20:59:16.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/changelog 2025-04-19 15:02:34.000000000 +0000 @@ -1,3 +1,150 @@ +freerdp2 (2.11.7+dfsg1-6~deb12u1) bookworm; urgency=high + + * Non-maintainer upload by the LTS Team for stable proposed updates. + * Revert time64_t transition commits, as they are not applicable to bookworm. + * Revert turning on keberos support. + * Reverting B-D: Depend on pkg-config instead of pkgconf. + * Do not use ffmpeg7 patch, bookworm is still at ffmpeg5. + + -- Tobias Frost Sat, 19 Apr 2025 17:02:34 +0200 + +freerdp2 (2.11.7+dfsg1-6) unstable; urgency=medium + + * Team upload + * d/tests/connect: use /cert-tofu to avoid errors with proxies + + -- Adrien Nader Wed, 18 Dec 2024 13:02:02 +0100 + +freerdp2 (2.11.7+dfsg1-5) unstable; urgency=medium + + * autopkgtest: add Depends: ca-certificates + + -- Jeremy Bícha Mon, 16 Dec 2024 22:57:23 -0500 + +freerdp2 (2.11.7+dfsg1-4) unstable; urgency=medium + + * Replace autopkgtests with the tests used by freerdp3 (Closes: #1079025) + + -- Jeremy Bícha Fri, 04 Oct 2024 16:21:36 -0400 + +freerdp2 (2.11.7+dfsg1-3) unstable; urgency=high + + * Team upload + + [ Jeremy Bícha ] + * SECURITY UPDATE: NULL access and crash (Closes: #1072112 + - debian/patches/CVE-2024-32661.patch: fix missing check in + rdp_write_logon_info_v1 in libfreerdp/core/info.c. + - CVE-2024-32661 + * Cherry-pick several patches to fix build with gcc-14 + (Closes: #1074969) (LP: #2075965) + * Remove obsolete 32-bit time transition lintian overrides + + [ Sébastien Noel ] + * Add patch to fix build with ffmpeg 7 (Closes: #1072413) + + [ Bernhard Übelacker ] + * Apply multiple fixes to autopkgtests (Closes: #1079025) + + -- Jeremy Bícha Thu, 03 Oct 2024 11:10:42 -0400 + +freerdp2 (2.11.7+dfsg1-2) unstable; urgency=medium + + * debian/tests/control: + + Add xauth. Fix tests on Debian, where xvfb does not pull-in xauth as + dependency (other than in Ubuntu). + + -- Mike Gabriel Sat, 20 Jul 2024 15:37:09 +0200 + +freerdp2 (2.11.7+dfsg1-1) unstable; urgency=medium + + [ Mike Gabriel ] + * New upstream release. (Closes: #1069728). + + CVE-2024-32041 [Low[ OutOfBound Read in zgfx_decompress_segment. + + CVE-2024-32039 [Moderate] Integer overflow & OutOfBound Write in + clear_decompress_residual_data. + + CVE-2024-32040 [Low] integer underflow in nsc_rle_decode. + + CVE-2024-32458 [Low] OutOfBound Read in planar_skip_plane_rle. + + CVE-2024-32459 [Low] OutOfBound Read in ncrush_decompress. + + CVE-2024-32460 [Low] OutOfBound Read in interleaved_decompress. + + [ Nathan Pratta Teodosio ] + * Add autopkgtest to test whether a client can connect + to an XRDP server via freerdp2 and that the login screen shows up + (Closes: #1073156) (LP: #2060976) + + -- Mike Gabriel Mon, 15 Jul 2024 16:46:25 +0200 + +freerdp2 (2.11.5+dfsg1-1) unstable; urgency=medium + + * New upstream release. + - CVE-2024-22211: Fix integer overflow in progressive decoder. (Closes: + #1061173). + * Upload time_t64 changes to unstable. (Closes: #1061952). + * debian/watch: + + Adjust so we only see 2.x release. + * debian/control: + + Switch from pkg-config to pkgconf. Thanks, lintian. + + -- Mike Gabriel Mon, 25 Mar 2024 16:09:04 +0100 + +freerdp2 (2.11.2+dfsg1-1.1~exp2) experimental; urgency=medium + + * Non-maintainer upload. + * Rename libraries for 64-bit time_t transition. + * Account for additional t64 Breaks/Replaces (Closes #1061982). + + -- Lukas Märdian Tue, 30 Jan 2024 13:19:02 +0000 + +freerdp2 (2.11.2+dfsg1-1) unstable; urgency=medium + + * New upstream release. (Closes: #1051638). + * Fixed security issues since v2.11.0: + - CVE-2023-40589: [codec,ncrush] fix index checks properly verify all + offsets while decoding data. + - CVE-2023-40567: Fix out-of-bounds write in the + `clear_decompress_bands_data` function. + - CVE-2023-40188: Fix out-of-bounds read in the `general_LumaToYUV444` + function. + - CVE-2023-40186: Fix out-of-bounds write in the `gdi_CreateSurface` + function. + - CVE-2023-40181: Fix out-of-bounds read in the `zgfx_decompress_segment` + function. + - CVE-2023-39356: Fix out-of-bounds read in the `gdi_multi_opaque_rect` + function. + - CVE-2023-39355: Fix use-after-free in processing + `RDPGFX_CMDID_RESETGRAPHICS` packets. + - CVE-2023-39354: Fix out-of-bounds read in the `nsc_rle_decompress_data` + function. + - CVE-2023-39353: Fix missing offset validation leading to out-of-bounds + read in the `libfreerdp/codec/rfx.c` file. + - CVE-2023-39352: Fix invalid offset validation leading to out-of-bounds + write. + - CVE-2023-39351: Fix null-pointer-dereference leading a crash in the + RemoteFX (rfx) handling. + - CVE-2023-39350: Fix integer underflow leading to DOS (e.g. abort due to + `WINPR_ASSERT` with default compilation flags). + * debian/patches: + + Drop 0001_fix_ftbfs_1041377.patch. Applied upstream. + * debian/control: + + Add B-D: libkrb5-dev. + * debian/rules: + + Add -DWITH_KERBEROS=ON configure option. (Closes: #1036095). + * debian/watch: + + Rework file. Find all released versions of freerdp2. (Closes: #1053317). + Thanks to Tobias Frost for sending a patch. + + -- Mike Gabriel Sun, 01 Oct 2023 23:21:15 +0200 + +freerdp2 (2.10.0+dfsg1-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * debian/patches/0001_fix_ftbfs_1041377.patch: + - include upstream fix for FTBFS with FFmpeg 6.0 + (Closes: #1041377) + + -- Héctor Orón Martínez Fri, 04 Aug 2023 04:08:40 -0400 + freerdp2 (2.10.0+dfsg1-1) unstable; urgency=medium * New upstream release. diff -Nru freerdp2-2.10.0+dfsg1/debian/control freerdp2-2.11.7+dfsg1/debian/control --- freerdp2-2.10.0+dfsg1/debian/control 2023-02-26 20:51:31.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/control 2025-04-19 15:02:29.000000000 +0000 @@ -90,8 +90,10 @@ ${shlibs:Depends}, libwinpr2-2 (= ${binary:Version}), Breaks: + libfreerdp2-2 (<< ${source:Version}), libfreerdp2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libfreerdp2-2, libfreerdp2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Suggests: @@ -112,8 +114,10 @@ ${shlibs:Depends}, libfreerdp2-2 (= ${binary:Version}), Breaks: + libfreerdp-client2-2 (<< ${source:Version}), libfreerdp-client2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libfreerdp-client2-2, libfreerdp-client2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: Free Remote Desktop Protocol library (client library) @@ -132,8 +136,10 @@ ${shlibs:Depends}, libfreerdp2-2 (= ${binary:Version}), Breaks: + libfreerdp-server2-2 (<< ${source:Version}), libfreerdp-server2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libfreerdp-server2-2, libfreerdp-server2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: Free Remote Desktop Protocol library (server library) @@ -151,8 +157,10 @@ ${misc:Depends}, ${shlibs:Depends}, Breaks: + libwinpr2-2 (<< ${source:Version}), libwinpr2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libwinpr2-2, libwinpr2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Suggests: @@ -179,8 +187,10 @@ ${shlibs:Depends}, libwinpr2-2 (= ${binary:Version}), Breaks: + libwinpr-tools2-2 (<< ${source:Version}), libwinpr-tools2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libwinpr-tools2-2, libwinpr-tools2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: Windows Portable Runtime Tools library @@ -260,8 +270,10 @@ libfreerdp-server2-2 (= ${binary:Version}), libwinpr-tools2-2 (= ${binary:Version}), Breaks: + libfreerdp-shadow2-2 (<< ${source:Version}), libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libfreerdp-shadow2-2, libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: FreeRDP Remote Desktop Protocol shadow libraries @@ -280,8 +292,10 @@ ${shlibs:Depends}, libfreerdp-shadow2-2 (= ${binary:Version}), Breaks: + libfreerdp-shadow-subsystem2-2 (<< ${source:Version}), libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libfreerdp-shadow-subsystem2-2, libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: FreeRDP Remote Desktop Protocol shadow subsystem libraries @@ -315,8 +329,10 @@ ${shlibs:Depends}, libfreerdp2-2 (= ${binary:Version}), Breaks: + libuwac0-0 (<< ${source:Version}), libuwac0 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: + libuwac0-0, libuwac0 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Multi-Arch: same Description: Using wayland as a client library diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0001-info-Fix-incompatible-pointer-type.patch freerdp2-2.11.7+dfsg1/debian/patches/0001-info-Fix-incompatible-pointer-type.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0001-info-Fix-incompatible-pointer-type.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0001-info-Fix-incompatible-pointer-type.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,32 @@ +From: Alessandro Bono +Date: Wed, 8 May 2024 16:06:17 +0200 +Subject: info: Fix incompatible pointer type +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This fixes the following: +``` +libfreerdp/core/info.c: In function ‘rdp_read_info_null_string’: +libfreerdp/core/info.c:88:39: error: initialization of ‘const WCHAR *’ {aka ‘const short unsigned int *’} from incompatible pointer type ‘BYTE *’ {aka ‘unsigned char *’} [-Wincompatible-pointer-types] + 88 | const WCHAR* domain = Stream_Pointer(s); +``` + +(cherry picked from commit 4f411197dc9d2076f00748b1178a60b2423030bf) +--- + libfreerdp/core/info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c +index 9aaa6cf..c9b2fc6 100644 +--- a/libfreerdp/core/info.c ++++ b/libfreerdp/core/info.c +@@ -85,7 +85,7 @@ static BOOL rdp_read_info_null_string(const char* what, UINT32 flags, wStream* s + + if (cbLen > 0) + { +- const WCHAR* domain = Stream_Pointer(s); ++ const WCHAR* domain = (WCHAR*)Stream_Pointer(s); + + if (isNullTerminated && (max > 0)) + max -= nullSize; diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0002-redirection-Fix-incompatible-pointer-type.patch freerdp2-2.11.7+dfsg1/debian/patches/0002-redirection-Fix-incompatible-pointer-type.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0002-redirection-Fix-incompatible-pointer-type.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0002-redirection-Fix-incompatible-pointer-type.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,38 @@ +From: Alessandro Bono +Date: Wed, 8 May 2024 16:06:26 +0200 +Subject: redirection: Fix incompatible pointer type +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This fixes the following: +``` +libfreerdp/core/redirection.c: In function ‘redirection_copy_data’: +libfreerdp/core/redirection.c:91:31: error: passing argument 1 of ‘redirection_free_data’ from incompatible pointer type [-Wincompatible-pointer-types] + 91 | redirection_free_data(dst, plen); + | ^~~ + | | + | char ** +libfreerdp/core/redirection.c:80:42: note: expected ‘BYTE **’ {aka ‘unsigned char **’} but argument is of type ‘char **’ + 80 | static void redirection_free_data(BYTE** str, UINT32* length) + | ~~~~~~~^~~ +``` + +(cherry picked from commit f3ed1f1ac367eb21f93c9fba5047447fdccdb5cc) +--- + libfreerdp/core/redirection.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c +index 59c6dbc..63bc8cc 100644 +--- a/libfreerdp/core/redirection.c ++++ b/libfreerdp/core/redirection.c +@@ -86,7 +86,7 @@ static void redirection_free_data(BYTE** str, UINT32* length) + *str = NULL; + } + +-static BOOL redirection_copy_data(char** dst, UINT32* plen, const char* str, UINT32 len) ++static BOOL redirection_copy_data(BYTE** dst, UINT32* plen, const BYTE* str, UINT32 len) + { + redirection_free_data(dst, plen); + diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0003-redirection-Fix-incompatible-pointer-type.patch freerdp2-2.11.7+dfsg1/debian/patches/0003-redirection-Fix-incompatible-pointer-type.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0003-redirection-Fix-incompatible-pointer-type.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0003-redirection-Fix-incompatible-pointer-type.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,33 @@ +From: Alessandro Bono +Date: Wed, 8 May 2024 16:06:30 +0200 +Subject: redirection: Fix incompatible pointer type +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This fixes the following: +``` +libfreerdp/core/redirection.c: In function ‘freerdp_settings_set_pointer_len’: +libfreerdp/core/redirection.c:112:31: error: assignment to ‘BYTE **’ {aka ‘unsigned char **’} from incompatible pointer type ‘char **’ [-Wincompatible-pointer-types] + 112 | pdata = &settings->TargetNetAddress; + | ^ +``` + +(cherry picked from commit 7894a7dfc5f811cb5dacc57a09236c11744b1ec8) +--- + libfreerdp/core/redirection.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c +index 63bc8cc..4872d4b 100644 +--- a/libfreerdp/core/redirection.c ++++ b/libfreerdp/core/redirection.c +@@ -109,7 +109,7 @@ static BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, c + switch (id) + { + case FreeRDP_TargetNetAddress: +- pdata = &settings->TargetNetAddress; ++ pdata = (BYTE**)&settings->TargetNetAddress; + plen = &settings->TargetNetAddressCount; + break; + case FreeRDP_LoadBalanceInfo: diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0004-X11-fix-pointer-integer-type-mismatch.patch freerdp2-2.11.7+dfsg1/debian/patches/0004-X11-fix-pointer-integer-type-mismatch.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0004-X11-fix-pointer-integer-type-mismatch.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0004-X11-fix-pointer-integer-type-mismatch.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,24 @@ +From: Mike Gilbert +Date: Wed, 22 May 2024 17:04:43 -0400 +Subject: X11: fix pointer/integer type mismatch + +Fixed on master in 2da280b8a1748052b70b3f5a1ef0d8e932c33adc. + +(cherry picked from commit d2b6771c748e54e659d5f1243a92e499c3beaa36) +--- + client/X11/xf_graphics.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c +index 5aa1fd4..fe81e0e 100644 +--- a/client/X11/xf_graphics.c ++++ b/client/X11/xf_graphics.c +@@ -438,7 +438,7 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) + + #endif + fail: +- WLog_DBG(TAG, "%s: %ld", __func__, rc ? pointer : -1); ++ WLog_DBG(TAG, "%s: %p", __func__, rc ? pointer : NULL); + return rc; + } + diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0005-client-wayland-fix-const-correctness.patch freerdp2-2.11.7+dfsg1/debian/patches/0005-client-wayland-fix-const-correctness.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0005-client-wayland-fix-const-correctness.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0005-client-wayland-fix-const-correctness.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,22 @@ +From: akallabeth +Date: Thu, 23 May 2024 09:30:33 +0200 +Subject: [client,wayland] fix const correctness + +(cherry picked from commit 67818bddb31900cdf3acb26cb0b673cc90b71cc9) +--- + client/Wayland/wlfreerdp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c +index 65e29bc..5988aed 100644 +--- a/client/Wayland/wlfreerdp.c ++++ b/client/Wayland/wlfreerdp.c +@@ -587,7 +587,7 @@ static void wlf_client_free(freerdp* instance, rdpContext* context) + DeleteCriticalSection(&wlf->critical); + } + +-static void* uwac_event_clone(const void* val) ++static void* uwac_event_clone(void* val) + { + UwacEvent* copy; + UwacEvent* ev = (UwacEvent*)val; diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0006-warnings-fix-Wincompatible-pointer-types.patch freerdp2-2.11.7+dfsg1/debian/patches/0006-warnings-fix-Wincompatible-pointer-types.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0006-warnings-fix-Wincompatible-pointer-types.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0006-warnings-fix-Wincompatible-pointer-types.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,89 @@ +From: Armin Novak +Date: Thu, 8 Aug 2024 11:03:24 +0200 +Subject: [warnings] fix -Wincompatible-pointer-types + +(cherry picked from commit 5b2b53b15c9af46b85c4ef0007e7fb59d7608289) +--- + channels/ainput/server/ainput_main.c | 8 ++++---- + libfreerdp/codec/dsp_ffmpeg.c | 2 +- + winpr/libwinpr/crt/unicode.c | 8 ++++---- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/channels/ainput/server/ainput_main.c b/channels/ainput/server/ainput_main.c +index 943d0fa..fc61f9b 100644 +--- a/channels/ainput/server/ainput_main.c ++++ b/channels/ainput/server/ainput_main.c +@@ -222,7 +222,7 @@ static HANDLE ainput_server_get_channel_handle(ainput_server* ainput) + + WINPR_ASSERT(ainput); + +- if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualEventHandle, &buffer, ++ if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualEventHandle, (void**)&buffer, + &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) +@@ -416,7 +416,7 @@ ainput_server_context* ainput_server_context_new(HANDLE vcm) + goto fail; + return &ainput->context; + fail: +- ainput_server_context_free(ainput); ++ ainput_server_context_free(&ainput->context); + return NULL; + } + +@@ -539,8 +539,8 @@ UINT ainput_server_context_poll_int(ainput_server_context* context) + BYTE* buffer = NULL; + DWORD BytesReturned = 0; + +- if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualChannelReady, &buffer, +- &BytesReturned) != TRUE) ++ if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualChannelReady, ++ (void**)&buffer, &BytesReturned) != TRUE) + { + WLog_ERR(TAG, "WTSVirtualChannelReady failed,"); + } +diff --git a/libfreerdp/codec/dsp_ffmpeg.c b/libfreerdp/codec/dsp_ffmpeg.c +index ef67914..80df188 100644 +--- a/libfreerdp/codec/dsp_ffmpeg.c ++++ b/libfreerdp/codec/dsp_ffmpeg.c +@@ -423,7 +423,7 @@ static BOOL ffmpeg_encode_frame(AVCodecContext* context, AVFrame* in, AVPacket* + uint8_t** pp = in->extended_data; + for (int y = 0; y < in->channels; y++) + { +- float* data = pp[y]; ++ float* data = (float*)pp[y]; + for (int x = 0; x < in->nb_samples; x++) + { + const float val1 = data[x]; +diff --git a/winpr/libwinpr/crt/unicode.c b/winpr/libwinpr/crt/unicode.c +index dc3533a..acbec01 100644 +--- a/winpr/libwinpr/crt/unicode.c ++++ b/winpr/libwinpr/crt/unicode.c +@@ -215,8 +215,8 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int + else + { + targetLength = +- ucnv_convert("UTF-16LE", "UTF-8", targetStart, targetCapacity * sizeof(WCHAR), +- lpMultiByteStr, cbMultiByte, &error); ++ ucnv_convert("UTF-16LE", "UTF-8", (char*)targetStart, ++ targetCapacity * sizeof(WCHAR), lpMultiByteStr, cbMultiByte, &error); + if (targetLength > 0) + targetLength /= sizeof(WCHAR); + cchWideChar = U_SUCCESS(error) ? targetLength : 0; +@@ -353,14 +353,14 @@ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int + #if defined(UCNV_CONVERT) + if (cbMultiByte == 0) + { +- targetLength = ucnv_convert("UTF-8", "UTF-16LE", NULL, 0, lpWideCharStr, ++ targetLength = ucnv_convert("UTF-8", "UTF-16LE", NULL, 0, (char*)lpWideCharStr, + cchWideChar * sizeof(WCHAR), &error); + cbMultiByte = targetLength; + } + else + { + targetLength = ucnv_convert("UTF-8", "UTF-16LE", targetStart, targetCapacity, +- lpWideCharStr, cchWideChar * sizeof(WCHAR), &error); ++ (char*)lpWideCharStr, cchWideChar * sizeof(WCHAR), &error); + cbMultiByte = U_SUCCESS(error) ? targetLength : 0; + } + diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/0007-server-proxy-deactivate-capture-module.patch freerdp2-2.11.7+dfsg1/debian/patches/0007-server-proxy-deactivate-capture-module.patch --- freerdp2-2.10.0+dfsg1/debian/patches/0007-server-proxy-deactivate-capture-module.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/0007-server-proxy-deactivate-capture-module.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,48 @@ +From: Armin Novak +Date: Thu, 8 Aug 2024 11:06:54 +0200 +Subject: [server,proxy] deactivate capture module + +the module does not work (and did not for a long time) + +(cherry picked from commit be23ed4ba990bd39391a651444fbb9130722c93b) +--- + server/proxy/modules/capture/CMakeLists.txt | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/server/proxy/modules/capture/CMakeLists.txt b/server/proxy/modules/capture/CMakeLists.txt +index 80ba3b7..4004aaa 100644 +--- a/server/proxy/modules/capture/CMakeLists.txt ++++ b/server/proxy/modules/capture/CMakeLists.txt +@@ -17,17 +17,19 @@ + # limitations under the License. + # + +-set(PLUGIN_NAME "proxy-capture-plugin") ++# deactivated: does not work + +-add_library(${PLUGIN_NAME} MODULE +- cap_main.c +- cap_config.c +- cap_config.h +- cap_protocol.c +- cap_protocol.h +-) +- +-set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "") +-set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1) +-set_target_properties(${PLUGIN_NAME} PROPERTIES +-LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}") ++#set(PLUGIN_NAME "proxy-capture-plugin") ++# ++#add_library(${PLUGIN_NAME} MODULE ++# cap_main.c ++# cap_config.c ++# cap_config.h ++# cap_protocol.c ++# cap_protocol.h ++#) ++# ++#set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "") ++#set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1) ++#set_target_properties(${PLUGIN_NAME} PROPERTIES ++#LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}") diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/1000-ffmpeg7.patch freerdp2-2.11.7+dfsg1/debian/patches/1000-ffmpeg7.patch --- freerdp2-2.10.0+dfsg1/debian/patches/1000-ffmpeg7.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/1000-ffmpeg7.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,114 @@ +From: =?utf-8?q?S=C3=A9bastien_Noel?= +Date: Tue, 30 Jul 2024 11:29:58 +0200 +Subject: Fix build with ffmpeg 7 + +cherry picked from d0c5b1ae4289c7f3cde3fbc031cb4a3160df05ff +from freerdp3 +--- + libfreerdp/codec/dsp_ffmpeg.c | 28 ++++++++++------------------ + 1 file changed, 10 insertions(+), 18 deletions(-) + +diff --git a/libfreerdp/codec/dsp_ffmpeg.c b/libfreerdp/codec/dsp_ffmpeg.c +index 80df188..68dfe5f 100644 +--- a/libfreerdp/codec/dsp_ffmpeg.c ++++ b/libfreerdp/codec/dsp_ffmpeg.c +@@ -225,18 +225,15 @@ static void ffmpeg_close_context(FREERDP_DSP_CONTEXT* context) + static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context) + { + int ret; +- int layout; +- const AUDIO_FORMAT* format; + + if (!context || context->isOpen) + return FALSE; + +- format = &context->format; ++ const AUDIO_FORMAT* format = &context->format; + + if (!format) + return FALSE; + +- layout = av_get_default_channel_layout(format->nChannels); + context->id = ffmpeg_get_avcodec(format); + + if (ffmpeg_codec_is_filtered(context->id, context->encoder)) +@@ -270,8 +267,7 @@ static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context) + break; + } + +- context->context->channels = format->nChannels; +- context->context->channel_layout = layout; ++ av_channel_layout_default(&context->context->ch_layout, format->nChannels); + context->context->sample_rate = format->nSamplesPerSec; + context->context->block_align = format->nBlockAlign; + context->context->bit_rate = format->nAvgBytesPerSec * 8; +@@ -314,8 +310,7 @@ static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context) + if (!context->rcontext) + goto fail; + +- context->frame->channel_layout = layout; +- context->frame->channels = format->nChannels; ++ av_channel_layout_default(&context->frame->ch_layout, format->nChannels); + context->frame->sample_rate = format->nSamplesPerSec; + context->frame->format = AV_SAMPLE_FMT_S16; + +@@ -330,13 +325,11 @@ static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* context) + context->resampled->sample_rate = format->nSamplesPerSec; + } + +- context->resampled->channel_layout = layout; +- context->resampled->channels = format->nChannels; ++ av_channel_layout_default(&context->resampled->ch_layout, format->nChannels); + + if (context->context->frame_size > 0) + { +- context->buffered->channel_layout = context->resampled->channel_layout; +- context->buffered->channels = context->resampled->channels; ++ av_channel_layout_copy(&context->buffered->ch_layout, &context->resampled->ch_layout); + context->buffered->format = context->resampled->format; + context->buffered->nb_samples = context->context->frame_size; + +@@ -421,7 +414,7 @@ static BOOL ffmpeg_encode_frame(AVCodecContext* context, AVFrame* in, AVPacket* + if (in->format == AV_SAMPLE_FMT_FLTP) + { + uint8_t** pp = in->extended_data; +- for (int y = 0; y < in->channels; y++) ++ for (int y = 0; y < in->ch_layout.nb_channels; y++) + { + float* data = (float*)pp[y]; + for (int x = 0; x < in->nb_samples; x++) +@@ -477,14 +470,13 @@ static BOOL ffmpeg_fill_frame(AVFrame* frame, const AUDIO_FORMAT* inputFormat, c + size_t size) + { + int ret, bpp; +- frame->channels = inputFormat->nChannels; ++ av_channel_layout_default(&frame->ch_layout, inputFormat->nChannels); + frame->sample_rate = inputFormat->nSamplesPerSec; + frame->format = ffmpeg_sample_format(inputFormat); +- frame->channel_layout = av_get_default_channel_layout(frame->channels); + bpp = av_get_bytes_per_sample(frame->format); + frame->nb_samples = size / inputFormat->nChannels / bpp; + +- if ((ret = avcodec_fill_audio_frame(frame, frame->channels, frame->format, data, size, 1)) < 0) ++ if ((ret = avcodec_fill_audio_frame(frame, inputFormat->nChannels, frame->format, data, size, 1)) < 0) + { + const char* err = av_err2str(ret); + WLog_ERR(TAG, "Error during audio frame fill %s [%d]", err, ret); +@@ -566,7 +558,7 @@ static BOOL ffmpeg_decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame + } + + { +- const size_t data_size = resampled->channels * resampled->nb_samples * 2; ++ const size_t data_size = resampled->ch_layout.nb_channels * resampled->nb_samples * 2; + Stream_EnsureRemainingCapacity(out, data_size); + Stream_Write(out, resampled->data[0], data_size); + } +@@ -664,7 +656,7 @@ BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* + rc = + av_samples_copy(context->buffered->extended_data, context->resampled->extended_data, + (int)context->bufferedSamples, copied, inSamples, +- context->context->channels, context->context->sample_fmt); ++ context->context->ch_layout.nb_channels, context->context->sample_fmt); + rest -= inSamples; + copied += inSamples; + context->bufferedSamples += (UINT32)inSamples; diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/CVE-2024-32661.patch freerdp2-2.11.7+dfsg1/debian/patches/CVE-2024-32661.patch --- freerdp2-2.10.0+dfsg1/debian/patches/CVE-2024-32661.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/CVE-2024-32661.patch 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,24 @@ +From: akallabeth +Date: Sun, 21 Apr 2024 13:56:13 +0200 +Subject: fix missing check in rdp_write_logon_info_v1 + +(cherrypicked from commit 71e463e31b4d69f4022d36bfc814592f56600793) +--- + libfreerdp/core/info.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c +index c9b2fc6..dc72b61 100644 +--- a/libfreerdp/core/info.c ++++ b/libfreerdp/core/info.c +@@ -1322,6 +1322,10 @@ static BOOL rdp_write_logon_info_v1(wStream* s, logon_info* info) + return FALSE; + + /* domain */ ++ WINPR_ASSERT(info); ++ if (!info->domain || !info->username) ++ return FALSE; ++ + ilen = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0); + + if (ilen < 0) diff -Nru freerdp2-2.10.0+dfsg1/debian/patches/series freerdp2-2.11.7+dfsg1/debian/patches/series --- freerdp2-2.10.0+dfsg1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/patches/series 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,9 @@ +0001-info-Fix-incompatible-pointer-type.patch +0002-redirection-Fix-incompatible-pointer-type.patch +0003-redirection-Fix-incompatible-pointer-type.patch +0004-X11-fix-pointer-integer-type-mismatch.patch +0005-client-wayland-fix-const-correctness.patch +0006-warnings-fix-Wincompatible-pointer-types.patch +0007-server-proxy-deactivate-capture-module.patch +#1000-ffmpeg7.patch +CVE-2024-32661.patch diff -Nru freerdp2-2.10.0+dfsg1/debian/tests/connect freerdp2-2.11.7+dfsg1/debian/tests/connect --- freerdp2-2.10.0+dfsg1/debian/tests/connect 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/tests/connect 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,22 @@ +#!/bin/sh -x +isNaturalNumber(){ + case "$1" in + ''|*[!0-9]*) return 0;; + *) return 1;; + esac +} + +sudo systemctl start xrdp +# XXX: Is there a better way to get the port number other than by parsing the +# configuration file? +port=$(sed -n '/^port=[0123456789]/{s/port=//p;q;}' /etc/xrdp/xrdp.ini) +if test ! isNaturalNumber "$port"; then + exit 1 +fi + +timeout 2s xvfb-run -l xfreerdp /v:localhost:"$port" /p: /u: /d: /cert-tofu +if test $? != 124; then + 2>&1 printf "%s\n" "Xfreerdp exited before the timeout, it has likely " \ + "failed to connect. The test has therefore failed." + exit 2 +fi diff -Nru freerdp2-2.10.0+dfsg1/debian/tests/control freerdp2-2.11.7+dfsg1/debian/tests/control --- freerdp2-2.10.0+dfsg1/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/tests/control 2025-04-19 15:02:29.000000000 +0000 @@ -0,0 +1,3 @@ +Tests: connect +Depends: @, ca-certificates, xauth, xrdp, xvfb +Restrictions: allow-stderr, needs-sudo diff -Nru freerdp2-2.10.0+dfsg1/debian/watch freerdp2-2.11.7+dfsg1/debian/watch --- freerdp2-2.10.0+dfsg1/debian/watch 2022-08-16 21:17:34.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/debian/watch 2025-04-19 15:02:29.000000000 +0000 @@ -3,5 +3,5 @@ filenamemangle=s/.*\/v?([\d\.-]+)\.tar\.gz/freerdp-$1.tar.gz/,\ dversionmangle=s/\+dfsg1//,\ repacksuffix=+dfsg1 \ -https://github.com/FreeRDP/FreeRDP/tags .*/archive/refs/tags/v?([\d\.]+).tar.gz \ +https://github.com/FreeRDP/FreeRDP/tags .*/archive/refs/tags/v?(2\.[\d\.]+).tar.gz \ debian diff -Nru freerdp2-2.10.0+dfsg1/include/freerdp/channels/rdpdr.h freerdp2-2.11.7+dfsg1/include/freerdp/channels/rdpdr.h --- freerdp2-2.10.0+dfsg1/include/freerdp/channels/rdpdr.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/include/freerdp/channels/rdpdr.h 2024-04-22 09:26:59.000000000 +0000 @@ -41,6 +41,14 @@ #define RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH 32 #define RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH 4 +#define RDPDR_VERSION_MAJOR 0x0001 + +#define RDPDR_VERSION_MINOR_RDP50 0x0002 +#define RDPDR_VERSION_MINOR_RDP51 0x0005 +#define RDPDR_VERSION_MINOR_RDP52 0x000A +#define RDPDR_VERSION_MINOR_RDP6X 0x000C +#define RDPDR_VERSION_MINOR_RDP10X 0x000D + /* RDPDR_HEADER.Component */ enum RDPDR_CTYP { diff -Nru freerdp2-2.10.0+dfsg1/include/freerdp/settings.h freerdp2-2.11.7+dfsg1/include/freerdp/settings.h --- freerdp2-2.10.0+dfsg1/include/freerdp/settings.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/include/freerdp/settings.h 2024-04-22 09:26:59.000000000 +0000 @@ -730,6 +730,7 @@ #define FreeRDP_PercentScreenUseWidth (1556) #define FreeRDP_PercentScreenUseHeight (1557) #define FreeRDP_DynamicResolutionUpdate (1558) +#define FreeRDP_GrabMouse (1559) #define FreeRDP_SoftwareGdi (1601) #define FreeRDP_LocalConnection (1602) #define FreeRDP_AuthenticationOnly (1603) @@ -1216,7 +1217,8 @@ ALIGN64 BOOL PercentScreenUseWidth; /* 1556 */ ALIGN64 BOOL PercentScreenUseHeight; /* 1557 */ ALIGN64 BOOL DynamicResolutionUpdate; /* 1558 */ - UINT64 padding1601[1601 - 1559]; /* 1559 */ + ALIGN64 BOOL GrabMouse; /* 1559 */ + UINT64 padding1601[1601 - 1560]; /* 1560 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/cache/pointer.c freerdp2-2.11.7+dfsg1/libfreerdp/cache/pointer.c --- freerdp2-2.10.0+dfsg1/libfreerdp/cache/pointer.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/cache/pointer.c 2024-04-22 09:26:59.000000000 +0000 @@ -68,6 +68,9 @@ !pointer_position) return FALSE; + if (!context->settings->GrabMouse) + return TRUE; + pointer = context->graphics->Pointer_Prototype; return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos, pointer_position->yPos); diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/clear.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/clear.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/clear.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/clear.c 2024-04-22 09:26:59.000000000 +0000 @@ -410,7 +410,7 @@ } } - if ((pixelIndex + runLengthFactor) > pixelCount) + if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex))) { WLog_ERR(TAG, "pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32 @@ -512,12 +512,12 @@ { case 0: /* Uncompressed */ { - UINT32 nSrcStep = width * GetBytesPerPixel(PIXEL_FORMAT_BGR24); - UINT32 nSrcSize = nSrcStep * height; + const UINT32 nSrcStep = width * GetBytesPerPixel(PIXEL_FORMAT_BGR24); + const size_t nSrcSize = 1ull * nSrcStep * height; if (bitmapDataByteCount != nSrcSize) { - WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIu32 "", + WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIuz "", bitmapDataByteCount, nSrcSize); return FALSE; } @@ -566,7 +566,7 @@ const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp; BYTE* tmp; vBarEntry->size = vBarEntry->count; - tmp = (BYTE*)realloc(vBarEntry->pixels, vBarEntry->count * bpp * 1ULL); + tmp = (BYTE*)realloc(vBarEntry->pixels, 1ull * vBarEntry->count * bpp); if (!tmp) { @@ -591,13 +591,9 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 bandsByteCount, UINT32 nWidth, UINT32 nHeight, BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, - UINT32 nYDst) + UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight) { - UINT32 i, y; - UINT32 count; - UINT32 suboffset; - UINT32 nXDstRel; - UINT32 nYDstRel; + UINT32 suboffset = 0; if (Stream_GetRemainingLength(s) < bandsByteCount) { @@ -605,22 +601,20 @@ return FALSE; } - suboffset = 0; - while (suboffset < bandsByteCount) { - BYTE r, g, b; + BYTE cr, cg, cb; UINT16 xStart; UINT16 xEnd; UINT16 yStart; UINT16 yEnd; UINT32 colorBkg; UINT16 vBarHeader; - UINT16 vBarYOn; + UINT16 vBarYOn = 0; UINT16 vBarYOff; UINT32 vBarCount; UINT32 vBarPixelCount; - UINT32 vBarShortPixelCount; + UINT32 vBarShortPixelCount = 0; if (Stream_GetRemainingLength(s) < 11) { @@ -632,11 +626,11 @@ Stream_Read_UINT16(s, xEnd); Stream_Read_UINT16(s, yStart); Stream_Read_UINT16(s, yEnd); - Stream_Read_UINT8(s, b); - Stream_Read_UINT8(s, g); - Stream_Read_UINT8(s, r); + Stream_Read_UINT8(s, cb); + Stream_Read_UINT8(s, cg); + Stream_Read_UINT8(s, cr); suboffset += 11; - colorBkg = FreeRDPGetColor(clear->format, r, g, b, 0xFF); + colorBkg = FreeRDPGetColor(clear->format, cr, cg, cb, 0xFF); if (xEnd < xStart) { @@ -652,13 +646,13 @@ vBarCount = (xEnd - xStart) + 1; - for (i = 0; i < vBarCount; i++) + for (UINT32 i = 0; i < vBarCount; i++) { UINT32 vBarHeight; CLEAR_VBAR_ENTRY* vBarEntry = NULL; - CLEAR_VBAR_ENTRY* vBarShortEntry; + CLEAR_VBAR_ENTRY* vBarShortEntry = NULL; BOOL vBarUpdate = FALSE; - const BYTE* pSrcPixel; + const BYTE* cpSrcPixel; if (Stream_GetRemainingLength(s) < 2) { @@ -740,11 +734,11 @@ if (!resize_vbar_entry(clear, vBarShortEntry)) return FALSE; - for (y = 0; y < vBarShortPixelCount; y++) + for (UINT32 y = 0; y < vBarShortPixelCount; y++) { - BYTE r, g, b; + BYTE r = 0, g = 0, b = 0; BYTE* dstBuffer = &vBarShortEntry->pixels[y * GetBytesPerPixel(clear->format)]; - UINT32 color; + UINT32 color = 0; Stream_Read_UINT8(s, b); Stream_Read_UINT8(s, g); Stream_Read_UINT8(s, r); @@ -804,8 +798,8 @@ dstBuffer = vBarEntry->pixels; /* if (y < vBarYOn), use colorBkg */ - y = 0; - count = vBarYOn; + UINT32 y = 0; + UINT32 count = vBarYOn; if ((y + count) > vBarPixelCount) count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; @@ -827,8 +821,15 @@ count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; if (count > 0) - pSrcPixel = - &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)]; + { + const size_t offset = (1ull * y - vBarYOn) * GetBytesPerPixel(clear->format); + pSrcPixel = &vBarShortEntry->pixels[offset]; + if (offset + count > vBarShortEntry->count) + { + WLog_ERR(TAG, "offset + count > vBarShortEntry->count"); + return FALSE; + } + } for (x = 0; x < count; x++) { @@ -868,28 +869,31 @@ return FALSE; } - nXDstRel = nXDst + xStart; - nYDstRel = nYDst + yStart; - pSrcPixel = vBarEntry->pixels; + const UINT32 nXDstRel = nXDst + xStart; + const UINT32 nYDstRel = nYDst + yStart; + cpSrcPixel = vBarEntry->pixels; if (i < nWidth) { - count = vBarEntry->count; + UINT32 count = vBarEntry->count; if (count > nHeight) count = nHeight; - for (y = 0; y < count; y++) + if (nXDstRel + i > nDstWidth) + return FALSE; + + for (UINT32 y = 0; y < count; y++) { BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) + ((nXDstRel + i) * GetBytesPerPixel(DstFormat))]; - UINT32 color = ReadColor(pSrcPixel, clear->format); + UINT32 color = ReadColor(cpSrcPixel, clear->format); color = FreeRDPConvertColor(color, clear->format, DstFormat, NULL); if (!WriteColor(pDstPixel8, DstFormat, color)) return FALSE; - pSrcPixel += GetBytesPerPixel(clear->format); + cpSrcPixel += GetBytesPerPixel(clear->format); } } } @@ -980,7 +984,7 @@ if (glyphEntry->count > glyphEntry->size) { BYTE* tmp; - tmp = realloc(glyphEntry->pixels, glyphEntry->count * bpp * 1ULL); + tmp = realloc(glyphEntry->pixels, 1ull * glyphEntry->count * bpp); if (!tmp) { @@ -1117,7 +1121,7 @@ if (bandsByteCount > 0) { if (!clear_decompress_bands_data(clear, s, bandsByteCount, nWidth, nHeight, pDstData, - DstFormat, nDstStep, nXDst, nYDst)) + DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight)) { WLog_ERR(TAG, "clear_decompress_bands_data failed!"); goto fail; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/color.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/color.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/color.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/color.c 2024-04-22 09:26:59.000000000 +0000 @@ -56,7 +56,7 @@ * means of accessing individual pixels in blitting operations */ scanline = (width + 7) / 8; - dstData = (BYTE*)_aligned_malloc(width * height * 1ULL, 16); + dstData = (BYTE*)_aligned_malloc(1ull * width * height, 16); if (!dstData) return NULL; @@ -545,7 +545,7 @@ for (y = nYDst; y < nHeight; y++) { BYTE* pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel]; - memset(pDstLine, 0, dstBytesPerPixel * (nWidth - nXDst) * 1ULL); + memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst)); } switch (xorBpp) @@ -613,6 +613,9 @@ if (!pDstData || !pSrcData) return FALSE; + if ((nWidth == 0) || (nHeight == 0)) + return TRUE; + if (nDstStep == 0) nDstStep = nWidth * GetBytesPerPixel(DstFormat); @@ -728,21 +731,22 @@ BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color) { - UINT32 x, y; + if ((nWidth == 0) || (nHeight == 0)) + return TRUE; const UINT32 bpp = GetBytesPerPixel(DstFormat); BYTE* pFirstDstLine = &pDstData[nYDst * nDstStep]; BYTE* pFirstDstLineXOffset = &pFirstDstLine[nXDst * bpp]; - for (x = 0; x < nWidth; x++) + for (UINT32 x = 0; x < nWidth; x++) { BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp]; WriteColor(pDst, DstFormat, color); } - for (y = 1; y < nHeight; y++) + for (UINT32 y = 1; y < nHeight; y++) { BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + nXDst * bpp]; - memcpy(pDstLine, pFirstDstLineXOffset, nWidth * bpp * 1ULL); + memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp); } return TRUE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/dsp_ffmpeg.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/dsp_ffmpeg.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/dsp_ffmpeg.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/dsp_ffmpeg.c 2024-04-22 09:26:59.000000000 +0000 @@ -418,9 +418,29 @@ static BOOL ffmpeg_encode_frame(AVCodecContext* context, AVFrame* in, AVPacket* packet, wStream* out) { - int ret; + if (in->format == AV_SAMPLE_FMT_FLTP) + { + uint8_t** pp = in->extended_data; + for (int y = 0; y < in->channels; y++) + { + float* data = pp[y]; + for (int x = 0; x < in->nb_samples; x++) + { + const float val1 = data[x]; + if (isnan(val1)) + data[x] = 0.0f; + else if (isinf(val1)) + { + if (val1 < 0.0f) + data[x] = -1.0f; + else + data[x] = 1.0f; + } + } + } + } /* send the packet with the compressed data to the encoder */ - ret = avcodec_send_frame(context, in); + int ret = avcodec_send_frame(context, in); if (ret < 0) { diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/h264.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/h264.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/h264.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/h264.c 2024-04-22 09:26:59.000000000 +0000 @@ -63,9 +63,9 @@ _aligned_free(h264->pYUVData[0]); _aligned_free(h264->pYUVData[1]); _aligned_free(h264->pYUVData[2]); - h264->pYUVData[0] = _aligned_malloc(h264->iStride[0] * height * 1ULL, 16); - h264->pYUVData[1] = _aligned_malloc(h264->iStride[1] * height * 1ULL, 16); - h264->pYUVData[2] = _aligned_malloc(h264->iStride[2] * height * 1ULL, 16); + h264->pYUVData[0] = _aligned_malloc(1ull * h264->iStride[0] * height, 16); + h264->pYUVData[1] = _aligned_malloc(1ull * h264->iStride[1] * height, 16); + h264->pYUVData[2] = _aligned_malloc(1ull * h264->iStride[2] * height, 16); if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2]) return FALSE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/h264_ffmpeg.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/h264_ffmpeg.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/h264_ffmpeg.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/h264_ffmpeg.c 2024-04-22 09:26:59.000000000 +0000 @@ -529,10 +529,12 @@ goto EXCEPTION; } +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED) { sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED; } +#endif #ifdef WITH_VAAPI diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/include/bitmap.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/include/bitmap.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/include/bitmap.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/include/bitmap.c 2024-04-22 09:26:59.000000000 +0000 @@ -31,7 +31,10 @@ 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 @@ data = xorPixel; DESTWRITEPIXEL(pbDest, data); - DESTNEXTPIXEL(pbDest); mask = mask << 1; }); return pbDest; @@ -62,7 +64,10 @@ 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 @@ data = BLACK_PIXEL; DESTWRITEPIXEL(pbDest, data); - DESTNEXTPIXEL(pbDest); mask = mask << 1; }); return pbDest; @@ -88,6 +92,9 @@ 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 @@ 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 @@ */ 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 @@ 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 @@ return FALSE; DESTWRITEPIXEL(pbDest, temp ^ fgPel); - DESTNEXTPIXEL(pbDest); runLength--; } @@ -176,7 +193,6 @@ UNROLL(runLength, { DESTREADPIXEL(temp, pbDest - rowDelta); DESTWRITEPIXEL(pbDest, temp); - DESTNEXTPIXEL(pbDest); }); } @@ -196,15 +212,16 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ { while (runLength > 8) { - bitmask = *pbSrc; - pbSrc = pbSrc + 1; + bitmask = *pbSrc++; + pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8); if (!pbDest) @@ -319,8 +331,9 @@ 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 @@ /* 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 @@ /* 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 @@ /* 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 -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/interleaved.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/interleaved.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/interleaved.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/interleaved.c 2024-04-22 09:26:59.000000000 +0000 @@ -21,6 +21,7 @@ * limitations under the License. */ +#include #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_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); + WINPR_ASSERT(pbSrc); + WINPR_ASSERT(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 @@ /** * 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) + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = (*pbOrderHdr) & g_MaskRegularRunLength; + if (runLength == 0) { - case REGULAR_FGBG_IMAGE: - runLength = (*pbOrderHdr) & g_MaskRegularRunLength; + if (!buffer_within_range(pbOrderHdr, 2, 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; + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(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; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = *pbOrderHdr & g_MaskRegularRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr, 2, 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; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + if (!buffer_within_range(pbOrderHdr, 3, 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; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(advance); + + runLength = *pbOrderHdr & g_MaskLiteRunLength; + if (runLength == 0) + { + if (!buffer_within_range(pbOrderHdr, 2, 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; + + WINPR_ASSERT(pbOrderHdr); + WINPR_ASSERT(pbEnd); + WINPR_ASSERT(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 @@ 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 @@ 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) { + WINPR_ASSERT(_buf); *_buf = _pix; } static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix) { + WINPR_ASSERT(_buf); (_buf)[0] = (BYTE)(_pix); (_buf)[1] = (BYTE)((_pix) >> 8); (_buf)[2] = (BYTE)((_pix) >> 16); @@ -232,6 +408,7 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) { + WINPR_ASSERT(_buf); _buf[0] = _pix & 0xFF; _buf[1] = (_pix >> 8) & 0xFF; } @@ -239,19 +416,30 @@ #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 @@ #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 @@ #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 @@ #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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ _aligned_free(interleaved->TempBuffer); Stream_Free(interleaved->bts, TRUE); - free(interleaved); + _aligned_free(interleaved); } diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/ncrush.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/ncrush.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/ncrush.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/ncrush.c 2024-04-22 09:26:59.000000000 +0000 @@ -1994,15 +1994,9 @@ UINT32* pDstSize, UINT32 flags) { UINT32 index; - UINT32 bits; - INT32 nbits; - const BYTE* SrcPtr; - const BYTE* SrcEnd; - UINT16 Mask; BYTE Literal; UINT32 IndexLEC; UINT32 BitLength; - UINT32 MaskedBits; UINT32 CopyOffset; UINT32 CopyLength; UINT32 OldCopyOffset; @@ -2010,9 +2004,6 @@ UINT32 LengthOfMatch; UINT32 CopyOffsetIndex; UINT32 OffsetCacheIndex; - BYTE* HistoryPtr; - BYTE* HistoryBuffer; - BYTE* HistoryBufferEnd; UINT32 CopyOffsetBits; UINT32 CopyOffsetBase; UINT32 LengthOfMatchBits; @@ -2021,8 +2012,8 @@ if (ncrush->HistoryEndOffset != 65535) return -1001; - HistoryBuffer = ncrush->HistoryBuffer; - HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset]; + BYTE* HistoryBuffer = ncrush->HistoryBuffer; + const BYTE* HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset]; if (flags & PACKET_AT_FRONT) { @@ -2041,7 +2032,7 @@ ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache)); } - HistoryPtr = ncrush->HistoryPtr; + BYTE* HistoryPtr = ncrush->HistoryPtr; if (!(flags & PACKET_COMPRESSED)) { @@ -2050,17 +2041,25 @@ return 1; } - SrcEnd = &pSrcData[SrcSize]; - nbits = 32; - bits = get_dword(pSrcData); - SrcPtr = pSrcData + 4; + if (SrcSize < 4) + { + WLog_ERR(TAG, "Input size short: SrcSize %" PRIu32 " < 4", SrcSize); + return -1; + } + + const BYTE* SrcEnd = &pSrcData[SrcSize]; + const BYTE* SrcPtr = pSrcData + 4; + INT32 nbits = 32; + UINT32 bits = get_dword(pSrcData); while (1) { while (1) { - Mask = get_word(&HuffTableMask[29]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[29]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits >= ARRAYSIZE(HuffTableLEC)) + return -1; IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF; BitLength = HuffTableLEC[MaskedBits] >> 12; bits >>= BitLength; @@ -2096,8 +2095,10 @@ return -1004; CopyOffset = ncrush->OffsetCache[OffsetCacheIndex]; - Mask = get_word(&HuffTableMask[21]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[21]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits > ARRAYSIZE(HuffTableLOM)) + return -1; LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; bits >>= BitLength; @@ -2106,13 +2107,23 @@ if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) return -1; + if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT)) + return -1; + LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; + + if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT)) + return -1; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); - MaskedBits = bits & Mask; + const size_t idx = (2ull * LengthOfMatchBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; LengthOfMatchBase += MaskedBits; @@ -2127,15 +2138,28 @@ } else { + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT)) + return -1; + CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex]; + + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBaseLUT)) + return -1; CopyOffsetBase = CopyOffsetBaseLUT[CopyOffsetIndex]; CopyOffset = CopyOffsetBase - 1; if (CopyOffsetBits) { - Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]); - MaskedBits = bits & Mask; - CopyOffset = CopyOffsetBase + MaskedBits - 1; + const size_t idx = (2ull * CopyOffsetBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; + const UINT32 tmp = CopyOffsetBase + MaskedBits; + if (tmp < 1) + return -1; + CopyOffset = tmp - 1; bits >>= CopyOffsetBits; nbits -= CopyOffsetBits; @@ -2143,8 +2167,11 @@ return -1; } - Mask = get_word(&HuffTableMask[21]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[21]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits >= ARRAYSIZE(HuffTableLOM)) + return -1; + LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; bits >>= BitLength; @@ -2153,13 +2180,23 @@ if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) return -1; + if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT)) + return -1; + LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; + + if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT)) + return -1; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); - MaskedBits = bits & Mask; + const size_t idx = (2ull * LengthOfMatchBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; LengthOfMatchBase += MaskedBits; @@ -2583,7 +2620,12 @@ } IndexLEC = Literal; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) @@ -2666,9 +2708,18 @@ bits = CopyOffset; CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2]; + + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT)) + return -1; + CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex]; IndexLEC = 257 + CopyOffsetIndex; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) @@ -2687,13 +2738,23 @@ else IndexCO = ncrush->HuffTableLOM[MatchLength]; + if (IndexCO >= ARRAYSIZE(HuffLengthLOM)) + return -1; BitLength = HuffLengthLOM[IndexCO]; + + if (IndexCO >= ARRAYSIZE(LOMBitsLUT)) + return -1; IndexLOM = LOMBitsLUT[IndexCO]; + + if (IndexCO >= ARRAYSIZE(HuffCodeLOM)) + return -1; NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); + if (IndexCO >= ARRAYSIZE(LOMBaseLUT)) + return -1; if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1010; } @@ -2701,7 +2762,11 @@ { /* CopyOffset in OffsetCache */ IndexLEC = 289 + OffsetCacheIndex; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength >= 15) @@ -2714,13 +2779,24 @@ else IndexCO = ncrush->HuffTableLOM[MatchLength]; + if (IndexCO >= ARRAYSIZE(HuffLengthLOM)) + return -1; + BitLength = HuffLengthLOM[IndexCO]; + + if (IndexCO >= ARRAYSIZE(LOMBitsLUT)) + return -1; IndexLOM = LOMBitsLUT[IndexCO]; + + if (IndexCO >= ARRAYSIZE(HuffCodeLOM)) + return -1; NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); + if (IndexCO >= ARRAYSIZE(LOMBaseLUT)) + return -1; if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1012; } @@ -2745,6 +2821,10 @@ Literal = *SrcPtr++; HistoryPtr++; IndexLEC = Literal; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); @@ -2817,6 +2897,11 @@ else i = context->HuffTableLOM[k]; + if (i >= ARRAYSIZE(LOMBitsLUT)) + return -1; + if (i >= ARRAYSIZE(LOMBaseLUT)) + return -1; + if (((((1 << LOMBitsLUT[i]) - 1) & (k - 2)) + LOMBaseLUT[i]) != k) return -1; } diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc.c 2024-04-22 09:26:59.000000000 +0000 @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include @@ -38,6 +40,12 @@ #include "nsc_sse2.h" +#if !defined(Stream_CheckAndLogRequiredLengthWLog) +#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \ + Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ + __FILE__, __LINE__) +#endif + #ifndef NSC_INIT_SIMD #define NSC_INIT_SIMD(_nsc_context) \ do \ @@ -87,8 +95,8 @@ for (x = 0; x < context->width; x++) { INT16 y_val = (INT16)*yplane; - INT16 co_val = (INT16)(INT8)(*coplane << shift); - INT16 cg_val = (INT16)(INT8)(*cgplane << shift); + INT16 co_val = (INT16)(INT8)(((INT16)*coplane) << shift); + INT16 cg_val = (INT16)(INT8)(((INT16)*cgplane) << shift); INT16 r_val = y_val + co_val - cg_val; INT16 g_val = y_val + cg_val; INT16 b_val = y_val - co_val - cg_val; @@ -111,12 +119,17 @@ return TRUE; } -static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize) +static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outSize, + UINT32 originalSize) { UINT32 left = originalSize; while (left > 4) { + if (inSize < 1) + return FALSE; + inSize--; + const BYTE value = *in++; UINT32 len = 0; @@ -129,17 +142,26 @@ *out++ = value; left--; } + else if (inSize < 1) + return FALSE; else if (value == *in) { + inSize--; in++; - if (*in < 0xFF) + if (inSize < 1) + return FALSE; + else if (*in < 0xFF) { + inSize--; len = (UINT32)*in++; len += 2; } else { + if (inSize < 5) + return FALSE; + inSize -= 5; in++; len = ((UINT32)(*in++)); len |= ((UINT32)(*in++)) << 8U; @@ -147,7 +169,7 @@ len |= ((UINT32)(*in++)) << 24U; } - if (outSize < len) + if ((outSize < len) || (left < len)) return FALSE; outSize -= len; @@ -169,26 +191,28 @@ if ((outSize < 4) || (left < 4)) return FALSE; + if (inSize < 4) + return FALSE; memcpy(out, in, 4); return TRUE; } static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) { - UINT16 i; - BYTE* rle; - UINT32 planeSize; - UINT32 originalSize; - if (!context) return FALSE; - rle = context->Planes; + const BYTE* rle = context->Planes; + size_t rleSize = context->PlanesSize; + WINPR_ASSERT(rle); - for (i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { - originalSize = context->OrgByteCount[i]; - planeSize = context->PlaneByteCount[i]; + const UINT32 originalSize = context->OrgByteCount[i]; + const UINT32 planeSize = context->PlaneByteCount[i]; + + if (rleSize < planeSize) + return FALSE; if (planeSize == 0) { @@ -199,7 +223,7 @@ } else if (planeSize < originalSize) { - if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i], + if (!nsc_rle_decode(rle, rleSize, context->priv->PlaneBuffers[i], context->priv->PlaneBuffersLength, originalSize)) return FALSE; } @@ -208,6 +232,9 @@ if (context->priv->PlaneBuffersLength < originalSize) return FALSE; + if (rleSize < originalSize) + return FALSE; + CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize); } @@ -219,64 +246,71 @@ static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s) { - int i; - - if (Stream_GetRemainingLength(s) < 20) + WINPR_ASSERT(context); + WINPR_ASSERT(context->priv); + if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20)) return FALSE; - for (i = 0; i < 4; i++) + size_t total = 0; + for (size_t i = 0; i < 4; i++) + { Stream_Read_UINT32(s, context->PlaneByteCount[i]); + total += context->PlaneByteCount[i]; + } Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */ + if ((context->ColorLossLevel < 1) || (context->ColorLossLevel > 7)) + { + WLog_Print(context->priv->log, WLOG_ERROR, + "ColorLossLevel=%" PRIu8 " out of range, must be [1,7] inclusive", + context->ColorLossLevel); + return FALSE; + } Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */ Stream_Seek(s, 2); /* Reserved (2 bytes) */ context->Planes = Stream_Pointer(s); - return TRUE; + context->PlanesSize = total; + return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total); } static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s) { - int i; - UINT32 length; - UINT32 tempWidth; - UINT32 tempHeight; - if (!nsc_stream_initialize(context, s)) return FALSE; - length = context->width * context->height * 4; + const size_t blength = context->width * context->height * 4ull; if (!context->BitmapData) { - context->BitmapData = calloc(1, length + 16); + context->BitmapData = calloc(1, blength + 16); if (!context->BitmapData) return FALSE; - context->BitmapDataLength = length; + context->BitmapDataLength = blength; } - else if (length > context->BitmapDataLength) + else if (blength > context->BitmapDataLength) { void* tmp; - tmp = realloc(context->BitmapData, length + 16); + tmp = realloc(context->BitmapData, blength + 16); if (!tmp) return FALSE; context->BitmapData = tmp; - context->BitmapDataLength = length; + context->BitmapDataLength = blength; } - tempWidth = ROUND_UP_TO(context->width, 8); - tempHeight = ROUND_UP_TO(context->height, 2); + const UINT32 tempWidth = ROUND_UP_TO(context->width, 8); + const UINT32 tempHeight = ROUND_UP_TO(context->height, 2); /* The maximum length a decoded plane can reach in all cases */ - length = tempWidth * tempHeight; + const size_t plength = 1ull * tempWidth * tempHeight; - if (length > context->priv->PlaneBuffersLength) + if (plength > context->priv->PlaneBuffersLength) { - for (i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { - void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], length); + void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], plength); if (!tmp) return FALSE; @@ -284,13 +318,11 @@ context->priv->PlaneBuffers[i] = tmp; } - context->priv->PlaneBuffersLength = length; + context->priv->PlaneBuffersLength = plength; } - for (i = 0; i < 4; i++) - { + for (size_t i = 0; i < 4; i++) context->OrgByteCount[i] = context->width * context->height; - } if (context->ChromaSubsamplingLevel) { diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc_encode.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc_encode.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc_encode.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc_encode.c 2024-04-22 09:26:59.000000000 +0000 @@ -119,6 +119,8 @@ UINT16 rw; BYTE ccl; const BYTE* src; + const UINT32* src_32; + const UINT16* src_16; BYTE* yplane = NULL; BYTE* coplane = NULL; BYTE* cgplane = NULL; @@ -140,69 +142,85 @@ coplane = context->priv->PlaneBuffers[1] + y * rw; cgplane = context->priv->PlaneBuffers[2] + y * rw; aplane = context->priv->PlaneBuffers[3] + y * context->width; + src_32 = (UINT32*)src; + src_16 = (UINT16*)src; for (x = 0; x < context->width; x++) { switch (context->format) { case PIXEL_FORMAT_BGRX32: - b_val = *src++; - g_val = *src++; - r_val = *src++; - src++; + b_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + r_val = (INT16)((*src_32 >> 16) & 0xFF); a_val = 0xFF; + src_32++; break; case PIXEL_FORMAT_BGRA32: - b_val = *src++; - g_val = *src++; - r_val = *src++; - a_val = *src++; + b_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + r_val = (INT16)((*src_32 >> 16) & 0xFF); + a_val = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; break; case PIXEL_FORMAT_RGBX32: - r_val = *src++; - g_val = *src++; - b_val = *src++; - src++; + r_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + b_val = (INT16)((*src_32 >> 16) & 0xFF); a_val = 0xFF; + src_32++; break; case PIXEL_FORMAT_RGBA32: - r_val = *src++; - g_val = *src++; - b_val = *src++; - a_val = *src++; + r_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + b_val = (INT16)((*src_32 >> 16) & 0xFF); + a_val = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; break; case PIXEL_FORMAT_BGR24: +#ifdef __LITTLE_ENDIAN__ b_val = *src++; g_val = *src++; r_val = *src++; +#else + r_val = *src++; + g_val = *src++; + b_val = *src++; +#endif a_val = 0xFF; break; case PIXEL_FORMAT_RGB24: +#ifdef __LITTLE_ENDIAN__ r_val = *src++; g_val = *src++; b_val = *src++; +#else + b_val = *src++; + g_val = *src++; + r_val = *src++; +#endif a_val = 0xFF; break; case PIXEL_FORMAT_BGR16: - b_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - r_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); + b_val = (INT16)((*src_16) & 0x1F); + g_val = (INT16)((*src_16 >> 5) & 0x3F); + r_val = (INT16)((*src_16 >> 11) & 0x1F); a_val = 0xFF; - src += 2; + src_16++; break; case PIXEL_FORMAT_RGB16: - r_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - b_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); + r_val = (INT16)((*src_16) & 0x1F); + g_val = (INT16)((*src_16 >> 5) & 0x3F); + b_val = (INT16)((*src_16 >> 11) & 0x1F); a_val = 0xFF; - src += 2; + src_16++; break; case PIXEL_FORMAT_A4: @@ -210,17 +228,17 @@ int shift; BYTE idx; shift = (7 - (x % 8)); - idx = ((*src) >> shift) & 1; - idx |= (((*(src + 1)) >> shift) & 1) << 1; - idx |= (((*(src + 2)) >> shift) & 1) << 2; - idx |= (((*(src + 3)) >> shift) & 1) << 3; + idx = (BYTE)(((*src_32 & 0xFF) >> shift) & 1); + idx |= (BYTE)(((((*src_32 >> 8) & 0xFF) >> shift) & 1) << 1); + idx |= (BYTE)(((((*src_32 >> 16) & 0xFF) >> shift) & 1) << 2); + idx |= (BYTE)(((((*src_32 >> 24) & 0xFF) >> shift) & 1) << 3); idx *= 3; r_val = (INT16)context->palette[idx]; g_val = (INT16)context->palette[idx + 1]; b_val = (INT16)context->palette[idx + 2]; if (shift == 0) - src += 4; + src_32++; } a_val = 0xFF; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc_types.h freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc_types.h --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/nsc_types.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/nsc_types.h 2024-04-22 09:26:59.000000000 +0000 @@ -61,6 +61,7 @@ UINT32 BitmapDataLength; BYTE* Planes; + size_t PlanesSize; UINT32 PlaneByteCount[4]; UINT32 ColorLossLevel; UINT32 ChromaSubsamplingLevel; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/planar.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/planar.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/planar.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/planar.c 2024-04-22 09:26:59.000000000 +0000 @@ -33,7 +33,8 @@ #define TAG FREERDP_TAG("codec") -#define ALIGN(val, align) ((val) % (align) == 0) ? (val) : ((val) + (align) - (val) % (align)) +#define PLANAR_ALIGN(val, align) \ + ((val) % (align) == 0) ? (val) : ((val) + (align) - (val) % (align)) static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* planar, BOOL alpha, UINT32 DstFormat) @@ -612,11 +613,20 @@ const UINT32 h = MIN(nSrcHeight, nDstHeight); const primitives_t* prims = primitives_get(); + WINPR_ASSERT(planar); + WINPR_ASSERT(prims); + if (nDstStep <= 0) nDstStep = nDstWidth * GetBytesPerPixel(DstFormat); srcp = pSrcData; + if (!pSrcData) + { + WLog_ERR(TAG, "Invalid argument pSrcData=NULL"); + return FALSE; + } + if (!pDstData) { WLog_ERR(TAG, "Invalid argument pDstData=NULL"); @@ -679,6 +689,13 @@ rawHeights[3] = nSrcHeight; } + const size_t diff = srcp - pSrcData; + if (SrcSize < diff) + { + WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff); + return FALSE; + } + if (!rle) /* RAW */ { UINT32 base = planeSize * 3; @@ -687,8 +704,12 @@ if (alpha) { - if ((SrcSize - (srcp - pSrcData)) < (planeSize + base)) + if ((SrcSize - diff) < (planeSize + base)) + { + WLog_ERR(TAG, "Alpha plane size mismatch %" PRIuz " < %" PRIu32, SrcSize - diff, + (planeSize + base)); return FALSE; + } planes[3] = srcp; /* AlphaPlane */ planes[0] = planes[3] + rawSizes[3]; /* LumaOrRedPlane */ @@ -700,8 +721,11 @@ } else { - if ((SrcSize - (srcp - pSrcData)) < base) + if ((SrcSize - diff) < base) + { + WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32, SrcSize - diff, base); return FALSE; + } planes[0] = srcp; /* LumaOrRedPlane */ planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */ @@ -716,8 +740,8 @@ if (alpha) { planes[3] = srcp; - rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData), - rawWidths[3], rawHeights[3]); /* AlphaPlane */ + rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - diff, rawWidths[3], + rawHeights[3]); /* AlphaPlane */ if (rleSizes[3] < 0) return FALSE; @@ -727,22 +751,41 @@ else planes[0] = srcp; - rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData), - rawWidths[0], rawHeights[0]); /* RedPlane */ + const size_t diff0 = (planes[0] - pSrcData); + if (SrcSize < diff0) + { + WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff0); + return FALSE; + } + rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - diff0, rawWidths[0], + rawHeights[0]); /* RedPlane */ if (rleSizes[0] < 0) return FALSE; planes[1] = planes[0] + rleSizes[0]; - rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData), - rawWidths[1], rawHeights[1]); /* GreenPlane */ + + const size_t diff1 = (planes[1] - pSrcData); + if (SrcSize < diff1) + { + WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff1); + return FALSE; + } + rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - diff1, rawWidths[1], + rawHeights[1]); /* GreenPlane */ if (rleSizes[1] < 1) return FALSE; planes[2] = planes[1] + rleSizes[1]; - rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData), - rawWidths[2], rawHeights[2]); /* BluePlane */ + const size_t diff2 = (planes[2] - pSrcData); + if (SrcSize < diff2) + { + WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff); + return FALSE; + } + rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - diff2, rawWidths[2], + rawHeights[2]); /* BluePlane */ if (rleSizes[2] < 1) return FALSE; @@ -1484,9 +1527,15 @@ return FALSE; context->bgr = FALSE; - context->maxWidth = ALIGN(width, 4); - context->maxHeight = ALIGN(height, 4); - context->maxPlaneSize = context->maxWidth * context->maxHeight; + context->maxWidth = PLANAR_ALIGN(width, 4); + context->maxHeight = PLANAR_ALIGN(height, 4); + const UINT64 tmp = (UINT64)context->maxWidth * context->maxHeight; + if (tmp > UINT32_MAX) + return FALSE; + context->maxPlaneSize = tmp; + + if (context->maxWidth > UINT32_MAX / 4) + return FALSE; context->nTempStep = context->maxWidth * 4; free(context->planesBuffer); free(context->pTempData); diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/progressive.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/progressive.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/progressive.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/progressive.c 2024-04-22 09:26:59.000000000 +0000 @@ -415,7 +415,7 @@ tile->stride = 4 * tile->width; { - size_t dataLen = tile->stride * tile->height * 1ULL; + size_t dataLen = 1ull * tile->stride * tile->height; tile->data = (BYTE*)_aligned_malloc(dataLen, 16); } @@ -1796,13 +1796,13 @@ for (index = 0; index < region->numTiles; index++) { RFX_PROGRESSIVE_TILE* tile = region->tiles[index]; - params[index].progressive = progressive; - params[index].region = region; - params[index].context = context; - params[index].tile = tile; if (progressive->rfx_context->priv->UseThreads) { + params[index].progressive = progressive; + params[index].region = region; + params[index].context = context; + params[index].tile = tile; if (!(work_objects[index] = CreateThreadpoolWork( progressive_process_tiles_tile_work_callback, (void*)¶ms[index], &progressive->rfx_context->priv->ThreadPoolEnv))) @@ -1817,7 +1817,10 @@ } else { - progressive_process_tiles_tile_work_callback(0, ¶ms[index], 0); + PROGRESSIVE_TILE_PROCESS_WORK_PARAM param = { + .progressive = progressive, .region = region, .context = context, .tile = tile + }; + progressive_process_tiles_tile_work_callback(0, ¶m, 0); } if (status < 0) @@ -2422,11 +2425,17 @@ for (j = 0; j < nbUpdateRects; j++) { const RECTANGLE_16* rect = &updateRects[j]; - const UINT32 nXSrc = rect->left - (nXDst + tile->x); - const UINT32 nYSrc = rect->top - (nYDst + tile->y); + if (rect->left < updateRect.left) + goto fail; + const UINT32 nXSrc = rect->left - updateRect.left; + const UINT32 nYSrc = rect->top - updateRect.top; const UINT32 width = rect->right - rect->left; const UINT32 height = rect->bottom - rect->top; + if (rect->left + width > surface->width) + goto fail; + if (rect->top + height > surface->height) + goto fail; if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, height, tile->data, progressive->format, tile->stride, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/rfx.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/rfx.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/rfx.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/rfx.c 2024-04-22 09:26:59.000000000 +0000 @@ -936,6 +936,27 @@ Stream_Read_UINT8(&sub, tile->quantIdxY); /* quantIdxY (1 byte) */ Stream_Read_UINT8(&sub, tile->quantIdxCb); /* quantIdxCb (1 byte) */ Stream_Read_UINT8(&sub, tile->quantIdxCr); /* quantIdxCr (1 byte) */ + if (tile->quantIdxY >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxY %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxY, context->numQuant); + rc = FALSE; + break; + } + else if (tile->quantIdxCb >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCb %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxCb, context->numQuant); + rc = FALSE; + break; + } + else if (tile->quantIdxCr >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCr %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxCr, context->numQuant); + rc = FALSE; + break; + } Stream_Read_UINT16(&sub, tile->xIdx); /* xIdx (2 bytes) */ Stream_Read_UINT16(&sub, tile->yIdx); /* yIdx (2 bytes) */ Stream_Read_UINT16(&sub, tile->YLen); /* YLen (2 bytes) */ @@ -1109,8 +1130,18 @@ } } - Stream_StaticInit(&subStream, Stream_Pointer(s), blockLen - (6 + extraBlockLen)); - Stream_Seek(s, blockLen - (6 + extraBlockLen)); + const size_t blockLenNoHeader = blockLen - 6; + if (blockLenNoHeader < extraBlockLen) + { + WLog_Print(context->priv->log, WLOG_ERROR, + "blockLen too small(%" PRIu32 "), must be >= 6 + %" PRIu16, blockLen, + extraBlockLen); + return FALSE; + } + + const size_t subStreamLen = blockLenNoHeader - extraBlockLen; + Stream_StaticInit(&subStream, Stream_Pointer(s), subStreamLen); + Stream_Seek(s, subStreamLen); switch (blockType) { @@ -1231,6 +1262,11 @@ region16_uninit(&clippingRects); return TRUE; } + else + { + rfx_message_free(context, message); + context->currentMessage.freeArray = TRUE; + } WLog_ERR(TAG, "%s failed", __FUNCTION__); return FALSE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/rfx_encode.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/rfx_encode.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/rfx_encode.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/rfx_encode.c 2024-04-22 09:26:59.000000000 +0000 @@ -49,6 +49,8 @@ int x_exceed; int y_exceed; const BYTE* src; + const UINT32* src_32; + const UINT16* src_16; INT16 r, g, b; INT16 *r_last, *g_last, *b_last; x_exceed = 64 - width; @@ -57,6 +59,8 @@ for (y = 0; y < height; y++) { src = rgb_data + y * rowstride; + src_32 = (UINT32*)src; + src_16 = (UINT16*)src; switch (pixel_format) { @@ -64,10 +68,10 @@ case PIXEL_FORMAT_BGRA32: for (x = 0; x < width; x++) { - *b_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *r_buf++ = (INT16)(*src++); - src++; + *b_buf++ = (INT16)(*src_32 & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *r_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + src_32++; } break; @@ -76,10 +80,10 @@ case PIXEL_FORMAT_ABGR32: for (x = 0; x < width; x++) { - src++; - *b_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *r_buf++ = (INT16)(*src++); + *b_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + *r_buf++ = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; } break; @@ -88,10 +92,10 @@ case PIXEL_FORMAT_RGBA32: for (x = 0; x < width; x++) { - *r_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *b_buf++ = (INT16)(*src++); - src++; + *r_buf++ = (INT16)(*src_32 & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *b_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + src_32++; } break; @@ -100,10 +104,10 @@ case PIXEL_FORMAT_ARGB32: for (x = 0; x < width; x++) { - src++; - *r_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *b_buf++ = (INT16)(*src++); + *r_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + *b_buf++ = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; } break; @@ -111,9 +115,15 @@ case PIXEL_FORMAT_BGR24: for (x = 0; x < width; x++) { +#ifdef __LITTLE_ENDIAN__ *b_buf++ = (INT16)(*src++); *g_buf++ = (INT16)(*src++); *r_buf++ = (INT16)(*src++); +#else + *r_buf++ = (INT16)(*src++); + *g_buf++ = (INT16)(*src++); + *b_buf++ = (INT16)(*src++); +#endif } break; @@ -121,9 +131,15 @@ case PIXEL_FORMAT_RGB24: for (x = 0; x < width; x++) { +#ifdef __LITTLE_ENDIAN__ *r_buf++ = (INT16)(*src++); *g_buf++ = (INT16)(*src++); *b_buf++ = (INT16)(*src++); +#else + *b_buf++ = (INT16)(*src++); + *g_buf++ = (INT16)(*src++); + *r_buf++ = (INT16)(*src++); +#endif } break; @@ -131,10 +147,10 @@ case PIXEL_FORMAT_BGR16: for (x = 0; x < width; x++) { - *b_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - *g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - *r_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); - src += 2; + *b_buf++ = (INT16)((*src_16) & 0x1F); + *g_buf++ = (INT16)((*src_16 >> 5) & 0x3F); + *r_buf++ = (INT16)((*src_16 >> 11) & 0x1F); + src_16++; } break; @@ -142,10 +158,10 @@ case PIXEL_FORMAT_RGB16: for (x = 0; x < width; x++) { - *r_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - *g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - *b_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); - src += 2; + *r_buf++ = (INT16)((*src_16 & 0x1F)); + *g_buf++ = (INT16)((*src_16 >> 5) & 0x3F); + *b_buf++ = (INT16)((*src_16 >> 11) & 0x1F); + src_16++; } break; @@ -159,17 +175,17 @@ int shift; BYTE idx; shift = (7 - (x % 8)); - idx = ((*src) >> shift) & 1; - idx |= (((*(src + 1)) >> shift) & 1) << 1; - idx |= (((*(src + 2)) >> shift) & 1) << 2; - idx |= (((*(src + 3)) >> shift) & 1) << 3; + idx = (BYTE)(((*src_32 & 0xFF) >> shift) & 1); + idx |= (BYTE)(((((*src_32 >> 8) & 0xFF) >> shift) & 1) << 1); + idx |= (BYTE)(((((*src_32 >> 16) & 0xFF) >> shift) & 1) << 2); + idx |= (BYTE)(((((*src_32 >> 24) & 0xFF) >> shift) & 1) << 3); idx *= 3; *r_buf++ = (INT16)palette[idx]; *g_buf++ = (INT16)palette[idx + 1]; *b_buf++ = (INT16)palette[idx + 2]; if (shift == 0) - src += 4; + src_32++; } break; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/xcrush.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/xcrush.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/xcrush.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/xcrush.c 2024-04-22 09:26:59.000000000 +0000 @@ -674,7 +674,7 @@ if (&OutputBuffer[2] >= &OutputBuffer[OutputSize]) return -6001; /* error */ - *((UINT16*)OutputBuffer) = MatchCount; + Data_Write_UINT16(OutputBuffer, MatchCount); MatchDetails = (RDP61_MATCH_DETAILS*)&OutputBuffer[2]; Literals = (BYTE*)&MatchDetails[MatchCount]; @@ -683,12 +683,12 @@ for (MatchIndex = 0; MatchIndex < MatchCount; MatchIndex++) { - MatchDetails[MatchIndex].MatchLength = - (UINT16)(xcrush->OptimizedMatches[MatchIndex].MatchLength); - MatchDetails[MatchIndex].MatchOutputOffset = - (UINT16)(xcrush->OptimizedMatches[MatchIndex].MatchOffset - HistoryOffset); - MatchDetails[MatchIndex].MatchHistoryOffset = - xcrush->OptimizedMatches[MatchIndex].ChunkOffset; + Data_Write_UINT16(&MatchDetails[MatchIndex].MatchLength, + xcrush->OptimizedMatches[MatchIndex].MatchLength); + Data_Write_UINT16(&MatchDetails[MatchIndex].MatchOutputOffset, + xcrush->OptimizedMatches[MatchIndex].MatchOffset - HistoryOffset); + Data_Write_UINT32(&MatchDetails[MatchIndex].MatchHistoryOffset, + xcrush->OptimizedMatches[MatchIndex].ChunkOffset); } CurrentOffset = HistoryOffset; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/codec/zgfx.c freerdp2-2.11.7+dfsg1/libfreerdp/codec/zgfx.c --- freerdp2-2.10.0+dfsg1/libfreerdp/codec/zgfx.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/codec/zgfx.c 2024-04-22 09:26:59.000000000 +0000 @@ -230,7 +230,10 @@ BYTE* pbSegment; size_t cbSegment; - if (!zgfx || !stream || (segmentSize < 2)) + WINPR_ASSERT(zgfx); + WINPR_ASSERT(stream); + + if (segmentSize < 2) return FALSE; cbSegment = segmentSize - 1; @@ -259,7 +262,11 @@ zgfx->pbInputCurrent = pbSegment; zgfx->pbInputEnd = &pbSegment[cbSegment - 1]; /* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */ - zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd; + const UINT32 bits = 8u * (cbSegment - 1u); + if (bits < *zgfx->pbInputEnd) + return FALSE; + + zgfx->cBitsRemaining = bits - *zgfx->pbInputEnd; zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; @@ -345,8 +352,9 @@ if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount) return FALSE; - - if (count > zgfx->cBitsRemaining / 8) + else if (count > zgfx->cBitsRemaining / 8) + return FALSE; + else if (zgfx->pbInputCurrent + count > zgfx->pbInputEnd) return FALSE; CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, @@ -377,15 +385,45 @@ return malloc(size + 64); } +static BOOL zgfx_append(ZGFX_CONTEXT* zgfx, BYTE** ppConcatenated, size_t uncompressedSize, + size_t* pUsed) +{ + WINPR_ASSERT(zgfx); + WINPR_ASSERT(ppConcatenated); + WINPR_ASSERT(pUsed); + + const size_t used = *pUsed; + if (zgfx->OutputCount > UINT32_MAX - used) + return FALSE; + + if (used + zgfx->OutputCount > uncompressedSize) + return FALSE; + + BYTE* tmp = realloc(*ppConcatenated, used + zgfx->OutputCount + 64ull); + if (!tmp) + return FALSE; + *ppConcatenated = tmp; + CopyMemory(&tmp[used], zgfx->OutputBuffer, zgfx->OutputCount); + *pUsed = used + zgfx->OutputCount; + return TRUE; +} + int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { int status = -1; - BYTE descriptor; + BYTE descriptor = 0; + size_t used = 0; + BYTE* pConcatenated = NULL; wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize); - if (!stream) - return -1; + WINPR_ASSERT(zgfx); + WINPR_ASSERT(stream); + WINPR_ASSERT(ppDstData); + WINPR_ASSERT(pDstSize); + + *ppDstData = NULL; + *pDstSize = 0; if (Stream_GetRemainingLength(stream) < 1) goto fail; @@ -397,16 +435,15 @@ if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream))) goto fail; - *ppDstData = NULL; - if (zgfx->OutputCount > 0) - *ppDstData = aligned_zgfx_malloc(zgfx->OutputCount); - - if (!*ppDstData) - goto fail; - - *pDstSize = zgfx->OutputCount; - CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); + { + if (!zgfx_append(zgfx, &pConcatenated, zgfx->OutputCount, &used)) + goto fail; + if (used != zgfx->OutputCount) + goto fail; + *ppDstData = pConcatenated; + *pDstSize = zgfx->OutputCount; + } } else if (descriptor == ZGFX_SEGMENTED_MULTIPART) { @@ -414,8 +451,6 @@ UINT16 segmentNumber; UINT16 segmentCount; UINT32 uncompressedSize; - BYTE* pConcatenated; - size_t used = 0; if (Stream_GetRemainingLength(stream) < 6) goto fail; @@ -423,17 +458,6 @@ Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */ Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */ - if (Stream_GetRemainingLength(stream) < segmentCount * sizeof(UINT32)) - goto fail; - - pConcatenated = aligned_zgfx_malloc(uncompressedSize); - - if (!pConcatenated) - goto fail; - - *ppDstData = pConcatenated; - *pDstSize = uncompressedSize; - for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) { if (Stream_GetRemainingLength(stream) < sizeof(UINT32)) @@ -444,16 +468,15 @@ if (!zgfx_decompress_segment(zgfx, stream, segmentSize)) goto fail; - if (zgfx->OutputCount > UINT32_MAX - used) + if (!zgfx_append(zgfx, &pConcatenated, uncompressedSize, &used)) goto fail; + } - if (used + zgfx->OutputCount > uncompressedSize) - goto fail; + if (used != uncompressedSize) + goto fail; - CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); - pConcatenated += zgfx->OutputCount; - used += zgfx->OutputCount; - } + *ppDstData = pConcatenated; + *pDstSize = uncompressedSize; } else { @@ -462,6 +485,8 @@ status = 1; fail: + if (status < 0) + free(pConcatenated); Stream_Free(stream, FALSE); return status; } diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/common/settings_getters.c freerdp2-2.11.7+dfsg1/libfreerdp/common/settings_getters.c --- freerdp2-2.10.0+dfsg1/libfreerdp/common/settings_getters.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/common/settings_getters.c 2024-04-22 09:26:59.000000000 +0000 @@ -231,6 +231,9 @@ case FreeRDP_GrabKeyboard: return settings->GrabKeyboard; + case FreeRDP_GrabMouse: + return settings->GrabMouse; + case FreeRDP_HasExtendedMouseEvent: return settings->HasExtendedMouseEvent; @@ -809,6 +812,10 @@ settings->GrabKeyboard = val; break; + case FreeRDP_GrabMouse: + settings->GrabMouse = val; + break; + case FreeRDP_HasExtendedMouseEvent: settings->HasExtendedMouseEvent = val; break; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/common/settings_str.c freerdp2-2.11.7+dfsg1/libfreerdp/common/settings_str.c --- freerdp2-2.10.0+dfsg1/libfreerdp/common/settings_str.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/common/settings_str.c 2024-04-22 09:26:59.000000000 +0000 @@ -87,6 +87,7 @@ { FreeRDP_GfxSmallCache, 0, "FreeRDP_GfxSmallCache" }, { FreeRDP_GfxThinClient, 0, "FreeRDP_GfxThinClient" }, { FreeRDP_GrabKeyboard, 0, "FreeRDP_GrabKeyboard" }, + { FreeRDP_GrabMouse, 0, "FreeRDP_GrabMouse" }, { FreeRDP_HasExtendedMouseEvent, 0, "FreeRDP_HasExtendedMouseEvent" }, { FreeRDP_HasHorizontalWheel, 0, "FreeRDP_HasHorizontalWheel" }, { FreeRDP_HasMonitorAttributes, 0, "FreeRDP_HasMonitorAttributes" }, diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/core/orders.c freerdp2-2.11.7+dfsg1/libfreerdp/core/orders.c --- freerdp2-2.10.0+dfsg1/libfreerdp/core/orders.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/core/orders.c 2024-04-22 09:26:59.000000000 +0000 @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -796,6 +797,7 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value) { BYTE byte; + UINT32 uvalue = 0; if (Stream_GetRemainingLength(s) < 1) { @@ -806,9 +808,9 @@ Stream_Read_UINT8(s, byte); if (byte & 0x40) - *value = (byte | ~0x3F); + uvalue = (byte | ~0x3F); else - *value = (byte & 0x3F); + uvalue = (byte & 0x3F); if (byte & 0x80) { @@ -819,8 +821,9 @@ } Stream_Read_UINT8(s, byte); - *value = (*value << 8) | byte; + uvalue = (uvalue << 8) | byte; } + *value = (INT32)uvalue; return TRUE; } @@ -1373,12 +1376,13 @@ static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt) { + UINT32 numRectangles = multi_dstblt->numRectangles; if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) || !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) || !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) || !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) || !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) || - !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE)) + !read_order_field_byte(orderInfo, s, 6, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) @@ -1386,12 +1390,21 @@ if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_dstblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_dstblt->cbData); return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles); } - + if (numRectangles > multi_dstblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_dstblt->numRectangles); + return FALSE; + } + multi_dstblt->numRectangles = numRectangles; return TRUE; } + static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt) { @@ -1407,7 +1420,8 @@ if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7)) return FALSE; - if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE)) + UINT32 numRectangles = multi_patblt->numRectangles; + if (!read_order_field_byte(orderInfo, s, 13, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0) @@ -1415,17 +1429,31 @@ if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_patblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_patblt->cbData); if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles)) return FALSE; } + if (numRectangles > multi_patblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_patblt->numRectangles); + return FALSE; + } + multi_patblt->numRectangles = numRectangles; + return TRUE; } static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt) { + WINPR_ASSERT(orderInfo); + WINPR_ASSERT(multi_scrblt); + + UINT32 numRectangles = multi_scrblt->numRectangles; if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) || !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) || !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) || @@ -1433,7 +1461,7 @@ !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) || !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) || !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) || - !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE)) + !read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) @@ -1441,10 +1469,20 @@ if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_scrblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_scrblt->cbData); return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles); } + if (numRectangles > multi_scrblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_scrblt->numRectangles); + return FALSE; + } + multi_scrblt->numRectangles = numRectangles; + return TRUE; } static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo, @@ -1484,7 +1522,8 @@ multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16); } - if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE)) + UINT32 numRectangles = multi_opaque_rect->numRectangles; + if (!read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) @@ -1492,22 +1531,32 @@ if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_opaque_rect->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_opaque_rect->cbData); return update_read_delta_rects(s, multi_opaque_rect->rectangles, &multi_opaque_rect->numRectangles); } + if (numRectangles > multi_opaque_rect->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_opaque_rect->numRectangles); + return FALSE; + } + multi_opaque_rect->numRectangles = numRectangles; return TRUE; } static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) { + UINT32 nDeltaEntries = multi_draw_nine_grid->nDeltaEntries; if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) || !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) || !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) || !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) || !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) || - !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE)) + !read_order_field_byte(orderInfo, s, 6, &nDeltaEntries, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) @@ -1515,11 +1564,21 @@ if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; Stream_Read_UINT16(s, multi_draw_nine_grid->cbData); return update_read_delta_rects(s, multi_draw_nine_grid->rectangles, &multi_draw_nine_grid->nDeltaEntries); } + if (nDeltaEntries > multi_draw_nine_grid->nDeltaEntries) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s nDeltaEntries %" PRIu32 " > %" PRIu32, orderName, nDeltaEntries, + multi_draw_nine_grid->nDeltaEntries); + return FALSE; + } + multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; + return TRUE; } static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, @@ -1610,6 +1669,14 @@ return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries, polyline->xStart, polyline->yStart); } + if (new_num > polyline->numDeltaEntries) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numDeltaEntries %" PRIu32 " > %" PRIu32, orderName, new_num, + polyline->numDeltaEntries); + return FALSE; + } + polyline->numDeltaEntries = new_num; return TRUE; } @@ -1942,6 +2009,13 @@ return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints, polygon_sc->xStart, polygon_sc->yStart); } + if (num > polygon_sc->numPoints) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_sc->numPoints); + return FALSE; + } + polygon_sc->numPoints = num; return TRUE; } @@ -1987,6 +2061,14 @@ return FALSE; } + if (num > polygon_cb->numPoints) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_cb->numPoints); + return FALSE; + } + polygon_cb->numPoints = num; + polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE; polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F); return TRUE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/core/server.c freerdp2-2.11.7+dfsg1/libfreerdp/core/server.c --- freerdp2-2.10.0+dfsg1/libfreerdp/core/server.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/core/server.c 2024-04-22 09:26:59.000000000 +0000 @@ -493,7 +493,7 @@ { ULONG written; vcm->drdynvc_channel = channel; - dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ + Data_Write_UINT32(&dynvc_caps, 0x00010050); /* DYNVC_CAPS_VERSION1 (4 bytes) */ if (!WTSVirtualChannelWrite(channel, (PCHAR)&dynvc_caps, sizeof(dynvc_caps), &written)) return FALSE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/core/test/settings_property_lists.h freerdp2-2.11.7+dfsg1/libfreerdp/core/test/settings_property_lists.h --- freerdp2-2.10.0+dfsg1/libfreerdp/core/test/settings_property_lists.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/core/test/settings_property_lists.h 2024-04-22 09:26:59.000000000 +0000 @@ -76,6 +76,7 @@ FreeRDP_GfxSmallCache, FreeRDP_GfxThinClient, FreeRDP_GrabKeyboard, + FreeRDP_GrabMouse, FreeRDP_HasExtendedMouseEvent, FreeRDP_HasHorizontalWheel, FreeRDP_HasMonitorAttributes, diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/core/window.c freerdp2-2.11.7+dfsg1/libfreerdp/core/window.c --- freerdp2-2.10.0+dfsg1/libfreerdp/core/window.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/core/window.c 2024-04-22 09:26:59.000000000 +0000 @@ -359,33 +359,31 @@ Stream_Read_UINT16(s, windowState->numWindowRects); /* numWindowRects (2 bytes) */ - if (windowState->numWindowRects == 0) + if (windowState->numWindowRects > 0) { - return TRUE; - } - - size = sizeof(RECTANGLE_16) * windowState->numWindowRects; - newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size); - - if (!newRect) - { - free(windowState->windowRects); - windowState->windowRects = NULL; - return FALSE; - } - - windowState->windowRects = newRect; + size = sizeof(RECTANGLE_16) * windowState->numWindowRects; + newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size); - if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects) - return FALSE; - - /* windowRects */ - for (i = 0; i < windowState->numWindowRects; i++) - { - Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */ + if (!newRect) + { + free(windowState->windowRects); + windowState->windowRects = NULL; + return FALSE; + } + + windowState->windowRects = newRect; + + if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects) + return FALSE; + + /* windowRects */ + for (i = 0; i < windowState->numWindowRects; i++) + { + Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */ + } } } diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/crypto/crypto.c freerdp2-2.11.7+dfsg1/libfreerdp/crypto/crypto.c --- freerdp2-2.10.0+dfsg1/libfreerdp/crypto/crypto.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/crypto/crypto.c 2024-04-22 09:26:59.000000000 +0000 @@ -950,10 +950,13 @@ { WINPR_ASSERT(xcert); - const int nid = X509_get_signature_nid(xcert); + EVP_PKEY* evp = X509_get_pubkey(xcert); + WINPR_ASSERT(evp); int hash_nid = 0; - if (OBJ_find_sigid_algs(nid, &hash_nid, NULL) != 1) + const int res = EVP_PKEY_get_default_digest_nid(evp, &hash_nid); + EVP_PKEY_free(evp); + if (res <= 0) return WINPR_MD_NONE; switch (hash_nid) @@ -976,7 +979,7 @@ return WINPR_MD_SHA512; case NID_ripemd160: return WINPR_MD_RIPEMD160; -#if (OPENSSL_VERSION_NUMBER >= 0x1010101fL) || defined(LIBRESSL_VERSION_NUMBER) +#if (OPENSSL_VERSION_NUMBER >= 0x1010101fL) && !defined(LIBRESSL_VERSION_NUMBER) case NID_sha3_224: return WINPR_MD_SHA3_224; case NID_sha3_256: @@ -985,11 +988,11 @@ return WINPR_MD_SHA3_384; case NID_sha3_512: return WINPR_MD_SHA3_512; -#endif case NID_shake128: return WINPR_MD_SHAKE128; case NID_shake256: return WINPR_MD_SHAKE256; +#endif case NID_undef: default: return WINPR_MD_NONE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/bitmap.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/bitmap.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/bitmap.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/bitmap.c 2024-04-22 09:26:59.000000000 +0000 @@ -148,7 +148,7 @@ hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = - _aligned_malloc(nWidth * nHeight * GetBytesPerPixel(hBitmap->format) * 1ULL, 16); + _aligned_malloc(1ull * nWidth * nHeight * GetBytesPerPixel(hBitmap->format), 16); hBitmap->free = _aligned_free; if (!hBitmap->data) diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/gdi.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/gdi.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/gdi.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/gdi.c 2024-04-22 09:26:59.000000000 +0000 @@ -997,16 +997,46 @@ return TRUE; } +static BOOL intersect_rect(const rdpGdi* gdi, const SURFACE_BITS_COMMAND* cmd, RECTANGLE_16* prect) +{ + const UINT32 w = (const UINT32)gdi->width; + const UINT32 h = (const UINT32)gdi->height; + + if (cmd->destLeft > w) + return FALSE; + if (cmd->destRight > w) + return FALSE; + if (cmd->destLeft > cmd->destRight) + return FALSE; + if (cmd->destRight > UINT16_MAX) + return FALSE; + + if (cmd->destTop > h) + return FALSE; + if (cmd->destBottom > h) + return FALSE; + if (cmd->destTop > cmd->destBottom) + return FALSE; + if (cmd->destBottom > UINT16_MAX) + return FALSE; + + prect->left = (const UINT16)cmd->destLeft; + prect->top = (const UINT16)cmd->destTop; + prect->right = MIN((UINT16)cmd->destRight, prect->left + cmd->bmp.width); + prect->bottom = MIN((UINT16)cmd->destBottom, prect->top + cmd->bmp.height); + return TRUE; +} + static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd) { BOOL result = FALSE; DWORD format; - rdpGdi* gdi; + rdpGdi* gdi = NULL; size_t size; REGION16 region; - RECTANGLE_16 cmdRect; - UINT32 i, nbRects; - const RECTANGLE_16* rects; + RECTANGLE_16 cmdRect = { 0 }; + UINT32 nbRects; + const RECTANGLE_16* rects = NULL; if (!context || !cmd) return FALSE; @@ -1020,16 +1050,15 @@ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom, cmd->bmp.bpp, cmd->bmp.flags, cmd->bmp.codecID, cmd->bmp.width, cmd->bmp.height, cmd->bmp.bitmapDataLength); region16_init(®ion); - cmdRect.left = cmd->destLeft; - cmdRect.top = cmd->destTop; - cmdRect.right = cmdRect.left + cmd->bmp.width; - cmdRect.bottom = cmdRect.top + cmd->bmp.height; + + if (!intersect_rect(gdi, cmd, &cmdRect)) + goto out; switch (cmd->bmp.codecID) { case RDP_CODEC_ID_REMOTEFX: if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData, - cmd->bmp.bitmapDataLength, cmd->destLeft, cmd->destTop, + cmd->bmp.bitmapDataLength, cmdRect.left, cmdRect.top, gdi->primary_buffer, gdi->dstFormat, gdi->stride, gdi->height, ®ion)) { @@ -1042,11 +1071,11 @@ case RDP_CODEC_ID_NSCODEC: format = gdi->dstFormat; - 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, cmd->destLeft, cmd->destTop, cmd->bmp.width, - cmd->bmp.height, FREERDP_FLIP_VERTICAL)) + 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)) { WLog_ERR(TAG, "Failed to process NSCodec message"); goto out; @@ -1057,17 +1086,18 @@ case RDP_CODEC_ID_NONE: format = gdi_get_pixel_format(cmd->bmp.bpp); - size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL; + size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format); if (size > cmd->bmp.bitmapDataLength) { WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz, cmd->bmp.bitmapDataLength, size); goto out; } - if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmd->destLeft, - cmd->destTop, cmd->bmp.width, cmd->bmp.height, - cmd->bmp.bitmapData, format, 0, 0, 0, &gdi->palette, - FREERDP_FLIP_VERTICAL)) + + if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmdRect.left, + cmdRect.top, cmdRect.right - cmdRect.left, + cmdRect.bottom - cmdRect.top, cmd->bmp.bitmapData, format, 0, 0, + 0, &gdi->palette, FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process nocodec message"); goto out; @@ -1084,7 +1114,7 @@ if (!(rects = region16_rects(®ion, &nbRects))) goto out; - for (i = 0; i < nbRects; i++) + for (UINT32 i = 0; i < nbRects; i++) { UINT32 left = rects[i].left; UINT32 top = rects[i].top; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/gfx.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/gfx.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/gfx.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/gfx.c 2024-04-22 09:26:59.000000000 +0000 @@ -726,7 +726,7 @@ { UINT32 x, y; - if (Stream_GetRemainingLength(&s) < cmd->height * cmd->width * 1ULL) + if (Stream_GetRemainingLength(&s) < 1ull * cmd->height * cmd->width) return ERROR_INVALID_DATA; for (y = cmd->top; y < cmd->top + cmd->height; y++) @@ -1025,7 +1025,7 @@ } surface->scanline = gfx_align_scanline(surface->width * 4UL, 16); - surface->data = (BYTE*)_aligned_malloc(surface->scanline * surface->height * 1ULL, 16); + surface->data = (BYTE*)_aligned_malloc(1ull * surface->scanline * surface->height, 16); if (!surface->data) { @@ -1079,6 +1079,28 @@ return rc; } +static BOOL intersect_rect(const RECTANGLE_16* rect, const gdiGfxSurface* surface, + RECTANGLE_16* prect) +{ + WINPR_ASSERT(rect); + WINPR_ASSERT(surface); + WINPR_ASSERT(prect); + + if (rect->left > rect->right) + return FALSE; + if (rect->left > surface->width) + return FALSE; + if (rect->top > rect->bottom) + return FALSE; + if (rect->top > surface->height) + return FALSE; + prect->left = rect->left; + prect->top = rect->top; + prect->right = MIN(rect->right, surface->width); + prect->bottom = MIN(rect->bottom, surface->height); + return TRUE; +} + /** * Function description * @@ -1087,40 +1109,36 @@ static UINT gdi_SolidFill(RdpgfxClientContext* context, const RDPGFX_SOLID_FILL_PDU* solidFill) { UINT status = ERROR_INTERNAL_ERROR; - UINT16 index; - UINT32 color; - BYTE a, r, g, b; - UINT32 nWidth, nHeight; - RECTANGLE_16* rect; - gdiGfxSurface* surface; - RECTANGLE_16 invalidRect; + BYTE a = 0; + RECTANGLE_16 invalidRect = { 0 }; rdpGdi* gdi = (rdpGdi*)context->custom; + EnterCriticalSection(&context->mux); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId); + + WINPR_ASSERT(context->GetSurfaceData); + gdiGfxSurface* surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId); if (!surface) goto fail; - b = solidFill->fillPixel.B; - g = solidFill->fillPixel.G; - r = solidFill->fillPixel.R; - /* a = solidFill->fillPixel.XA; - * Ignore alpha channel, this is a solid fill. */ + const BYTE b = solidFill->fillPixel.B; + const BYTE g = solidFill->fillPixel.G; + const BYTE r = solidFill->fillPixel.R; a = 0xFF; - color = FreeRDPGetColor(surface->format, r, g, b, a); + const UINT32 color = FreeRDPGetColor(surface->format, r, g, b, a); - for (index = 0; index < solidFill->fillRectCount; index++) + for (UINT16 index = 0; index < solidFill->fillRectCount; index++) { - rect = &(solidFill->fillRects[index]); - nWidth = rect->right - rect->left; - nHeight = rect->bottom - rect->top; - invalidRect.left = rect->left; - invalidRect.top = rect->top; - invalidRect.right = rect->right; - invalidRect.bottom = rect->bottom; + const RECTANGLE_16* rect = &(solidFill->fillRects[index]); + + if (!intersect_rect(rect, surface, &invalidRect)) + goto fail; + + const UINT32 nWidth = invalidRect.right - invalidRect.left; + const UINT32 nHeight = invalidRect.bottom - invalidRect.top; - if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, rect->left, - rect->top, nWidth, nHeight, color)) + if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, invalidRect.left, + invalidRect.top, nWidth, nHeight, color)) goto fail; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/graphics.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/graphics.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/graphics.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/graphics.c 2024-04-22 09:26:59.000000000 +0000 @@ -52,7 +52,7 @@ return NULL; nDstStep = nWidth * GetBytesPerPixel(gdi->dstFormat); - pDstData = _aligned_malloc(nHeight * nDstStep * 1ULL, 16); + pDstData = _aligned_malloc(1ull * nHeight * nDstStep, 16); if (!pDstData) return NULL; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/shape.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/shape.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/shape.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/shape.c 2024-04-22 09:26:59.000000000 +0000 @@ -158,7 +158,7 @@ for (y = 1; y < nHeight; y++) { BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); - memcpy(dstp, srcp, nWidth * formatSize * 1ULL); + memcpy(dstp, srcp, 1ull * nWidth * formatSize); } break; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/gdi/video.c freerdp2-2.11.7+dfsg1/libfreerdp/gdi/video.c --- freerdp2-2.10.0+dfsg1/libfreerdp/gdi/video.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/gdi/video.c 2024-04-22 09:26:59.000000000 +0000 @@ -66,7 +66,7 @@ ret->base.w = width; ret->base.h = height; ret->scanline = width * bpp; - ret->image = _aligned_malloc(ret->scanline * height * 1ULL, 16); + ret->image = _aligned_malloc(1ull * ret->scanline * height, 16); if (!ret->image) { diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c freerdp2-2.11.7+dfsg1/libfreerdp/locale/xkb_layout_ids.c --- freerdp2-2.10.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/locale/xkb_layout_ids.c 2024-04-22 09:26:59.000000000 +0000 @@ -806,7 +806,7 @@ { "sk", KBD_SLOVAK, sk_variants }, /* Slovakia */ { "es", KBD_SPANISH, es_variants }, /* Spain */ { "se", KBD_SWEDISH, se_variants }, /* Sweden */ - { "ch", KBD_SWISS_FRENCH, ch_variants }, /* Switzerland */ + { "ch", KBD_SWISS_GERMAN, ch_variants }, /* Switzerland */ { "sy", KBD_SYRIAC, sy_variants }, /* Syria */ { "tj", 0, tj_variants }, /* Tajikistan */ { "lk", 0, lk_variants }, /* Sri Lanka */ diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/primitives/prim_copy.c freerdp2-2.11.7+dfsg1/libfreerdp/primitives/prim_copy.c --- freerdp2-2.10.0+dfsg1/libfreerdp/primitives/prim_copy.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/primitives/prim_copy.c 2024-04-22 09:26:59.000000000 +0000 @@ -60,14 +60,14 @@ if (p1m <= p2m) { - ULONG_PTR p1mEnd = p1m + (height - 1) * p1Step * 1ULL + width * p1Size * 1ULL; + ULONG_PTR p1mEnd = p1m + 1ull * (height - 1) * p1Step + 1ull * width * p1Size; if (p1mEnd > p2m) return TRUE; } else { - ULONG_PTR p2mEnd = p2m + (height - 1) * p2Step * 1ULL + width * p2Size * 1ULL; + ULONG_PTR p2mEnd = p2m + 1ull * (height - 1) * p2Step + 1ull * width * p2Size; if (p2mEnd > p1m) return TRUE; diff -Nru freerdp2-2.10.0+dfsg1/libfreerdp/primitives/primitives.c freerdp2-2.11.7+dfsg1/libfreerdp/primitives/primitives.c --- freerdp2-2.10.0+dfsg1/libfreerdp/primitives/primitives.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/libfreerdp/primitives/primitives.c 2024-04-22 09:26:59.000000000 +0000 @@ -157,7 +157,7 @@ if (!buf) goto fail; - winpr_RAND(buf, roi->width * roi->height * 1ULL); + winpr_RAND(buf, 1ull * roi->width * roi->height); ret->steps[i] = roi->width; } diff -Nru freerdp2-2.10.0+dfsg1/uwac/CMakeLists.txt freerdp2-2.11.7+dfsg1/uwac/CMakeLists.txt --- freerdp2-2.10.0+dfsg1/uwac/CMakeLists.txt 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/uwac/CMakeLists.txt 2024-04-22 09:26:59.000000000 +0000 @@ -17,8 +17,8 @@ # Soname versioning set(UWAC_VERSION_MAJOR "0") -set(UWAC_VERSION_MINOR "1") -set(UWAC_VERSION_REVISION "1") +set(UWAC_VERSION_MINOR "2") +set(UWAC_VERSION_REVISION "0") set(UWAC_VERSION "${UWAC_VERSION_MAJOR}.${UWAC_VERSION_MINOR}.${UWAC_VERSION_REVISION}") set(UWAC_VERSION_FULL "${UWAC_VERSION}") set(UWAC_API_VERSION "${UWAC_VERSION_MAJOR}") diff -Nru freerdp2-2.10.0+dfsg1/uwac/include/uwac/uwac.h freerdp2-2.11.7+dfsg1/uwac/include/uwac/uwac.h --- freerdp2-2.10.0+dfsg1/uwac/include/uwac/uwac.h 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/uwac/include/uwac/uwac.h 2024-04-22 09:26:59.000000000 +0000 @@ -107,7 +107,9 @@ UWAC_EVENT_CLIPBOARD_OFFER, UWAC_EVENT_OUTPUT_GEOMETRY, UWAC_EVENT_KEYBOARD_MODIFIERS, - UWAC_EVENT_POINTER_AXIS_DISCRETE + UWAC_EVENT_POINTER_AXIS_DISCRETE, + UWAC_EVENT_POINTER_FRAME, + UWAC_EVENT_POINTER_SOURCE }; /** @brief window states */ @@ -195,6 +197,23 @@ }; typedef struct uwac_pointer_axis_event UwacPointerAxisEvent; +struct uwac_pointer_frame_event +{ + int type; + UwacWindow* window; + UwacSeat* seat; +}; +typedef struct uwac_pointer_frame_event UwacPointerFrameEvent; + +struct uwac_pointer_source_event +{ + int type; + UwacWindow* window; + UwacSeat* seat; + enum wl_pointer_axis_source axis_source; +}; +typedef struct uwac_pointer_source_event UwacPointerSourceEvent; + struct uwac_touch_frame_event { int type; @@ -286,6 +305,8 @@ UwacPointerMotionEvent mouse_motion; UwacPointerButtonEvent mouse_button; UwacPointerAxisEvent mouse_axis; + UwacPointerFrameEvent mouse_frame; + UwacPointerSourceEvent mouse_source; UwacKeyboardEnterLeaveEvent keyboard_enter_leave; UwacKeyboardModifiersEvent keyboard_modifiers; UwacClipboardEvent clipboard; diff -Nru freerdp2-2.10.0+dfsg1/uwac/libuwac/uwac-input.c freerdp2-2.11.7+dfsg1/uwac/libuwac/uwac-input.c --- freerdp2-2.10.0+dfsg1/uwac/libuwac/uwac-input.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/uwac/libuwac/uwac-input.c 2024-04-22 09:26:59.000000000 +0000 @@ -846,12 +846,37 @@ static void pointer_frame(void* data, struct wl_pointer* wl_pointer) { - /*UwacSeat *seat = data;*/ + UwacPointerFrameEvent* event; + UwacSeat* seat = data; + UwacWindow* window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerFrameEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_FRAME); + if (!event) + return; + + event->seat = seat; + event->window = window; } static void pointer_axis_source(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source) { - /*UwacSeat *seat = data;*/ + UwacPointerSourceEvent* event; + UwacSeat* seat = data; + UwacWindow* window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerSourceEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_SOURCE); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->axis_source = axis_source; } static void pointer_axis_stop(void* data, struct wl_pointer* wl_pointer, uint32_t time, diff -Nru freerdp2-2.10.0+dfsg1/uwac/libuwac/uwac-window.c freerdp2-2.11.7+dfsg1/uwac/libuwac/uwac-window.c --- freerdp2-2.10.0+dfsg1/uwac/libuwac/uwac-window.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/uwac/libuwac/uwac-window.c 2024-04-22 09:26:59.000000000 +0000 @@ -320,14 +320,14 @@ w->buffers = newBuffers; memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers); - fd = uwac_create_anonymous_file(allocSize * nbuffers * 1ULL); + fd = uwac_create_anonymous_file(1ull * allocSize * nbuffers); if (fd < 0) { return UWAC_ERROR_INTERNAL; } - data = mmap(NULL, allocSize * nbuffers * 1ULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + data = mmap(NULL, 1ull * allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { @@ -339,7 +339,7 @@ if (!pool) { - munmap(data, allocSize * nbuffers * 1ULL); + munmap(data, 1ull * allocSize * nbuffers); ret = UWAC_ERROR_NOMEMORY; goto error_mmap; } @@ -764,7 +764,7 @@ if (copyContentForNextFrame) memcpy(nextDrawingBuffer->data, pendingBuffer->data, - window->stride * window->height * 1ULL); + 1ull * window->stride * window->height); UwacSubmitBufferPtr(window, pendingBuffer); return UWAC_SUCCESS; diff -Nru freerdp2-2.10.0+dfsg1/winpr/CMakeLists.txt freerdp2-2.11.7+dfsg1/winpr/CMakeLists.txt --- freerdp2-2.10.0+dfsg1/winpr/CMakeLists.txt 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/CMakeLists.txt 2024-04-22 09:26:59.000000000 +0000 @@ -57,7 +57,7 @@ endif() # Soname versioning -set(RAW_VERSION_STRING "2.10.0") +set(RAW_VERSION_STRING "2.11.7") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff -Nru freerdp2-2.10.0+dfsg1/winpr/include/winpr/wtypes.h.in freerdp2-2.11.7+dfsg1/winpr/include/winpr/wtypes.h.in --- freerdp2-2.10.0+dfsg1/winpr/include/winpr/wtypes.h.in 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/include/winpr/wtypes.h.in 2024-04-22 09:26:59.000000000 +0000 @@ -161,8 +161,9 @@ #ifndef __APPLE__ typedef __int32 BOOL; #else /* __APPLE__ */ +#include /* ensure compatibility with objc libraries */ -#if (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH +#if (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0) && defined(__LP64__)) || (defined(TARGET_OS_WATCH) && (TARGET_OS_WATCH != 0)) typedef bool BOOL; #else typedef signed char BOOL; diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/credui/CMakeLists.txt freerdp2-2.11.7+dfsg1/winpr/libwinpr/credui/CMakeLists.txt --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/credui/CMakeLists.txt 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/credui/CMakeLists.txt 2024-04-22 09:26:59.000000000 +0000 @@ -19,8 +19,8 @@ if(WIN32) winpr_library_add_public(credui) -endif() - -if(BUILD_TESTING) - add_subdirectory(test) +else() + if(BUILD_TESTING) + add_subdirectory(test) + endif() endif() diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/crt/CMakeLists.txt freerdp2-2.11.7+dfsg1/winpr/libwinpr/crt/CMakeLists.txt --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/crt/CMakeLists.txt 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/crt/CMakeLists.txt 2024-04-22 09:26:59.000000000 +0000 @@ -29,7 +29,7 @@ endif(NOT WITH_ICU) if (WITH_ICU) - find_package(ICU REQUIRED i18n uc io) + find_package(ICU REQUIRED i18n uc io data) winpr_include_directory_add(${ICU_INCLUDE_DIRS}) winpr_library_add_private(${ICU_LIBRARIES}) endif (WITH_ICU) diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/crt/unicode.c freerdp2-2.11.7+dfsg1/winpr/libwinpr/crt/unicode.c --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/crt/unicode.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/crt/unicode.c 2024-04-22 09:26:59.000000000 +0000 @@ -40,6 +40,8 @@ #include "../log.h" #define TAG WINPR_TAG("unicode") +#define UCNV_CONVERT 1 + /** * Notes on cross-platform Unicode portability: * @@ -201,6 +203,26 @@ targetCapacity = cchWideChar; error = U_ZERO_ERROR; +#if defined(UCNV_CONVERT) + if (cchWideChar == 0) + { + targetLength = + ucnv_convert("UTF-16LE", "UTF-8", NULL, 0, lpMultiByteStr, cbMultiByte, &error); + if (targetLength > 0) + targetLength /= sizeof(WCHAR); + cchWideChar = targetLength; + } + else + { + targetLength = + ucnv_convert("UTF-16LE", "UTF-8", targetStart, targetCapacity * sizeof(WCHAR), + lpMultiByteStr, cbMultiByte, &error); + if (targetLength > 0) + targetLength /= sizeof(WCHAR); + cchWideChar = U_SUCCESS(error) ? targetLength : 0; + } + +#else if (cchWideChar == 0) { u_strFromUTF8(NULL, 0, &targetLength, lpMultiByteStr, cbMultiByte, &error); @@ -212,6 +234,7 @@ &error); cchWideChar = U_SUCCESS(error) ? targetLength : 0; } +#endif } #else @@ -327,6 +350,21 @@ targetCapacity = cbMultiByte; error = U_ZERO_ERROR; +#if defined(UCNV_CONVERT) + if (cbMultiByte == 0) + { + targetLength = ucnv_convert("UTF-8", "UTF-16LE", NULL, 0, lpWideCharStr, + cchWideChar * sizeof(WCHAR), &error); + cbMultiByte = targetLength; + } + else + { + targetLength = ucnv_convert("UTF-8", "UTF-16LE", targetStart, targetCapacity, + lpWideCharStr, cchWideChar * sizeof(WCHAR), &error); + cbMultiByte = U_SUCCESS(error) ? targetLength : 0; + } + +#else if (cbMultiByte == 0) { u_strToUTF8(NULL, 0, &targetLength, lpWideCharStr, cchWideChar, &error); @@ -338,6 +376,7 @@ &error); cbMultiByte = U_SUCCESS(error) ? targetLength : 0; } +#endif } #else diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/crypto/cipher.c freerdp2-2.11.7+dfsg1/winpr/libwinpr/crypto/cipher.c --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/crypto/cipher.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/crypto/cipher.c 2024-04-22 09:26:59.000000000 +0000 @@ -66,7 +66,11 @@ if (!evp) return NULL; +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + EVP_CIPHER_CTX_reset((EVP_CIPHER_CTX*)ctx); +#else EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*)ctx); +#endif if (EVP_EncryptInit_ex((EVP_CIPHER_CTX*)ctx, evp, NULL, NULL, NULL) != 1) { EVP_CIPHER_CTX_free ((EVP_CIPHER_CTX*)ctx); diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/utils/collections/ArrayList.c freerdp2-2.11.7+dfsg1/winpr/libwinpr/utils/collections/ArrayList.c --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/utils/collections/ArrayList.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/utils/collections/ArrayList.c 2024-04-22 09:26:59.000000000 +0000 @@ -233,6 +233,18 @@ * Adds an object to the end of the ArrayList. */ +static int insert(wArrayList* arrayList, size_t index, void* obj) +{ + if (arrayList->object.fnObjectNew) + { + obj = arrayList->object.fnObjectNew(obj); + arrayList->array[index] = obj; + } + else + arrayList->array[index] = obj; + return index + 1; +} + int ArrayList_Add(wArrayList* arrayList, void* obj) { int index = -1; @@ -253,8 +265,7 @@ arrayList->capacity = newCapacity; } - arrayList->array[arrayList->size++] = obj; - index = arrayList->size; + index = arrayList->size = insert(arrayList, arrayList->size, obj); out: if (arrayList->synchronized) @@ -282,7 +293,7 @@ } else { - arrayList->array[index] = obj; + insert(arrayList, index, obj); } } diff -Nru freerdp2-2.10.0+dfsg1/winpr/libwinpr/utils/lodepng/lodepng.c freerdp2-2.11.7+dfsg1/winpr/libwinpr/utils/lodepng/lodepng.c --- freerdp2-2.10.0+dfsg1/winpr/libwinpr/utils/lodepng/lodepng.c 2023-02-16 09:55:03.000000000 +0000 +++ freerdp2-2.11.7+dfsg1/winpr/libwinpr/utils/lodepng/lodepng.c 2024-04-22 09:26:59.000000000 +0000 @@ -3815,7 +3815,7 @@ { size_t i; ColorTree tree; - size_t numpixels = w * h * 1ULL; + size_t numpixels = 1ull * w * h; if (lodepng_color_mode_equal(mode_out, mode_in)) { @@ -3918,7 +3918,7 @@ unsigned error = 0; size_t i; ColorTree tree; - size_t numpixels = w * h * 1ULL; + size_t numpixels = 1ull * w * h; unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0; unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1; @@ -4539,7 +4539,7 @@ if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) { CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); - removePaddingBits(out, in, w * bpp * 1ULL, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h); + removePaddingBits(out, in, 1ull * w * bpp, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h); } /*we can immediatly filter into the out buffer, no other steps needed*/ else @@ -4565,7 +4565,7 @@ bits between the different reduced images: each reduced image still starts nicely at a byte*/ removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], - passw[i] * bpp * 1ULL, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, + 1ull * passw[i] * bpp, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passh[i]); } } @@ -6056,7 +6056,7 @@ error = 83; /*alloc fail*/ if (!error) { - addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, w * bpp * 1ULL, h); + addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * w * bpp, h); error = filter(*out, padded, w, h, &info_png->color, settings); } free(padded); @@ -6100,8 +6100,8 @@ if (!padded) ERROR_BREAK(83); /*alloc fail*/ addPaddingBits(padded, &adam7[passstart[i]], - ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passw[i] * bpp * 1ULL, - passh[i] * 1ULL); + ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * passw[i] * bpp, + 1ull * passh[i]); error = filter(&(*out)[filter_passstart[i]], padded, passw[i], passh[i], &info_png->color, settings); free(padded);