diff options
55 files changed, 734 insertions, 312 deletions
diff --git a/.github/workflows/fuzzing.yml b/.github/workflows/fuzzing.yml index 948fd42..cf4794f 100644 --- a/.github/workflows/fuzzing.yml +++ b/.github/workflows/fuzzing.yml @@ -3,8 +3,10 @@ name: Fuzzing testing on: workflow_dispatch: branches: [ master, stable* ] - pull_request_target: + pull_request: branches: [ master, stable* ] + schedule: + - cron: "0 3 21 * *" jobs: fuzzing: @@ -15,14 +17,10 @@ jobs: strategy: fail-fast: false matrix: - sanitizer: [address] + sanitizer: [address, undefined] steps: - - uses: suzuki-shunsuke/get-pr-action@v0.1.0 - id: pr - uses: actions/checkout@v4 - with: - ref: ${{steps.pr.outputs.merge_commit_sha}} - name: Build fuzzers (${{ matrix.sanitizer }}) id: build diff --git a/CMakeLists.txt b/CMakeLists.txt index 7700e18..9ee67f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)") -set(RAW_VERSION_STRING "3.5.0") +set(RAW_VERSION_STRING "3.5.1") if(EXISTS "${PROJECT_SOURCE_DIR}/.source_tag") file(READ ${PROJECT_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -202,11 +202,6 @@ if (EXPORT_ALL_SYMBOLS) add_definitions(-DEXPORT_ALL_SYMBOLS) endif(EXPORT_ALL_SYMBOLS) -if(FREEBSD) - find_path(EPOLLSHIM_INCLUDE_DIR NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) - find_library(EPOLLSHIM_LIBS NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) -endif() - # Compiler-specific flags if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686") @@ -499,10 +494,6 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED") set(FFMPEG_FEATURE_PURPOSE "multimedia") set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback") -set(VAAPI_FEATURE_TYPE "OPTIONAL") -set(VAAPI_FEATURE_PURPOSE "multimedia") -set(VAAPI_FEATURE_DESCRIPTION "VA-API hardware acceleration for video playback") - set(OPENH264_FEATURE_TYPE "OPTIONAL") set(OPENH264_FEATURE_PURPOSE "codec") set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library") @@ -535,12 +526,10 @@ if(WIN32) set(WAYLAND_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "OPTIONAL") - set(VAAPI_FEATURE_TYPE "DISABLED") endif() if(APPLE) set(FFMPEG_FEATURE_TYPE "OPTIONAL") - set(VAAPI_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") if(IOS) set(PCSC_FEATURE_TYPE "DISABLED") @@ -550,7 +539,6 @@ endif() if(ANDROID) set(WAYLAND_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED") - set(VAAPI_FEATURE_TYPE "DISABLED") endif() find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAND_FEATURE_DESCRIPTION}) @@ -1,3 +1,19 @@ +# 2024-04-22 Version 3.5.1 + +This release eliminates a bunch of issues detected during oss-fuzz runs. +The test coverage was increased and detected issues eliminates, so an update +is highly recommended. + +Noteworthy changes: +* Lots of fixes for oss-fuzz reports +* Timezone detection fixes (#10106) +* SDL key remapping support (#10103) +* Improved help (#10099) +* FreeBSD epoll detection fix (#10097) + +For a complete and detailed change log since the last release run: +git log 3.5.1...3.5.0 + # 2024-04-16 Version 3.5.0 This release focus is on squashing bugs. diff --git a/channels/location/client/location_main.c b/channels/location/client/location_main.c index 281070f..df6b82e 100644 --- a/channels/location/client/location_main.c +++ b/channels/location/client/location_main.c @@ -110,7 +110,7 @@ static UINT location_channel_send(IWTSVirtualChannel* channel, wStream* s) static UINT location_send_client_ready_pdu(const LOCATION_CALLBACK* callback) { wStream sbuffer = { 0 }; - char buffer[32] = { 0 }; + BYTE buffer[32] = { 0 }; wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer)); WINPR_ASSERT(s); @@ -210,7 +210,7 @@ static UINT location_send_base_location3d(IWTSVirtualChannel* channel, const RDPLOCATION_BASE_LOCATION3D_PDU* pdu) { wStream sbuffer = { 0 }; - char buffer[32] = { 0 }; + BYTE buffer[32] = { 0 }; wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer)); WINPR_ASSERT(s); WINPR_ASSERT(channel); @@ -251,7 +251,7 @@ static UINT location_send_location2d_delta(IWTSVirtualChannel* channel, const RDPLOCATION_LOCATION2D_DELTA_PDU* pdu) { wStream sbuffer = { 0 }; - char buffer[32] = { 0 }; + BYTE buffer[32] = { 0 }; wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer)); WINPR_ASSERT(s); @@ -287,7 +287,7 @@ static UINT location_send_location3d_delta(IWTSVirtualChannel* channel, const RDPLOCATION_LOCATION3D_DELTA_PDU* pdu) { wStream sbuffer = { 0 }; - char buffer[32] = { 0 }; + BYTE buffer[32] = { 0 }; wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer)); WINPR_ASSERT(s); diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index c5828c1..3878807 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -112,7 +112,7 @@ UINT rail_send_channel_data(railPlugin* rail, wStream* src) */ static UINT rail_client_execute(RailClientContext* context, const RAIL_EXEC_ORDER* exec) { - char* exeOrFile = NULL; + const char* exeOrFile = NULL; UINT error = 0; railPlugin* rail = NULL; UINT16 flags = 0; diff --git a/channels/rail/server/rail_main.c b/channels/rail/server/rail_main.c index 8e38c2b..5089646 100644 --- a/channels/rail/server/rail_main.c +++ b/channels/rail/server/rail_main.c @@ -650,7 +650,7 @@ static UINT rail_read_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec) +static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec, char* args[]) { RAIL_EXEC_ORDER order = { 0 }; UINT16 exeLen = 0; @@ -671,30 +671,31 @@ static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec) if (exeLen > 0) { const SSIZE_T len = exeLen / sizeof(WCHAR); - exec->RemoteApplicationProgram = Stream_Read_UTF16_String_As_UTF8(s, len, NULL); + exec->RemoteApplicationProgram = args[0] = Stream_Read_UTF16_String_As_UTF8(s, len, NULL); if (!exec->RemoteApplicationProgram) goto fail; } if (workLen > 0) { const SSIZE_T len = workLen / sizeof(WCHAR); - exec->RemoteApplicationWorkingDir = Stream_Read_UTF16_String_As_UTF8(s, len, NULL); + exec->RemoteApplicationWorkingDir = args[1] = + Stream_Read_UTF16_String_As_UTF8(s, len, NULL); if (!exec->RemoteApplicationWorkingDir) goto fail; } if (argLen > 0) { const SSIZE_T len = argLen / sizeof(WCHAR); - exec->RemoteApplicationArguments = Stream_Read_UTF16_String_As_UTF8(s, len, NULL); + exec->RemoteApplicationArguments = args[2] = Stream_Read_UTF16_String_As_UTF8(s, len, NULL); if (!exec->RemoteApplicationArguments) goto fail; } return CHANNEL_RC_OK; fail: - free(exec->RemoteApplicationProgram); - free(exec->RemoteApplicationArguments); - free(exec->RemoteApplicationWorkingDir); + free(args[0]); + free(args[1]); + free(args[2]); *exec = order; return ERROR_INTERNAL_ERROR; } @@ -948,12 +949,14 @@ static UINT rail_recv_client_client_status_order(RailServerContext* context, static UINT rail_recv_client_exec_order(RailServerContext* context, wStream* s) { UINT error = 0; + char* args[3] = { 0 }; RAIL_EXEC_ORDER exec = { 0 }; if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_exec_order(s, &exec))) + error = rail_read_exec_order(s, &exec, args); + if (error) { WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error); return error; @@ -964,9 +967,9 @@ static UINT rail_recv_client_exec_order(RailServerContext* context, wStream* s) if (error) WLog_ERR(TAG, "context.Exec failed with error %" PRIu32 "", error); - free(exec.RemoteApplicationProgram); - free(exec.RemoteApplicationArguments); - free(exec.RemoteApplicationWorkingDir); + free(args[0]); + free(args[1]); + free(args[2]); return error; } diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 2ffa951..8cbb359 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -1861,7 +1861,7 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) UINT status = 0; rdpdrPlugin* plugin = (rdpdrPlugin*)rdpdr; - if (!rdpdr || !s) + if (!s) { Stream_Release(s); return CHANNEL_RC_NULL_DATA; @@ -1870,16 +1870,14 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) if (!plugin) { Stream_Release(s); - status = CHANNEL_RC_BAD_INIT_HANDLE; - } - else - { - const size_t pos = Stream_GetPosition(s); - rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] send"); - status = plugin->channelEntryPoints.pVirtualChannelWriteEx( - plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), pos, s); + return CHANNEL_RC_BAD_INIT_HANDLE; } + const size_t pos = Stream_GetPosition(s); + rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] send"); + status = plugin->channelEntryPoints.pVirtualChannelWriteEx( + plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), pos, s); + if (status != CHANNEL_RC_OK) { Stream_Release(s); diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index 1d39ed1..269e9a8 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -69,7 +69,7 @@ static UINT remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s) */ static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk) { - char* name = NULL; + const char* name = NULL; char* pass = NULL; const char* password = NULL; rdpSettings* settings = NULL; diff --git a/client/SDL/dialogs/sdl_connection_dialog.hpp b/client/SDL/dialogs/sdl_connection_dialog.hpp index f21f538..57e5596 100644 --- a/client/SDL/dialogs/sdl_connection_dialog.hpp +++ b/client/SDL/dialogs/sdl_connection_dialog.hpp @@ -89,15 +89,15 @@ class SDLConnectionDialog private: struct widget_cfg_t { - SDL_Color fgcolor; - SDL_Color bgcolor; + SDL_Color fgcolor = {}; + SDL_Color bgcolor = {}; SdlWidget widget; }; private: - rdpContext* _context; - SDL_Window* _window; - SDL_Renderer* _renderer; + rdpContext* _context = nullptr; + SDL_Window* _window = nullptr; + SDL_Renderer* _renderer = nullptr; mutable std::mutex _mux; std::string _title; std::string _msg; @@ -124,6 +124,6 @@ class SDLConnectionDialogHider SDLConnectionDialog* get(rdpContext* context); private: - SDLConnectionDialog* _dialog; - bool _visible; + SDLConnectionDialog* _dialog = nullptr; + bool _visible = false; }; diff --git a/client/SDL/sdl_disp.cpp b/client/SDL/sdl_disp.cpp index ffd13c8..34863ba 100644 --- a/client/SDL/sdl_disp.cpp +++ b/client/SDL/sdl_disp.cpp @@ -142,6 +142,8 @@ static BOOL sdl_disp_check_context(void* context, SdlContext** ppsdl, sdlDispCon return FALSE; auto sdl = get_context(context); + if (!sdl) + return FALSE; if (!sdl->context()->settings) return FALSE; @@ -200,6 +202,9 @@ Uint32 sdlDispContext::OnTimer(Uint32 interval, void* param) return 0; SdlContext* sdl = ctx->_sdl; + if (!sdl) + return 0; + sdlDispContext* sdlDisp = nullptr; rdpSettings* settings = nullptr; diff --git a/client/SDL/sdl_kbd.cpp b/client/SDL/sdl_kbd.cpp index 984614e..c6e668d 100644 --- a/client/SDL/sdl_kbd.cpp +++ b/client/SDL/sdl_kbd.cpp @@ -488,6 +488,66 @@ uint32_t sdlInput::prefKeyValue(const std::string& key, uint32_t fallback) return val; } +std::list<std::string> sdlInput::tokenize(const std::string& data, const std::string& delimiter) +{ + size_t lastpos = 0; + size_t pos = 0; + std::list<std::string> list; + while ((pos = data.find(delimiter, lastpos)) != std::string::npos) + { + auto token = data.substr(lastpos, pos); + lastpos = pos + 1; + list.push_back(token); + } + auto token = data.substr(lastpos); + list.push_back(token); + return list; +} + +bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value) +{ + int rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIu32, &key, &value); + if (rc != 2) + rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIx32 "", &key, &value); + if (rc != 2) + rc = sscanf(token.c_str(), "%" PRIu32 "=%" PRIx32, &key, &value); + if (rc != 2) + rc = sscanf(token.c_str(), "%" PRIx32 "=%" PRIu32, &key, &value); + return (rc == 2); +} + +uint32_t sdlInput::remapScancode(uint32_t scancode) +{ + if (!_remapInitialized.exchange(true)) + remapInitialize(); + auto it = _remapList.find(scancode); + if (it != _remapList.end()) + return it->second; + return scancode; +} + +void sdlInput::remapInitialize() +{ + WINPR_ASSERT(_sdl); + + auto context = _sdl->context(); + WINPR_ASSERT(context); + auto KeyboardRemappingList = + freerdp_settings_get_string(context->settings, FreeRDP_KeyboardRemappingList); + if (!KeyboardRemappingList) + return; + + auto list = tokenize(KeyboardRemappingList); + for (auto& token : list) + { + uint32_t key = 0; + uint32_t value = 0; + if (!extract(token, key, value)) + continue; + _remapList.emplace(key, value); + } +} + BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { WINPR_ASSERT(ev); @@ -526,8 +586,10 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) } } } + + auto scancode = remapScancode(rdp_scancode); return freerdp_input_send_keyboard_event_ex(_sdl->context()->input, ev->type == SDL_KEYDOWN, - ev->repeat, rdp_scancode); + ev->repeat, scancode); } BOOL sdlInput::keyboard_grab(Uint32 windowID, SDL_bool enable) @@ -564,5 +626,4 @@ BOOL sdlInput::mouse_grab(Uint32 windowID, SDL_bool enable) sdlInput::sdlInput(SdlContext* sdl) : _sdl(sdl), _lastWindowID(UINT32_MAX) { - WINPR_ASSERT(_sdl); } diff --git a/client/SDL/sdl_kbd.hpp b/client/SDL/sdl_kbd.hpp index 2a6c7fa..c75da4d 100644 --- a/client/SDL/sdl_kbd.hpp +++ b/client/SDL/sdl_kbd.hpp @@ -20,6 +20,9 @@ #pragma once #include <string> +#include <map> +#include <list> +#include <atomic> #include <winpr/wtypes.h> #include <freerdp/freerdp.h> @@ -51,6 +54,16 @@ class sdlInput static uint32_t prefKeyValue(const std::string& key, uint32_t fallback = SDL_SCANCODE_UNKNOWN); private: + static std::list<std::string> tokenize(const std::string& data, + const std::string& delimiter = ","); + static bool extract(const std::string& token, uint32_t& key, uint32_t& value); + + uint32_t remapScancode(uint32_t scancode); + void remapInitialize(); + + private: SdlContext* _sdl; Uint32 _lastWindowID; + std::map<uint32_t, uint32_t> _remapList; + std::atomic<bool> _remapInitialized = false; }; diff --git a/client/Wayland/wlf_cliprdr.c b/client/Wayland/wlf_cliprdr.c index f0c3318..112ffd1 100644 --- a/client/Wayland/wlf_cliprdr.c +++ b/client/Wayland/wlf_cliprdr.c @@ -70,6 +70,13 @@ typedef struct char* responseMime; } wlf_request; +typedef struct +{ + const FILE* responseFile; + UINT32 responseFormat; + const char* responseMime; +} wlf_const_request; + struct wlf_clipboard { wlfContext* wfc; @@ -311,7 +318,7 @@ static BOOL wlf_cliprdr_add_client_format(wfClipboard* clipboard, const char* mi * * @return 0 on success, otherwise a Win32 error code */ -static UINT wlf_cliprdr_send_data_request(wfClipboard* clipboard, const wlf_request* rq) +static UINT wlf_cliprdr_send_data_request(wfClipboard* clipboard, const wlf_const_request* rq) { WINPR_ASSERT(rq); @@ -522,7 +529,7 @@ static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char* EnterCriticalSection(&clipboard->lock); - wlf_request request = { 0 }; + wlf_const_request request = { 0 }; if (wlf_mime_is_html(mime)) { request.responseMime = mime_html; @@ -720,7 +727,7 @@ wlf_cliprdr_server_format_data_request(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { UINT rc = CHANNEL_RC_OK; - BYTE* data = NULL; + char* data = NULL; size_t size = 0; const char* mime = NULL; UINT32 formatId = 0; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 01d5b37..8d24af7 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -5321,7 +5321,7 @@ static void argv_free(int* pargc, char** pargv[]) free(argv); } -static BOOL argv_append(int* pargc, char** pargv[], const char* what) +static BOOL argv_append(int* pargc, char** pargv[], char* what) { WINPR_ASSERT(pargc); WINPR_ASSERT(pargv); diff --git a/cmake/PlatformDefaults.cmake b/cmake/PlatformDefaults.cmake index 30c8a92..0037ebe 100644 --- a/cmake/PlatformDefaults.cmake +++ b/cmake/PlatformDefaults.cmake @@ -100,4 +100,9 @@ if (USE_PLATFORM_DEFAULT) set(WINPR_TIMEZONE_FILE "/var/db/zoneinfo") endif() add_definitions("-DWINPR_TIMEZONE_FILE=\"${WINPR_TIMEZONE_FILE}\"") + + if(FREEBSD) + find_path(EPOLLSHIM_INCLUDE_DIR NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) + find_library(EPOLLSHIM_LIBS NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) + endif() endif() diff --git a/include/freerdp/rail.h b/include/freerdp/rail.h index b3cd702..64a01e5 100644 --- a/include/freerdp/rail.h +++ b/include/freerdp/rail.h @@ -347,9 +347,9 @@ typedef struct typedef struct { UINT16 flags; - char* RemoteApplicationProgram; - char* RemoteApplicationWorkingDir; - char* RemoteApplicationArguments; + const char* RemoteApplicationProgram; + const char* RemoteApplicationWorkingDir; + const char* RemoteApplicationArguments; } RAIL_EXEC_ORDER; typedef struct diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 512aeae..c9538c8 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -500,12 +500,12 @@ static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* clear, wStream* s, { case 0: /* Uncompressed */ { - UINT32 nSrcStep = width * FreeRDPGetBytesPerPixel(PIXEL_FORMAT_BGR24); - UINT32 nSrcSize = nSrcStep * height; + const UINT32 nSrcStep = width * FreeRDPGetBytesPerPixel(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; } @@ -798,10 +798,16 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; if (count > 0) - pSrcPixel = - &vBarShortEntry - ->pixels[(y - vBarYOn) * FreeRDPGetBytesPerPixel(clear->format)]; - + { + const size_t offset = + (1ull * y - vBarYOn) * FreeRDPGetBytesPerPixel(clear->format); + pSrcPixel = &vBarShortEntry->pixels[offset]; + if (offset + count > vBarShortEntry->count) + { + WLog_ERR(TAG, "offset + count > vBarShortEntry->count"); + return FALSE; + } + } for (UINT32 x = 0; x < count; x++) { UINT32 color = 0; @@ -1169,7 +1175,10 @@ CLEAR_CONTEXT* clear_context_new(BOOL Compressor) return clear; error_nsc: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC clear_context_free(clear); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 186d477..2c3d08a 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -583,16 +583,16 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette, UINT32 flags) { - const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat); - const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat); - const UINT32 copyDstWidth = nWidth * dstByte; - const UINT32 xSrcOffset = nXSrc * srcByte; - const UINT32 xDstOffset = nXDst * dstByte; + const SSIZE_T dstByte = FreeRDPGetBytesPerPixel(DstFormat); + const SSIZE_T srcByte = FreeRDPGetBytesPerPixel(SrcFormat); + const SSIZE_T copyDstWidth = nWidth * dstByte; + const SSIZE_T xSrcOffset = nXSrc * srcByte; + const SSIZE_T xDstOffset = nXDst * dstByte; const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE; - UINT32 srcVOffset = 0; - INT32 srcVMultiplier = 1; - UINT32 dstVOffset = 0; - INT32 dstVMultiplier = 1; + SSIZE_T srcVOffset = 0; + SSIZE_T srcVMultiplier = 1; + SSIZE_T dstVOffset = 0; + SSIZE_T dstVMultiplier = 1; if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX)) return FALSE; @@ -608,24 +608,24 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D if (vSrcVFlip) { - srcVOffset = (nHeight - 1) * nSrcStep; + srcVOffset = (nHeight - 1ll) * nSrcStep; srcVMultiplier = -1; } if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColorIgnoreAlpha(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -645,29 +645,29 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D } else if (FreeRDPAreColorFormatsEqualNoAlpha(SrcFormat, DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } else { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -699,10 +699,10 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n const UINT32 xSrcOffset = nXSrc * srcByte; const UINT32 xDstOffset = nXDst * dstByte; const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE; - UINT32 srcVOffset = 0; - INT32 srcVMultiplier = 1; - UINT32 dstVOffset = 0; - INT32 dstVMultiplier = 1; + SSIZE_T srcVOffset = 0; + SSIZE_T srcVMultiplier = 1; + SSIZE_T dstVOffset = 0; + SSIZE_T dstVMultiplier = 1; if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX)) return FALSE; @@ -718,16 +718,16 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n if (vSrcVFlip) { - srcVOffset = (nHeight - 1) * nSrcStep; + srcVOffset = (nHeight - 1ll) * nSrcStep; srcVMultiplier = -1; } if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { - const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; @@ -756,44 +756,44 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n /* Copy down */ if (nYDst < nYSrc) { - for (INT32 y = 0; y < (INT32)nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy up */ else if (nYDst > nYSrc) { - for (INT32 y = (INT32)nHeight - 1; y >= 0; y--) + for (SSIZE_T y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy left */ else if (nXSrc > nXDst) { - for (INT32 y = 0; y < (INT32)nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy right */ else if (nXSrc < nXDst) { - for (INT32 y = (INT32)nHeight - 1; y >= 0; y--) + for (SSIZE_T y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } @@ -804,16 +804,16 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n } else { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { - const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -847,6 +847,9 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 if (!pDstData || !pSrcData) return FALSE; + if ((nWidth == 0) || (nHeight == 0)) + return TRUE; + if (nDstStep == 0) nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat); diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c index 54492e1..a2ad12f 100644 --- a/libfreerdp/codec/h264_ffmpeg.c +++ b/libfreerdp/codec/h264_ffmpeg.c @@ -636,6 +636,7 @@ static BOOL libavcodec_init(H264_CONTEXT* h264) goto fail_hwdevice_create; } } + WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 decoding"); sys->codecDecoderContext->get_format = libavcodec_get_format; sys->hw_pix_fmt = AV_PIX_FMT_VAAPI; diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index df148b6..262895d 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -212,7 +212,7 @@ static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEn runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -262,7 +262,7 @@ static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, U runLength = *pbOrderHdr & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -282,7 +282,7 @@ static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 3, pbEnd)) { *advance = 0; return 0; @@ -305,7 +305,7 @@ static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT runLength = *pbOrderHdr & g_MaskLiteRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -735,7 +735,10 @@ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor) return interleaved; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC bitmap_interleaved_context_free(interleaved); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index 74f4e28..d1b594b 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -86,8 +86,8 @@ static BOOL nsc_decode(NSC_CONTEXT* context) for (UINT32 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; @@ -250,6 +250,13 @@ static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s) } 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); @@ -363,7 +370,10 @@ NSC_CONTEXT* nsc_context_new(void) NSC_INIT_SIMD(context); return context; error: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC nsc_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 4b51a02..e894761 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -1747,7 +1747,10 @@ BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, UINT32 max if (!freerdp_bitmap_planar_context_reset(context, maxWidth, maxHeight)) { + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC freerdp_bitmap_planar_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index df98ad3..3ab84ef 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -2312,67 +2312,11 @@ static SSIZE_T progressive_parse_block(PROGRESSIVE_CONTEXT* progressive, wStream return rc; } -INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize, - BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, - UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId, - UINT32 frameId) +static BOOL update_tiles(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_SURFACE_CONTEXT* surface, + BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, + UINT32 nYDst, PROGRESSIVE_BLOCK_REGION* region, REGION16* invalidRegion) { - INT32 rc = 1; - - WINPR_ASSERT(progressive); - PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId); - - if (!surface) - { - WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion no surface for %" PRIu16, - surfaceId); - return -1001; - } - - PROGRESSIVE_BLOCK_REGION* region = &progressive->region; - WINPR_ASSERT(region); - - if (surface->frameId != frameId) - { - surface->frameId = frameId; - surface->numUpdatedTiles = 0; - } - - wStream ss = { 0 }; - wStream* s = Stream_StaticConstInit(&ss, pSrcData, SrcSize); - WINPR_ASSERT(s); - - switch (DstFormat) - { - case PIXEL_FORMAT_RGBA32: - case PIXEL_FORMAT_RGBX32: - case PIXEL_FORMAT_BGRA32: - case PIXEL_FORMAT_BGRX32: - progressive->format = DstFormat; - break; - default: - progressive->format = PIXEL_FORMAT_XRGB32; - break; - } - - const size_t start = Stream_GetPosition(s); - progressive->state = 0; /* Set state to not initialized */ - while (Stream_GetRemainingLength(s) > 0) - { - if (progressive_parse_block(progressive, s, surface, region) < 0) - goto fail; - } - - const size_t end = Stream_GetPosition(s); - if ((end - start) != SrcSize) - { - WLog_Print(progressive->log, WLOG_ERROR, - "total block len %" PRIuz " does not match read data %" PRIu32, end - start, - SrcSize); - rc = -1041; - goto fail; - } - + BOOL rc = TRUE; REGION16 clippingRects = { 0 }; region16_init(&clippingRects); @@ -2425,13 +2369,11 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD goto fail; if (rect->top + height > surface->height) goto fail; - if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, + rc = freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, height, tile->data, progressive->format, tile->stride, nXSrc, - nYSrc, NULL, FREERDP_KEEP_DST_ALPHA)) - { - rc = -42; + nYSrc, NULL, FREERDP_KEEP_DST_ALPHA); + if (!rc) break; - } if (invalidRegion) region16_union_rect(invalidRegion, invalidRegion, rect); @@ -2441,8 +2383,75 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD tile->dirty = FALSE; } +fail: region16_uninit(&clippingRects); - surface->numUpdatedTiles = 0; + return rc; +} + +INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, + UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId, + UINT32 frameId) +{ + INT32 rc = 1; + + WINPR_ASSERT(progressive); + PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId); + + if (!surface) + { + WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion no surface for %" PRIu16, + surfaceId); + return -1001; + } + + PROGRESSIVE_BLOCK_REGION* region = &progressive->region; + WINPR_ASSERT(region); + + if (surface->frameId != frameId) + { + surface->frameId = frameId; + surface->numUpdatedTiles = 0; + } + + wStream ss = { 0 }; + wStream* s = Stream_StaticConstInit(&ss, pSrcData, SrcSize); + WINPR_ASSERT(s); + + switch (DstFormat) + { + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_BGRX32: + progressive->format = DstFormat; + break; + default: + progressive->format = PIXEL_FORMAT_XRGB32; + break; + } + + const size_t start = Stream_GetPosition(s); + progressive->state = 0; /* Set state to not initialized */ + while (Stream_GetRemainingLength(s) > 0) + { + if (progressive_parse_block(progressive, s, surface, region) < 0) + goto fail; + } + + const size_t end = Stream_GetPosition(s); + if ((end - start) != SrcSize) + { + WLog_Print(progressive->log, WLOG_ERROR, + "total block len %" PRIuz " does not match read data %" PRIu32, end - start, + SrcSize); + rc = -1041; + goto fail; + } + + if (!update_tiles(progressive, surface, pDstData, DstFormat, nDstStep, nXDst, nYDst, region, + invalidRegion)) + return -2002; fail: return rc; } @@ -2631,7 +2640,10 @@ PROGRESSIVE_CONTEXT* progressive_context_new_ex(BOOL Compressor, UINT32 Threadin } return progressive; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC progressive_context_free(progressive); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 66ed1e0..c12f6d4 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -342,7 +342,10 @@ RFX_CONTEXT* rfx_context_new_ex(BOOL encoder, UINT32 ThreadingFlags) context->expectedDataBlockType = WBT_FRAME_BEGIN; return context; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC rfx_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/test/TestFuzzCodecs.c b/libfreerdp/codec/test/TestFuzzCodecs.c index d83d8d4..f923765 100644 --- a/libfreerdp/codec/test/TestFuzzCodecs.c +++ b/libfreerdp/codec/test/TestFuzzCodecs.c @@ -453,28 +453,15 @@ int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) if (Size < 4) return 0; - int i = 0; - winpr_RAND(&i, sizeof(i)); - i = i % 18; - - if (i < 2) - TestFreeRDPCodecClear(Data, Size); - else if (i < 4) - TestFreeRDPCodecXCrush(Data, Size); - else if (i < 6) - TestFreeRDPCodecZGfx(Data, Size); - else if (i < 8) - TestFreeRDPCodecNCrush(Data, Size); - else if (i < 10) - TestFreeRDPCodecRemoteFX(Data, Size); - else if (i < 12) - TestFreeRDPCodecMppc(Data, Size); - else if (i < 14) - TestFreeRDPCodecProgressive(Data, Size); - else if (i < 16) - TestFreeRDPCodecInterleaved(Data, Size); - else if (i < 18) - TestFreeRDPCodecPlanar(Data, Size); + TestFreeRDPCodecClear(Data, Size); + TestFreeRDPCodecXCrush(Data, Size); + TestFreeRDPCodecZGfx(Data, Size); + TestFreeRDPCodecNCrush(Data, Size); + TestFreeRDPCodecRemoteFX(Data, Size); + TestFreeRDPCodecMppc(Data, Size); + TestFreeRDPCodecProgressive(Data, Size); + TestFreeRDPCodecInterleaved(Data, Size); + TestFreeRDPCodecPlanar(Data, Size); return 0; } diff --git a/libfreerdp/codec/yuv.c b/libfreerdp/codec/yuv.c index c546566..97c2374 100644 --- a/libfreerdp/codec/yuv.c +++ b/libfreerdp/codec/yuv.c @@ -251,7 +251,10 @@ YUV_CONTEXT* yuv_context_new(BOOL encoder, UINT32 ThreadingFlags) return ret; error_threadpool: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC yuv_context_free(ret); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index b7ee275..3a9d2e5 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -382,16 +382,46 @@ static BYTE* aligned_zgfx_malloc(size_t size) 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 = 0; wStream sbuffer = { 0 }; + size_t used = 0; + BYTE* pConcatenated = NULL; wStream* stream = Stream_StaticConstInit(&sbuffer, pSrcData, SrcSize); WINPR_ASSERT(zgfx); WINPR_ASSERT(stream); + WINPR_ASSERT(ppDstData); + WINPR_ASSERT(pDstSize); + + *ppDstData = NULL; + *pDstSize = 0; if (!Stream_CheckAndLogRequiredLength(TAG, stream, 1)) goto fail; @@ -403,16 +433,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY 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) { @@ -420,8 +449,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY UINT16 segmentNumber = 0; UINT16 segmentCount = 0; UINT32 uncompressedSize = 0; - BYTE* pConcatenated = NULL; - size_t used = 0; if (!Stream_CheckAndLogRequiredLength(TAG, stream, 6)) goto fail; @@ -429,17 +456,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */ Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */ - if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, 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_CheckAndLogRequiredLength(TAG, stream, sizeof(UINT32))) @@ -450,16 +466,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY 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 { @@ -468,6 +483,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY status = 1; fail: + if (status < 0) + free(pConcatenated); return status; } diff --git a/libfreerdp/core/aad.c b/libfreerdp/core/aad.c index 15eabed..00593a0 100644 --- a/libfreerdp/core/aad.c +++ b/libfreerdp/core/aad.c @@ -716,11 +716,11 @@ static char* bn_to_base64_url(wLog* wlog, rdpPrivateKey* key, enum FREERDP_KEY_P WINPR_ASSERT(key); size_t len = 0; - char* bn = freerdp_key_get_param(key, param, &len); + BYTE* bn = freerdp_key_get_param(key, param, &len); if (!bn) return NULL; - char* b64 = (char*)crypto_base64url_encode(bn, len); + char* b64 = crypto_base64url_encode(bn, len); free(bn); if (!b64) diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 733a763..f2d035a 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -1765,6 +1765,9 @@ static BOOL gcc_update_server_random(rdpSettings* settings) */ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { + if (!gcc_update_server_random(mcs_get_settings(mcs))) + return FALSE; + const rdpSettings* settings = mcs_get_const_settings(mcs); WINPR_ASSERT(s); @@ -1779,8 +1782,6 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE) return TRUE; - if (!gcc_update_server_random(settings)) - return FALSE; if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32) + settings->ServerRandomLength)) return FALSE; diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 7d6eec1..3395e4d 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -1398,6 +1398,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; + len = strnlen(info->domain, charLen + 1); if (len > charLen) return FALSE; diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 855b700..bef1b45 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -797,9 +797,11 @@ static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value) return TRUE; } + static INLINE BOOL update_read_delta(wStream* s, INT32* value) { BYTE byte = 0; + UINT32 uvalue = 0; if (!Stream_CheckAndLogRequiredLength(TAG, s, 1)) return FALSE; @@ -807,9 +809,9 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value) Stream_Read_UINT8(s, byte); if (byte & 0x40) - *value = (byte | ~0x3F); + uvalue = (byte | ~0x3F); else - *value = (byte & 0x3F); + uvalue = (byte & 0x3F); if (byte & 0x80) { @@ -817,8 +819,9 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value) return FALSE; Stream_Read_UINT8(s, byte); - *value = (*value << 8) | byte; + uvalue = (uvalue << 8) | byte; } + *value = (INT32)uvalue; return TRUE; } @@ -2171,7 +2174,9 @@ static BOOL update_read_ellipse_cb_order(const char* orderName, wStream* s, return TRUE; return FALSE; } + /* Secondary Drawing Orders */ +WINPR_ATTR_MALLOC(free_cache_bitmap_order, 2) static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wStream* s, BOOL compressed, UINT16 flags) { @@ -2290,6 +2295,7 @@ BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache return TRUE; } +WINPR_ATTR_MALLOC(free_cache_bitmap_v2_order, 2) static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s, BOOL compressed, UINT16 flags) { @@ -2466,6 +2472,8 @@ BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache cache_bitmap_v2->compressed = compressed; return TRUE; } + +WINPR_ATTR_MALLOC(free_cache_bitmap_v3_order, 2) static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s, UINT16 flags) { @@ -2571,6 +2579,8 @@ BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache Stream_Write(s, bitmapData->data, bitmapData->length); return TRUE; } + +WINPR_ATTR_MALLOC(free_cache_color_table_order, 2) static CACHE_COLOR_TABLE_ORDER* update_read_cache_color_table_order(rdpUpdate* update, wStream* s, UINT16 flags) { diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 42c4c21..fba9281 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -1532,6 +1532,7 @@ BOOL freerdp_peer_context_new_ex(freerdp_peer* client, const rdpSettings* settin if (!client) return FALSE; + WINPR_ASSERT(client->ContextSize >= sizeof(rdpContext)); if (!(context = (rdpContext*)calloc(1, client->ContextSize))) goto fail; diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c index 8538a90..5343a07 100644 --- a/libfreerdp/core/redirection.c +++ b/libfreerdp/core/redirection.c @@ -243,7 +243,7 @@ static BOOL rdp_redirection_read_base64_wchar(UINT32 flag, wStream* s, UINT32* p const WCHAR* wchar = (const WCHAR*)ptr; size_t utf8_len = 0; - char* utf8 = ConvertWCharNToUtf8Alloc(wchar, *pLength, &utf8_len); + char* utf8 = ConvertWCharNToUtf8Alloc(wchar, *pLength / sizeof(WCHAR), &utf8_len); if (!utf8) goto fail; diff --git a/libfreerdp/core/test/CMakeLists.txt b/libfreerdp/core/test/CMakeLists.txt index ebd8fef..9b2e654 100644 --- a/libfreerdp/core/test/CMakeLists.txt +++ b/libfreerdp/core/test/CMakeLists.txt @@ -10,7 +10,9 @@ set(${MODULE_PREFIX}_TESTS TestSettings.c) set(FUZZERS - TestFuzzCryptoCertificateDataSetPEM.c + TestFuzzCoreClient.c + TestFuzzCoreServer.c + TestFuzzCryptoCertificateDataSetPEM.c ) if(WITH_SAMPLE AND WITH_SERVER AND NOT WIN32) @@ -34,7 +36,7 @@ add_definitions(-DTESTING_SRC_DIRECTORY="${PROJECT_SOURCE_DIR}") target_link_libraries(${MODULE_NAME} freerdp winpr freerdp-client) include (AddFuzzerTest) -add_fuzzer_test("${FUZZERS}" "freerdp winpr") +add_fuzzer_test("${FUZZERS}" "freerdp-client freerdp winpr") set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") @@ -44,4 +46,3 @@ foreach(test ${${MODULE_PREFIX}_TESTS}) endforeach() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Core/Test") - diff --git a/libfreerdp/core/test/TestFuzzCoreClient.c b/libfreerdp/core/test/TestFuzzCoreClient.c new file mode 100644 index 0000000..5c67497 --- /dev/null +++ b/libfreerdp/core/test/TestFuzzCoreClient.c @@ -0,0 +1,116 @@ +#include <freerdp/client.h> + +#include "../fastpath.h" +#include "../surface.h" +#include "../window.h" +#include "../info.h" +#include "../multitransport.h" + +static BOOL test_client(const uint8_t* Data, size_t Size) +{ + RDP_CLIENT_ENTRY_POINTS entry = { 0 }; + + entry.Version = RDP_CLIENT_INTERFACE_VERSION; + entry.Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1); + entry.ContextSize = sizeof(rdpContext); + + rdpContext* context = freerdp_client_context_new(&entry); + if (!context) + goto fail; + + rdpRdp* rdp = context->rdp; + WINPR_ASSERT(rdp); + + wStream sbuffer = { 0 }; + wStream* s = Stream_StaticConstInit(&sbuffer, Data, Size); + + { + rdpFastPath* fastpath = rdp->fastpath; + WINPR_ASSERT(fastpath); + + fastpath_recv_updates(fastpath, s); + fastpath_recv_inputs(fastpath, s); + + UINT16 length = 0; + fastpath_read_header_rdp(fastpath, s, &length); + fastpath_decrypt(fastpath, s, &length); + } + + { + UINT16 length = 0; + UINT16 flags = 0; + UINT16 channelId = 0; + UINT16 tpktLength = 0; + UINT16 remainingLength = 0; + UINT16 type = 0; + UINT16 securityFlags = 0; + UINT32 share_id = 0; + BYTE compressed_type = 0; + BYTE btype = 0; + UINT16 compressed_len = 0; + + rdp_recv_callback(rdp->transport, s, rdp); + rdp_read_security_header(rdp, s, &flags, &length); + rdp_read_header(rdp, s, &length, &channelId); + rdp_read_share_control_header(rdp, s, &tpktLength, &remainingLength, &type, &channelId); + rdp_read_share_data_header(rdp, s, &length, &btype, &share_id, &compressed_type, + &compressed_len); + rdp_recv_enhanced_security_redirection_packet(rdp, s); + rdp_recv_out_of_sequence_pdu(rdp, s, type, length); + rdp_recv_message_channel_pdu(rdp, s, securityFlags); + } + { + rdpUpdate* update = rdp->update; + UINT16 channelId = 0; + UINT16 length = 0; + UINT16 pduSource = 0; + UINT16 pduLength = 0; + update_recv_order(update, s); + update_recv_altsec_window_order(update, s); + update_recv_play_sound(update, s); + update_recv_pointer(update, s); + update_recv_surfcmds(update, s); + rdp_recv_get_active_header(rdp, s, &channelId, &length); + rdp_recv_demand_active(rdp, s, pduSource, length); + rdp_recv_confirm_active(rdp, s, pduLength); + } + { + rdpNla* nla = nla_new(rdp->context, rdp->transport); + nla_recv_pdu(nla, s); + nla_free(nla); + } + { + rdp_recv_heartbeat_packet(rdp, s); + rdp->state = CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE; + rdp_recv_client_info(rdp, s); + rdp_recv_save_session_info(rdp, s); + } + { + freerdp_is_valid_mcs_create_request(Data, Size); + freerdp_is_valid_mcs_create_response(Data, Size); + } + { + multitransport_recv_request(rdp->multitransport, s); + multitransport_recv_response(rdp->multitransport, s); + } + { + autodetect_recv_request_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s); + autodetect_recv_response_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s); + } + { + rdp_recv_deactivate_all(rdp, s); + rdp_recv_server_synchronize_pdu(rdp, s); + rdp_recv_client_synchronize_pdu(rdp, s); + + rdp_recv_data_pdu(rdp, s); + rdp_recv_font_map_pdu(rdp, s); + } +fail: + freerdp_client_context_free(context); +} + +int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) +{ + test_client(Data, Size); + return 0; +} diff --git a/libfreerdp/core/test/TestFuzzCoreServer.c b/libfreerdp/core/test/TestFuzzCoreServer.c new file mode 100644 index 0000000..cd469f4 --- /dev/null +++ b/libfreerdp/core/test/TestFuzzCoreServer.c @@ -0,0 +1,108 @@ +#include <freerdp/peer.h> + +#include "../fastpath.h" +#include "../surface.h" +#include "../window.h" +#include "../info.h" +#include "../multitransport.h" + +static BOOL test_server(const uint8_t* Data, size_t Size) +{ + freerdp_peer* client = calloc(1, sizeof(freerdp_peer)); + if (!client) + goto fail; + client->ContextSize = sizeof(rdpContext); + if (!freerdp_peer_context_new(client)) + goto fail; + + WINPR_ASSERT(client->context); + rdpRdp* rdp = client->context->rdp; + WINPR_ASSERT(rdp); + + wStream sbuffer = { 0 }; + wStream* s = Stream_StaticConstInit(&sbuffer, Data, Size); + + { + rdpFastPath* fastpath = rdp->fastpath; + WINPR_ASSERT(fastpath); + + fastpath_recv_updates(fastpath, s); + fastpath_recv_inputs(fastpath, s); + + UINT16 length = 0; + fastpath_read_header_rdp(fastpath, s, &length); + fastpath_decrypt(fastpath, s, &length); + } + + { + UINT16 length = 0; + UINT16 flags = 0; + UINT16 channelId = 0; + UINT16 tpktLength = 0; + UINT16 remainingLength = 0; + UINT16 type = 0; + UINT16 securityFlags = 0; + UINT32 share_id = 0; + BYTE compressed_type = 0; + BYTE btype = 0; + UINT16 compressed_len = 0; + rdp_read_security_header(rdp, s, &flags, &length); + rdp_read_header(rdp, s, &length, &channelId); + rdp_read_share_control_header(rdp, s, &tpktLength, &remainingLength, &type, &channelId); + rdp_read_share_data_header(rdp, s, &length, &btype, &share_id, &compressed_type, + &compressed_len); + rdp_recv_message_channel_pdu(rdp, s, securityFlags); + } + { + rdpUpdate* update = rdp->update; + UINT16 channelId = 0; + UINT16 length = 0; + UINT16 pduSource = 0; + UINT16 pduLength = 0; + update_recv_order(update, s); + update_recv_altsec_window_order(update, s); + update_recv_play_sound(update, s); + update_recv_pointer(update, s); + update_recv_surfcmds(update, s); + rdp_recv_get_active_header(rdp, s, &channelId, &length); + rdp_recv_demand_active(rdp, s, pduSource, length); + rdp_recv_confirm_active(rdp, s, pduLength); + } + { + rdpNla* nla = nla_new(rdp->context, rdp->transport); + nla_recv_pdu(nla, s); + nla_free(nla); + } + { + rdp_recv_heartbeat_packet(rdp, s); + rdp->state = CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE; + rdp_recv_client_info(rdp, s); + rdp_recv_save_session_info(rdp, s); + } + { + freerdp_is_valid_mcs_create_request(Data, Size); + freerdp_is_valid_mcs_create_response(Data, Size); + } + { + multitransport_recv_request(rdp->multitransport, s); + multitransport_recv_response(rdp->multitransport, s); + } + { + autodetect_recv_request_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s); + autodetect_recv_response_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s); + } + { + rdp_recv_deactivate_all(rdp, s); + rdp_recv_server_synchronize_pdu(rdp, s); + rdp_recv_client_synchronize_pdu(rdp, s); + } +fail: + freerdp_peer_context_free(client); + free(client); +} + +int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) +{ + test_server(Data, Size); + return 0; +} diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index cfc0abc..9e79863 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -2031,7 +2031,9 @@ static BOOL update_send_cache_brush(rdpContext* context, const CACHE_BRUSH_ORDER return FALSE; const size_t em = Stream_GetPosition(s); - WINPR_ASSERT(em > bm + 13); + if (em <= bm + 13) + return FALSE; + const size_t orderLength = (em - bm) - 13; WINPR_ASSERT(orderLength <= UINT16_MAX); Stream_SetPosition(s, bm); @@ -3299,6 +3301,9 @@ void update_free(rdpUpdate* update) MessageQueue_Free(up->queue); DeleteCriticalSection(&up->mux); + + if (up->us) + Stream_Free(up->us, TRUE); free(update); } } @@ -3328,7 +3333,9 @@ BOOL update_begin_paint(rdpUpdate* update) /* Reset the invalid regions, we start a new frame here. */ rdpGdi* gdi = update->context->gdi; - WINPR_ASSERT(gdi); + if (!gdi) + return FALSE; + if (gdi->hdc && gdi->primary && gdi->primary->hdc) { HGDI_WND hwnd = gdi->primary->hdc->hwnd; diff --git a/libfreerdp/crypto/privatekey.c b/libfreerdp/crypto/privatekey.c index 55379d4..9a6fb25 100644 --- a/libfreerdp/crypto/privatekey.c +++ b/libfreerdp/crypto/privatekey.c @@ -442,7 +442,7 @@ fail: return rc; } -char* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM param, size_t* plength) +BYTE* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM param, size_t* plength) { BYTE* buf = NULL; @@ -527,7 +527,7 @@ char* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM par fail: BN_free(bn); - return (char*)buf; + return buf; } WINPR_DIGEST_CTX* freerdp_key_digest_sign(rdpPrivateKey* key, WINPR_MD_TYPE digest) diff --git a/libfreerdp/crypto/privatekey.h b/libfreerdp/crypto/privatekey.h index 418abf5..b423c9a 100644 --- a/libfreerdp/crypto/privatekey.h +++ b/libfreerdp/crypto/privatekey.h @@ -52,7 +52,7 @@ extern "C" */ FREERDP_LOCAL EVP_PKEY* freerdp_key_get_evp_pkey(const rdpPrivateKey* key); - FREERDP_LOCAL char* freerdp_key_get_param(const rdpPrivateKey* key, + FREERDP_LOCAL BYTE* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM param, size_t* plength); FREERDP_LOCAL WINPR_DIGEST_CTX* freerdp_key_digest_sign(rdpPrivateKey* key, diff --git a/libfreerdp/emu/scard/smartcard_emulate.c b/libfreerdp/emu/scard/smartcard_emulate.c index d517bd6..6e21f17 100644 --- a/libfreerdp/emu/scard/smartcard_emulate.c +++ b/libfreerdp/emu/scard/smartcard_emulate.c @@ -38,8 +38,8 @@ #define MAX_CACHE_ITEM_SIZE 4096 #define MAX_CACHE_ITEM_VALUES 4096 -static const CHAR g_ReaderNameA[] = { 'F', 'r', 'e', 'e', 'R', 'D', 'P', ' ', 'E', - 'm', 'u', 'l', 'a', 't', 'o', 'r', '\0', '\0' }; +static CHAR g_ReaderNameA[] = { 'F', 'r', 'e', 'e', 'R', 'D', 'P', ' ', 'E', + 'm', 'u', 'l', 'a', 't', 'o', 'r', '\0', '\0' }; static INIT_ONCE g_ReaderNameWGuard = INIT_ONCE_STATIC_INIT; static WCHAR g_ReaderNameW[32] = { 0 }; static size_t g_ReaderNameWLen = 0; diff --git a/libfreerdp/gdi/test/TestGdiCreate.c b/libfreerdp/gdi/test/TestGdiCreate.c index c71b396..e6594ea 100644 --- a/libfreerdp/gdi/test/TestGdiCreate.c +++ b/libfreerdp/gdi/test/TestGdiCreate.c @@ -124,7 +124,7 @@ fail: if (hBitmap) gdi_DeleteObject((HGDIOBJECT)hBitmap); else - free(data); + winpr_aligned_free(data); return rc; } diff --git a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c index 318aec6..10a8754 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c @@ -76,7 +76,7 @@ static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height) if (c != sse) { - printf("optimized->YCoCgRToRGB FAIL[%s] [%" PRIu32 "]: 0x%08" PRIx32 + printf("optimized->YCoCgRToRGB FAIL[%s] [%" PRIuz "]: 0x%08" PRIx32 " -> C 0x%08" PRIx32 " vs optimized 0x%08" PRIx32 "\n", formatName, i, in[i + 1], c, sse); status = -1; diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c index 14c9014..717128c 100644 --- a/server/shadow/shadow.c +++ b/server/shadow/shadow.c @@ -54,7 +54,7 @@ int main(int argc, char** argv) "maximum connections allowed to server, 0 to deactivate" }, { "rect", COMMAND_LINE_VALUE_REQUIRED, "<x,y,w,h>", NULL, NULL, -1, NULL, "Select rectangle within monitor to share" }, - { "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, + { "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients must authenticate" }, { "remote-guard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Remote credential guard" }, diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index f06aaf7..9c8eced 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -137,7 +137,7 @@ endif() # Soname versioning set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)") -set(RAW_VERSION_STRING "3.5.0") +set(RAW_VERSION_STRING "3.5.1") if(EXISTS "${PROJECT_SOURCE_DIR}/.source_tag") file(READ ${PROJECT_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff --git a/winpr/libwinpr/clipboard/synthetic.c b/winpr/libwinpr/clipboard/synthetic.c index db8af71..cae5106 100644 --- a/winpr/libwinpr/clipboard/synthetic.c +++ b/winpr/libwinpr/clipboard/synthetic.c @@ -379,7 +379,7 @@ static void* clipboard_synthesize_image_format_to_bmp(wClipboard* clipboard, UIN WINPR_ASSERT(data); WINPR_ASSERT(pSize); - void* dst = NULL; + BYTE* dst = NULL; const UINT32 SrcSize = *pSize; size_t size = 0; wImage* image = winpr_image_new(); diff --git a/winpr/libwinpr/clipboard/synthetic_file.c b/winpr/libwinpr/clipboard/synthetic_file.c index 9a1084b..4290d2a 100644 --- a/winpr/libwinpr/clipboard/synthetic_file.c +++ b/winpr/libwinpr/clipboard/synthetic_file.c @@ -1105,8 +1105,8 @@ static UINT file_get_range(struct synthetic_file* file, UINT64 offset, UINT32 si if (!GetFileInformationByHandle(file->fd, &FileInfo)) { - file->fd = INVALID_HANDLE_VALUE; CloseHandle(file->fd); + file->fd = INVALID_HANDLE_VALUE; error = GetLastError(); WLog_ERR(TAG, "Get file [%s] information fail: 0x%08" PRIx32, file->local_name, error); return error; diff --git a/winpr/libwinpr/comm/comm.c b/winpr/libwinpr/comm/comm.c index cd68a40..f891ca7 100644 --- a/winpr/libwinpr/comm/comm.c +++ b/winpr/libwinpr/comm/comm.c @@ -1343,7 +1343,10 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare return (HANDLE)pComm; error_handle: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC CloseHandle(pComm); + WINPR_PRAGMA_DIAG_POP return INVALID_HANDLE_VALUE; } diff --git a/winpr/libwinpr/crt/test/TestUnicodeConversion.c b/winpr/libwinpr/crt/test/TestUnicodeConversion.c index 187a068..eb0acb7 100644 --- a/winpr/libwinpr/crt/test/TestUnicodeConversion.c +++ b/winpr/libwinpr/crt/test/TestUnicodeConversion.c @@ -15,9 +15,9 @@ typedef struct { - char* utf8; + const char* utf8; size_t utf8len; - WCHAR* utf16; + const WCHAR* utf16; size_t utf16len; } testcase_t; diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 9318586..e7bc0cf 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -925,7 +925,10 @@ static WIN32_FILE_SEARCH* file_search_new(const char* name, size_t namelen, cons return pFileSearch; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC FindClose(pFileSearch); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFile.c b/winpr/libwinpr/file/test/TestFileFindFirstFile.c index 04829a3..0e5de44 100644 --- a/winpr/libwinpr/file/test/TestFileFindFirstFile.c +++ b/winpr/libwinpr/file/test/TestFileFindFirstFile.c @@ -98,7 +98,8 @@ static BOOL find_first_file_success(const char* FilePath) } rc = TRUE; fail: - FindClose(hFind); + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); return rc; } diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c index 3cf7786..cba8038 100644 --- a/winpr/libwinpr/sspi/Kerberos/kerberos.c +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c @@ -1496,7 +1496,7 @@ static SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext, KRB_CONTEXT* context = get_context(phContext); PSecBuffer sig_buffer = NULL; PSecBuffer data_buffer = NULL; - BYTE* header = NULL; + char* header = NULL; BYTE flags = 0; krb5glue_key key = NULL; krb5_keyusage usage = 0; @@ -1547,15 +1547,15 @@ static SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext, /* Set up the iov array in sig_buffer */ header = sig_buffer->pvBuffer; encrypt_iov[2].data.data = header + 16; - encrypt_iov[3].data.data = (BYTE*)encrypt_iov[2].data.data + encrypt_iov[2].data.length; - encrypt_iov[4].data.data = (BYTE*)encrypt_iov[3].data.data + encrypt_iov[3].data.length; - encrypt_iov[0].data.data = (BYTE*)encrypt_iov[4].data.data + encrypt_iov[4].data.length; + encrypt_iov[3].data.data = encrypt_iov[2].data.data + encrypt_iov[2].data.length; + encrypt_iov[4].data.data = encrypt_iov[3].data.data + encrypt_iov[3].data.length; + encrypt_iov[0].data.data = encrypt_iov[4].data.data + encrypt_iov[4].data.length; encrypt_iov[1].data.data = data_buffer->pvBuffer; /* Write the GSS header with 0 in RRC */ Data_Write_UINT16_BE(header, TOK_ID_WRAP); header[2] = flags; - header[3] = 0xFF; + header[3] = (char)0xFF; Data_Write_UINT32(header + 4, 0); Data_Write_UINT64_BE(header + 8, (context->local_seq + MessageSeqNo)); @@ -1656,8 +1656,8 @@ static SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(PCtxtHandle phContext, iov[0].data.data = header + 16 + rrc + ec; iov[1].data.data = data_buffer->pvBuffer; iov[2].data.data = header + 16 + ec; - iov[3].data.data = (BYTE*)iov[2].data.data + iov[2].data.length; - iov[4].data.data = (BYTE*)iov[3].data.data + iov[3].data.length; + iov[3].data.data = iov[2].data.data + iov[2].data.length; + iov[4].data.data = iov[3].data.data + iov[3].data.length; if (krb_log_exec(krb5glue_decrypt_iov, context->ctx, key, usage, iov, ARRAYSIZE(iov))) return SEC_E_INTERNAL_ERROR; diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 6ca3e54..a727d67 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -23,6 +23,7 @@ #include <winpr/wtypes.h> #include <winpr/timezone.h> #include <winpr/crt.h> +#include <winpr/assert.h> #include <winpr/file.h> #include "../log.h" @@ -308,6 +309,11 @@ static TIME_ZONE_ENTRY* winpr_detect_windows_time_zone(void) free(tzid); tzid = NULL; } + else if (tzid[0] == ':') + { + /* Remove leading colon, see tzset(3) */ + memmove(tzid, tzid + 1, nSize - sizeof(char)); + } } if (tzid == NULL) @@ -323,7 +329,14 @@ static TIME_ZONE_ENTRY* winpr_detect_windows_time_zone(void) char buf[1024] = { 0 }; const char* links[] = { buf }; - snprintf(buf, ARRAYSIZE(buf), "%s%s", zipath, tzid); + if (tzid[0] == '/') + { + /* Full path given in TZ */ + links[0] = tzid; + } + else + snprintf(buf, ARRAYSIZE(buf), "%s%s", zipath, tzid); + ntzid = winpr_get_timezone_from_link(links, 1); if (ntzid != NULL) { @@ -390,17 +403,20 @@ winpr_get_current_time_zone_rule(const TIME_ZONE_RULE_ENTRY* rules, UINT32 count DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { time_t t = 0; - struct tm tres; - struct tm* local_time = NULL; + struct tm tres = { 0 }; TIME_ZONE_ENTRY* dtz = NULL; + const TIME_ZONE_INFORMATION empty = { 0 }; LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; - lpTimeZoneInformation->StandardBias = 0; - time(&t); - local_time = localtime_r(&t, &tres); + + WINPR_ASSERT(tz); + + *tz = empty; + + t = time(NULL); + struct tm* local_time = localtime_r(&t, &tres); if (!local_time) goto out_error; - memset(tz, 0, sizeof(TIME_ZONE_INFORMATION)); #ifdef WINPR_HAVE_TM_GMTOFF { long bias = -(local_time->tm_gmtoff / 60L); @@ -410,19 +426,14 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) tz->Bias = (LONG)bias; } -#else - tz->Bias = 0; #endif dtz = winpr_detect_windows_time_zone(); if (dtz != NULL) { - const TIME_ZONE_INFORMATION empty = { 0 }; - WLog_DBG(TAG, "tz: Bias=%" PRId32 " sn='%s' dln='%s'", dtz->Bias, dtz->StandardName, dtz->DaylightName); - *tz = empty; tz->Bias = dtz->Bias; if (ConvertUtf8ToWChar(dtz->StandardName, tz->StandardName, ARRAYSIZE(tz->StandardName)) < @@ -462,8 +473,9 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) WLog_DBG(TAG, "tz not found, using computed bias %" PRId32 ".", tz->Bias); out_error: free(dtz); - memcpy(tz->StandardName, L"Client Local Time", sizeof(tz->StandardName)); - memcpy(tz->DaylightName, L"Client Local Time", sizeof(tz->DaylightName)); + if (ConvertUtf8ToWChar("Client Local Time", tz->StandardName, ARRAYSIZE(tz->StandardName)) <= 0) + WLog_WARN(TAG, "Failed to set default timezone name"); + memcpy(tz->DaylightName, tz->StandardName, sizeof(tz->DaylightName)); return 0; /* TIME_ZONE_ID_UNKNOWN */ } diff --git a/winpr/libwinpr/utils/debug.c b/winpr/libwinpr/utils/debug.c index a7c9a13..42d916e 100644 --- a/winpr/libwinpr/utils/debug.c +++ b/winpr/libwinpr/utils/debug.c @@ -161,7 +161,7 @@ char** winpr_backtrace_symbols(void* buffer, size_t* used) *msgptr = msg; strncpy(msg, support_msg, len); *used = 1; - return ppmsg; + return msgptr; #endif } diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index cc2e2ad..c609825 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -52,12 +52,12 @@ #include "../log.h" #define TAG WINPR_TAG("utils.image") -static SSIZE_T winpr_convert_from_jpeg(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data); -static SSIZE_T winpr_convert_from_png(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data); -static SSIZE_T winpr_convert_from_webp(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data); +static SSIZE_T winpr_convert_from_jpeg(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data); +static SSIZE_T winpr_convert_from_png(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data); +static SSIZE_T winpr_convert_from_webp(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data); static BOOL writeBitmapFileHeader(wStream* s, const WINPR_BITMAP_FILE_HEADER* bf) { @@ -484,7 +484,7 @@ int winpr_image_read(wImage* image, const char* filename) if (pos > 0) { - char* buffer = malloc((size_t)pos); + BYTE* buffer = malloc((size_t)pos); if (buffer) { size_t r = fread(buffer, 1, (size_t)pos, fp); @@ -518,9 +518,8 @@ int winpr_image_read_buffer(wImage* image, const BYTE* buffer, size_t size) (sig[8] == 'W') && (sig[9] == 'E') && (sig[10] == 'B') && (sig[11] == 'P')) { image->type = WINPR_IMAGE_WEBP; - const SSIZE_T rc = - winpr_convert_from_webp((const char*)buffer, size, &image->width, &image->height, - &image->bitsPerPixel, ((char**)&image->data)); + const SSIZE_T rc = winpr_convert_from_webp(buffer, size, &image->width, &image->height, + &image->bitsPerPixel, &image->data); if (rc >= 0) { image->bytesPerPixel = (image->bitsPerPixel + 7) / 8; @@ -533,9 +532,8 @@ int winpr_image_read_buffer(wImage* image, const BYTE* buffer, size_t size) (sig[10] == 0x00)) { image->type = WINPR_IMAGE_JPEG; - const SSIZE_T rc = - winpr_convert_from_jpeg((const char*)buffer, size, &image->width, &image->height, - &image->bitsPerPixel, ((char**)&image->data)); + const SSIZE_T rc = winpr_convert_from_jpeg(buffer, size, &image->width, &image->height, + &image->bitsPerPixel, &image->data); if (rc >= 0) { image->bytesPerPixel = (image->bitsPerPixel + 7) / 8; @@ -547,9 +545,8 @@ int winpr_image_read_buffer(wImage* image, const BYTE* buffer, size_t size) (sig[4] == '\r') && (sig[5] == '\n') && (sig[6] == 0x1A) && (sig[7] == '\n')) { image->type = WINPR_IMAGE_PNG; - const SSIZE_T rc = - winpr_convert_from_png((const char*)buffer, size, &image->width, &image->height, - &image->bitsPerPixel, ((char**)&image->data)); + const SSIZE_T rc = winpr_convert_from_png(buffer, size, &image->width, &image->height, + &image->bitsPerPixel, &image->data); if (rc >= 0) { image->bytesPerPixel = (image->bitsPerPixel + 7) / 8; @@ -625,11 +622,11 @@ void* winpr_convert_to_jpeg(const void* data, size_t size, UINT32 width, UINT32 jpeg_start_compress(&cinfo, TRUE); - const unsigned char* cdata = data; + const JSAMPLE* cdata = data; for (size_t x = 0; x < height; x++) { const JDIMENSION offset = x * stride; - const JSAMPROW coffset = &cdata[offset]; + const JSAMPLE* coffset = &cdata[offset]; if (jpeg_write_scanlines(&cinfo, &coffset, 1) != 1) goto fail; } @@ -643,8 +640,8 @@ fail: #endif } -SSIZE_T winpr_convert_from_jpeg(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data) +SSIZE_T winpr_convert_from_jpeg(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data) { WINPR_ASSERT(comp_data || (comp_data_bytes == 0)); WINPR_ASSERT(width); @@ -658,7 +655,7 @@ SSIZE_T winpr_convert_from_jpeg(const char* comp_data, size_t comp_data_bytes, U struct jpeg_decompress_struct cinfo = { 0 }; struct jpeg_error_mgr jerr; SSIZE_T size = -1; - char* decomp_data = NULL; + BYTE* decomp_data = NULL; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); @@ -734,8 +731,8 @@ void* winpr_convert_to_webp(const void* data, size_t size, UINT32 width, UINT32 #endif } -SSIZE_T winpr_convert_from_webp(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data) +SSIZE_T winpr_convert_from_webp(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data) { WINPR_ASSERT(comp_data || (comp_data_bytes == 0)); WINPR_ASSERT(width); @@ -751,13 +748,20 @@ SSIZE_T winpr_convert_from_webp(const char* comp_data, size_t comp_data_bytes, U return -1; #else - uint8_t* dst = WebPDecodeBGRA(comp_data, comp_data_bytes, width, height); - if (!dst) + int w = 0; + int h = 0; + uint8_t* dst = WebPDecodeBGRA(comp_data, comp_data_bytes, &w, &h); + if (!dst || (w < 0) || (h < 0)) + { + free(dst); return -1; + } + *width = w; + *height = h; *bpp = 32; *ppdecomp_data = dst; - return (*width) * (*height) * 4; + return 4ll * w * h; #endif } @@ -1006,8 +1010,8 @@ void* winpr_convert_to_png(const void* data, size_t size, UINT32 width, UINT32 h #endif } -SSIZE_T winpr_convert_from_png(const char* comp_data, size_t comp_data_bytes, UINT32* width, - UINT32* height, UINT32* bpp, char** ppdecomp_data) +SSIZE_T winpr_convert_from_png(const BYTE* comp_data, size_t comp_data_bytes, UINT32* width, + UINT32* height, UINT32* bpp, BYTE** ppdecomp_data) { #if defined(WINPR_UTILS_IMAGE_PNG) size_t len = 0; diff --git a/winpr/libwinpr/utils/test/TestStream.c b/winpr/libwinpr/utils/test/TestStream.c index 00130ae..f86996e 100644 --- a/winpr/libwinpr/utils/test/TestStream.c +++ b/winpr/libwinpr/utils/test/TestStream.c @@ -124,7 +124,13 @@ static BOOL TestStream_Static(void) if (v != 2) return FALSE; + // Intentional warning as the stream is not allocated. + // Still, Stream_Free should not release such memory, therefore this statement + // is required to test that. + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC Stream_Free(s, TRUE); + WINPR_PRAGMA_DIAG_POP return TRUE; } |