mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-07-14 03:05:11 +03:00
fix copilot review
This commit is contained in:
@@ -285,9 +285,12 @@ struct wf_clipboard
|
|||||||
char *req_fdata;
|
char *req_fdata;
|
||||||
HANDLE req_fevent;
|
HANDLE req_fevent;
|
||||||
BOOL req_f_received;
|
BOOL req_f_received;
|
||||||
// The req_f* fields below are a single-slot rendezvous for ONE outstanding
|
// The req_f* fields below are a single-slot rendezvous that ASSUMES one outstanding
|
||||||
// file-contents request at a time (the request/response handshake is serialized
|
// file-contents request at a time. That is an unenforced usage invariant, not a
|
||||||
// by req_fevent). They are not a general multi-request queue.
|
// guarantee: req_fevent only signals response completion, it does NOT provide mutual
|
||||||
|
// exclusion between concurrent callers, so concurrent IStream reads would clobber
|
||||||
|
// these fields. req_f_mutex below only makes the buffer hand-off memory-safe; it does
|
||||||
|
// not serialize whole requests. They are not a general multi-request queue.
|
||||||
//
|
//
|
||||||
// Number of bytes asked for by the most recent file-contents request; set before
|
// Number of bytes asked for by the most recent file-contents request; set before
|
||||||
// the request is sent and read when its response arrives, so no lock is needed for
|
// the request is sent and read when its response arrives, so no lock is needed for
|
||||||
@@ -417,12 +420,17 @@ static ULONG STDMETHODCALLTYPE CliprdrStream_Release(IStream *This)
|
|||||||
// it. Held only across these few field assignments, never across a blocking wait.
|
// it. Held only across these few field assignments, never across a blocking wait.
|
||||||
static void take_req_fdata(wfClipboard *clipboard, char **data, ULONG *size)
|
static void take_req_fdata(wfClipboard *clipboard, char **data, ULONG *size)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(clipboard->req_f_mutex, INFINITE);
|
DWORD wait = WaitForSingleObject(clipboard->req_f_mutex, INFINITE);
|
||||||
*data = clipboard->req_fdata;
|
*data = clipboard->req_fdata;
|
||||||
*size = clipboard->req_fsize;
|
*size = clipboard->req_fsize;
|
||||||
clipboard->req_fdata = NULL;
|
clipboard->req_fdata = NULL;
|
||||||
clipboard->req_fsize = 0;
|
clipboard->req_fsize = 0;
|
||||||
ReleaseMutex(clipboard->req_f_mutex);
|
// WAIT_OBJECT_0 and WAIT_ABANDONED both mean the mutex is held; release only then.
|
||||||
|
// On WAIT_FAILED (e.g. the handle was closed during teardown) we do not own it, so
|
||||||
|
// calling ReleaseMutex would be undefined; the field access above then degrades to
|
||||||
|
// unsynchronized best effort, which is the pre-existing teardown behavior.
|
||||||
|
if (wait == WAIT_OBJECT_0 || wait == WAIT_ABANDONED)
|
||||||
|
ReleaseMutex(clipboard->req_f_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream *This, void *pv, ULONG cb,
|
static HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream *This, void *pv, ULONG cb,
|
||||||
@@ -3356,8 +3364,10 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
|||||||
// (CliprdrStream_Read / _New) via req_f_mutex. Held only across the buffer
|
// (CliprdrStream_Read / _New) via req_f_mutex. Held only across the buffer
|
||||||
// manipulation below (never across a blocking wait), and released exactly once
|
// manipulation below (never across a blocking wait), and released exactly once
|
||||||
// after the loop, so no `break` path can leak the lock or deadlock.
|
// after the loop, so no `break` path can leak the lock or deadlock.
|
||||||
WaitForSingleObject(clipboard->req_f_mutex, INFINITE);
|
// WAIT_OBJECT_0 / WAIT_ABANDONED both mean we hold the mutex; WAIT_FAILED (e.g. a
|
||||||
locked = TRUE;
|
// handle closed during teardown) means we do not, so we must not release it.
|
||||||
|
DWORD wait = WaitForSingleObject(clipboard->req_f_mutex, INFINITE);
|
||||||
|
locked = (wait == WAIT_OBJECT_0 || wait == WAIT_ABANDONED);
|
||||||
|
|
||||||
// Free any buffer left over from a prior request that was never consumed
|
// Free any buffer left over from a prior request that was never consumed
|
||||||
// (e.g. a response that arrived after its reader timed out). Safe under the
|
// (e.g. a response that arrived after its reader timed out). Safe under the
|
||||||
@@ -3549,7 +3559,18 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
CloseHandle(clipboard->req_fevent);
|
CloseHandle(clipboard->req_fevent);
|
||||||
|
|
||||||
if (clipboard->req_f_mutex)
|
if (clipboard->req_f_mutex)
|
||||||
|
{
|
||||||
|
// Free any file-contents buffer a response published that no consumer ever took
|
||||||
|
// (e.g. one that arrived during shutdown), so it is not leaked. Reclaim it under
|
||||||
|
// req_f_mutex (still valid here) to stay memory-safe against a late response,
|
||||||
|
// then close the handle.
|
||||||
|
char *leftover = NULL;
|
||||||
|
ULONG leftover_sz = 0;
|
||||||
|
take_req_fdata(clipboard, &leftover, &leftover_sz);
|
||||||
|
free(leftover);
|
||||||
|
|
||||||
CloseHandle(clipboard->req_f_mutex);
|
CloseHandle(clipboard->req_f_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
clear_file_array(clipboard);
|
clear_file_array(clipboard);
|
||||||
clear_format_map(clipboard);
|
clear_format_map(clipboard);
|
||||||
|
|||||||
Reference in New Issue
Block a user