From 33f59beebbe7a99fc7b0677faae487ef95aad82b Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 16 Sep 2026 13:02:04 +0800 Subject: [PATCH] clipboard: fail a size request for an entry that has no size The descriptor now carries FD_FILESIZE only when the size was actually read, which leaves both size fields at zero for an entry where it was not. The non-stream FILECONTENTS_SIZE handler passed those fields straight back, so a receiver asking about such an entry would be told it is empty and would write a zero-length file without any error. The previous code returned whatever GetFileSize() had left behind, which for a failure is INVALID_FILE_SIZE -- also wrong, but wrong loudly. Answer only when the descriptor has a size, and fail the request otherwise. The receiver then fails the paste instead of completing it with an empty file, which is the same class of outcome the old code produced for that entry. The IStream_Stat path is unchanged; it already answers from the stream. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab --- libs/clipboard/src/windows/wf_cliprdr.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index 3baf83a1d..e85fb5079 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -3539,15 +3539,24 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context, { if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE) { + FILEDESCRIPTORW *fd; + if (clipboard->nFiles <= fileContentsRequest->listIndex) { rc = ERROR_INTERNAL_ERROR; goto exit; } - *((UINT32 *)&pData[0]) = - clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeLow; - *((UINT32 *)&pData[4]) = - clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeHigh; + + fd = clipboard->fileDescriptor[fileContentsRequest->listIndex]; + // The size fields only mean anything when FD_FILESIZE says so. Answering with + // them regardless would describe an entry whose size could not be read as empty. + if ((fd->dwFlags & FD_FILESIZE) == 0) + { + rc = ERROR_INTERNAL_ERROR; + goto exit; + } + *((UINT32 *)&pData[0]) = fd->nFileSizeLow; + *((UINT32 *)&pData[4]) = fd->nFileSizeHigh; uSize = cbRequested; } else if (fileContentsRequest->dwFlags == FILECONTENTS_RANGE)