From 46f1d141c1596ac4079beefffaaa46f9453b9bdd Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 28 Feb 2023 11:37:42 +0100 Subject: [PATCH] [client,common] fixed winpr clipboard locking --- client/Wayland/wlf_cliprdr.c | 29 ++++++++++------- client/X11/xf_cliprdr.c | 49 +++++++++++++++++++---------- client/common/client_cliprdr_file.c | 33 ++++++++++++++++--- 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/client/Wayland/wlf_cliprdr.c b/client/Wayland/wlf_cliprdr.c index 788a294f5..51b3407c7 100644 --- a/client/Wayland/wlf_cliprdr.c +++ b/client/Wayland/wlf_cliprdr.c @@ -778,15 +778,17 @@ wlf_cliprdr_server_format_data_request(CliprdrClientContext* context, goto fail; } + ClipboardLock(clipboard->system); const BOOL res = ClipboardSetData(clipboard->system, localFormatId, data, size); free(data); - data = NULL; - if (!res) - goto fail; UINT32 len = 0; - data = ClipboardGetData(clipboard->system, formatId, &len); - if (!data) + data = NULL; + if (res) + data = ClipboardGetData(clipboard->system, formatId, &len); + + ClipboardUnlock(clipboard->system); + if (!res || !data) goto fail; if (fileFormatId == formatId) @@ -867,9 +869,9 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context, ClipboardGetFormatId(clipboard->system, type_FileGroupDescriptorW); dstFormatId = ClipboardGetFormatId(clipboard->system, request->responseMime); - if (!cliprdr_file_context_update_base(clipboard->file, clipboard->system)) + if (!cliprdr_file_context_update_server_data(clipboard->file, data, size)) goto unlock; - else if (!cliprdr_file_context_update_server_data(clipboard->file, data, size)) + else if (!cliprdr_file_context_update_base(clipboard->file, clipboard->system)) goto unlock; } else if (strcmp(type_HtmlFormat, name) == 0) @@ -882,12 +884,15 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context, break; } - if (!ClipboardSetData(clipboard->system, srcFormatId, data, size)) - goto unlock; - + ClipboardLock(clipboard->system); UINT32 len = 0; - data = ClipboardGetData(clipboard->system, dstFormatId, &len); - if (!data) + + const BOOL sres = ClipboardSetData(clipboard->system, srcFormatId, data, size); + if (sres) + data = ClipboardGetData(clipboard->system, dstFormatId, &len); + ClipboardUnlock(clipboard->system); + + if (!sres || !data) goto unlock; if (request->responseFile) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index d69fb42eb..f0fa41909 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -834,6 +834,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa return; } + ClipboardLock(clipboard->system); SrcSize = (UINT32)size; bSuccess = ClipboardSetData(clipboard->system, srcFormatId, data, SrcSize); @@ -842,6 +843,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa DstSize = 0; pDstData = (BYTE*)ClipboardGetData(clipboard->system, format->formatToRequest, &DstSize); } + ClipboardUnlock(clipboard->system); if (!pDstData) { @@ -874,7 +876,9 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa UINT32 formatId = ClipboardGetFormatId(clipboard->system, mime_uri_list); UINT32 url_size = 0; + ClipboardLock(clipboard->system); char* url = ClipboardGetData(clipboard->system, formatId, &url_size); + ClipboardUnlock(clipboard->system); cliprdr_file_context_update_client_data(clipboard->file, url, url_size); free(url); @@ -1257,7 +1261,10 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, /* Cached converted clipboard data available. Send it now */ respond->property = xevent->property; + ClipboardLock(clipboard->system); void* data = ClipboardGetData(clipboard->system, cformat->localFormat, &DstSize); + ClipboardUnlock(clipboard->system); + xf_cliprdr_provide_data(clipboard, respond, data, DstSize); free(data); } @@ -1881,11 +1888,11 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, if (strcmp(clipboard->requestedFormat->formatName, type_FileGroupDescriptorW) == 0) { - if (!cliprdr_file_context_update_base(clipboard->file, clipboard->system)) + if (!cliprdr_file_context_update_server_data(clipboard->file, data, size)) + WLog_WARN(TAG, "failed to update file descriptors"); + else if (!cliprdr_file_context_update_base(clipboard->file, clipboard->system)) { } - else if (!cliprdr_file_context_update_server_data(clipboard->file, data, size)) - WLog_WARN(TAG, "failed to update file descriptors"); srcFormatId = ClipboardGetFormatId(clipboard->system, type_FileGroupDescriptorW); const xfCliprdrFormat* dstTargetFormat = @@ -1933,8 +1940,11 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, format->formatToRequest, ClipboardGetFormatIdString(format->formatToRequest), format->localFormat, format->formatName); SrcSize = (UINT32)size; + + ClipboardLock(clipboard->system); bSuccess = ClipboardSetData(clipboard->system, srcFormatId, data, SrcSize); + BOOL willQuit = FALSE; if (bSuccess) { if (SrcSize == 0) @@ -1942,25 +1952,30 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, WLog_DBG(TAG, "skipping, empty data detected!"); free(clipboard->respond); clipboard->respond = NULL; - return CHANNEL_RC_OK; + willQuit = TRUE; } - - pDstData = (BYTE*)ClipboardGetData(clipboard->system, dstFormatId, &DstSize); - - if (!pDstData) + else { - WLog_WARN(TAG, "failed to get clipboard data in format %s [source format %s]", - ClipboardGetFormatName(clipboard->system, dstFormatId), - ClipboardGetFormatName(clipboard->system, srcFormatId)); - } + pDstData = (BYTE*)ClipboardGetData(clipboard->system, dstFormatId, &DstSize); - if (nullTerminated && pDstData) - { - BYTE* nullTerminator = memchr(pDstData, '\0', DstSize); - if (nullTerminator) - DstSize = nullTerminator - pDstData; + if (!pDstData) + { + WLog_WARN(TAG, "failed to get clipboard data in format %s [source format %s]", + ClipboardGetFormatName(clipboard->system, dstFormatId), + ClipboardGetFormatName(clipboard->system, srcFormatId)); + } + + if (nullTerminated && pDstData) + { + BYTE* nullTerminator = memchr(pDstData, '\0', DstSize); + if (nullTerminator) + DstSize = nullTerminator - pDstData; + } } } + ClipboardUnlock(clipboard->system); + if (willQuit) + return CHANNEL_RC_OK; /* Cache converted and original data to avoid doing a possibly costly * conversion again on subsequent requests */ diff --git a/client/common/client_cliprdr_file.c b/client/common/client_cliprdr_file.c index 5aa1fcb26..191785754 100644 --- a/client/common/client_cliprdr_file.c +++ b/client/common/client_cliprdr_file.c @@ -147,6 +147,7 @@ struct cliprdr_file_context CliprdrClientContext* context; char* path; char* current_path; + char* exposed_path; BYTE server_data_hash[WINPR_SHA256_DIGEST_LENGTH]; BYTE client_data_hash[WINPR_SHA256_DIGEST_LENGTH]; }; @@ -922,6 +923,8 @@ struct stream_node_arg CliprdrFuseInode* root; }; +static BOOL update_sub_path(CliprdrFileContext* file, UINT32 lockID); + static BOOL add_stream_node(const void* key, void* value, void* arg) { const CliprdrFuseStreamLock* stream = value; @@ -933,6 +936,12 @@ static BOOL add_stream_node(const void* key, void* value, void* arg) char name[10] = { 0 }; _snprintf(name, sizeof(name), "%08" PRIx32, stream->lockId); + if ((cliprdr_file_context_current_flags(stream->context) & CB_CAN_LOCK_CLIPDATA) == 0) + { + if (!update_sub_path(stream->context, stream->lockId)) + return FALSE; + } + const size_t idx = ArrayList_Count(node_arg->list); CliprdrFuseInode* node = cliprdr_file_fuse_node_new( stream->lockId, idx, FUSE_ROOT_ID + 1 + stream->lockId, FUSE_ROOT_ID, name, S_IFDIR | 0700); @@ -1583,9 +1592,12 @@ static BOOL update_sub_path(CliprdrFileContext* file, UINT32 lockID) char lockstr[32] = { 0 }; _snprintf(lockstr, sizeof(lockstr), "%08" PRIx32, lockID); + HashTable_Lock(file->remote_streams); free(file->current_path); file->current_path = GetCombinedPath(file->path, lockstr); - return file->current_path != NULL; + const BOOL res = file->current_path != NULL; + HashTable_Unlock(file->remote_streams); + return res; } static UINT change_lock(CliprdrFileContext* file, UINT32 lockId, BOOL lock) @@ -1823,6 +1835,7 @@ void cliprdr_file_context_free(CliprdrFileContext* file) winpr_RemoveDirectory(file->path); free(file->path); free(file->current_path); + free(file->exposed_path); free(file); } @@ -2092,8 +2105,6 @@ CliprdrFileContext* cliprdr_file_context_new(void* context) file->log = WLog_Get(CLIENT_TAG("common.cliprdr.file")); file->clipboard = context; - if (!create_base_path(file)) - goto fail; file->local_streams = HashTable_New(FALSE); if (!file->local_streams) @@ -2150,7 +2161,12 @@ CliprdrFileContext* cliprdr_file_context_new(void* context) } obj = ArrayList_Object(file->ino_list); obj->fnObjectFree = cliprdr_file_fuse_node_free; +#endif + if (!create_base_path(file)) + goto fail; + +#if defined(WITH_FUSE2) || defined(WITH_FUSE3) if (!cliprdr_fuse_repopulate(file, file->ino_list)) goto fail; @@ -2275,8 +2291,15 @@ BOOL cliprdr_file_context_update_base(CliprdrFileContext* file, wClipboard* clip wClipboardDelegate* delegate = ClipboardGetDelegate(clip); if (!delegate) return FALSE; - delegate->basePath = file->current_path; - return TRUE; + ClipboardLock(clip); + HashTable_Lock(file->remote_streams); + free(file->exposed_path); + file->exposed_path = _strdup(file->current_path); + HashTable_Unlock(file->remote_streams); + + delegate->basePath = (file->exposed_path); + ClipboardUnlock(clip); + return delegate->basePath != NULL; } BOOL cliprdr_file_context_has_local_support(CliprdrFileContext* file)