Skip to content

X11Clipboard is a data race and should not be Sync #548

Open
@meithecatte

Description

@meithecatte

claim_clipboard_ownership, as well as respond_to_clipboard_request perform unsynchronized accesses on mutable statics:

// Next message for clipboard request
static mut MESSAGE: Option<String> = None;
/// Claim that our app is X11 clipboard owner
/// Now when some other linux app will ask X11 for clipboard content - it will be redirected to our app
unsafe fn claim_clipboard_ownership(
libx11: &mut LibX11,
display: *mut Display,
window: Window,
message: String,
) {
(libx11.XSetSelectionOwner)(
display,
libx11.extensions.clipboard,
window,
CurrentTime as Time,
);
MESSAGE = Some(message);
}

This means that X11Clipboard::set is not threadsafe:

impl crate::native::Clipboard for X11Clipboard {
fn get(&mut self) -> Option<String> {
let utf8_string = self.libx11.extensions.utf8_string;
let bytes =
unsafe { get_clipboard(&mut self.libx11, self.display, self.window, utf8_string)? };
Some(std::str::from_utf8(&bytes).ok()?.to_string())
}
fn set(&mut self, data: &str) {
unsafe {
claim_clipboard_ownership(&mut self.libx11, self.display, self.window, data.to_owned());
};
}
}

Nevertheless, X11Clipboard explicitly implements Send and Sync:

unsafe impl Send for X11Clipboard {}
unsafe impl Sync for X11Clipboard {}

Moreover, removing the Sync impl would not be enough – creating two separate X11Clipboard instances can cause UB even without this impl.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions