Merge pull request #13 from kchibisov/reader-crash

Fix crash when receiving non-utf8 data
This commit is contained in:
Victor Berger 2020-03-08 22:18:53 +01:00 committed by GitHub
commit b97ebc4321
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 21 deletions

View file

@ -2,6 +2,9 @@
## Unreleased ## Unreleased
- Fix crash when receiving non-utf8 data
- **Breaking** `load` and `load_primary` now return `Result<String>` to indicate errors
## 0.3.7 -- 2020-02-27 ## 0.3.7 -- 2020-02-27
- Only bind seat with version up to 6, as version 7 is not yet supported by SCTK - Only bind seat with version up to 6, as version 7 is not yet supported by SCTK

View file

@ -37,7 +37,7 @@ fn main() {
} = event } = event
{ {
if text == " " { if text == " " {
*cb_contents_clone.lock().unwrap() = dbg!(clipboard.load(None)); *cb_contents_clone.lock().unwrap() = dbg!(clipboard.load(None).unwrap());
need_redraw_clone.store(true, atomic::Ordering::Relaxed) need_redraw_clone.store(true, atomic::Ordering::Relaxed)
} else if text == "s" { } else if text == "s" {
clipboard.store( clipboard.store(

View file

@ -1,5 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Read, Write}; use std::io::{Read, Result, Write};
use std::ops::Deref; use std::ops::Deref;
use std::os::unix::io::FromRawFd; use std::os::unix::io::FromRawFd;
use std::sync::mpsc; use std::sync::mpsc;
@ -50,7 +50,7 @@ type SeatMap = HashMap<
/// Object representing the Wayland clipboard /// Object representing the Wayland clipboard
pub struct ThreadedClipboard { pub struct ThreadedClipboard {
request_send: mpsc::Sender<ThreadRequest>, request_send: mpsc::Sender<ThreadRequest>,
load_recv: mpsc::Receiver<String>, load_recv: mpsc::Receiver<Result<String>>,
} }
// Kill thread when clipboard object is dropped // Kill thread when clipboard object is dropped
@ -113,7 +113,7 @@ impl ThreadedClipboard {
/// focus to work. Otherwise if no seat name is provided /// focus to work. Otherwise if no seat name is provided
/// the name of the seat to last generate a key or pointer event /// the name of the seat to last generate a key or pointer event
/// is used /// is used
pub fn load(&mut self, seat_name: Option<String>) -> String { pub fn load(&mut self, seat_name: Option<String>) -> Result<String> {
self.request_send self.request_send
.send(ThreadRequest::Load(seat_name)) .send(ThreadRequest::Load(seat_name))
.unwrap(); .unwrap();
@ -141,7 +141,7 @@ impl ThreadedClipboard {
/// focus to work. Otherwise if no seat name is provided /// focus to work. Otherwise if no seat name is provided
/// the name of the seat to last generate a key or pointer event /// the name of the seat to last generate a key or pointer event
/// is used /// is used
pub fn load_primary(&mut self, seat_name: Option<String>) -> String { pub fn load_primary(&mut self, seat_name: Option<String>) -> Result<String> {
self.request_send self.request_send
.send(ThreadRequest::LoadPrimary(seat_name)) .send(ThreadRequest::LoadPrimary(seat_name))
.unwrap(); .unwrap();
@ -180,7 +180,7 @@ fn clipboard_thread(
display: &WlDisplay, display: &WlDisplay,
event_queue: &mut EventQueue, event_queue: &mut EventQueue,
request_recv: mpsc::Receiver<ThreadRequest>, request_recv: mpsc::Receiver<ThreadRequest>,
load_send: mpsc::Sender<String>, load_send: mpsc::Sender<Result<String>>,
) { ) {
// Create a seat map to register seats // Create a seat map to register seats
let seat_map = Arc::new(Mutex::new(SeatMap::new())); let seat_map = Arc::new(Mutex::new(SeatMap::new()));
@ -296,7 +296,7 @@ fn clipboard_thread(
// Get the clipboard contents of the requested seat from the seat map // Get the clipboard contents of the requested seat from the seat map
let contents = seat_map let contents = seat_map
.get(&seat_name.unwrap_or_else(|| last_seat_name.lock().unwrap().clone())) .get(&seat_name.unwrap_or_else(|| last_seat_name.lock().unwrap().clone()))
.map_or(String::new(), |seat| { .map_or(Ok(String::new()), |seat| {
let mut reader = None; let mut reader = None;
seat.0.lock().unwrap().with_selection(|offer| { seat.0.lock().unwrap().with_selection(|offer| {
if let Some(offer) = offer { if let Some(offer) = offer {
@ -312,15 +312,18 @@ fn clipboard_thread(
} }
}); });
event_queue.sync_roundtrip().unwrap(); event_queue.sync_roundtrip().unwrap();
reader.map_or(String::new(), |mut reader| { reader.map_or(Ok(String::new()), |mut reader| {
let mut contents = String::new(); let mut contents = String::new();
reader.read_to_string(&mut contents).unwrap(); if let Err(err) = reader.read_to_string(&mut contents) {
contents Err(err)
} else {
Ok(contents)
}
}) })
}); });
// Normalization should happen only on `text/plain;charset=utf-8`, in case we // Normalization should happen only on `text/plain;charset=utf-8`, in case we
// add other mime types consult gtk for normalization. // add other mime types consult gtk for normalization.
let contents = normilize_to_lf(contents); let contents = contents.and_then(|contents| Ok(normilize_to_lf(contents)));
load_send.send(contents).unwrap(); load_send.send(contents).unwrap();
} }
// Store text in the clipboard // Store text in the clipboard
@ -361,9 +364,9 @@ fn clipboard_thread(
&seat_name &seat_name
.unwrap_or_else(|| last_seat_name.lock().unwrap().clone()), .unwrap_or_else(|| last_seat_name.lock().unwrap().clone()),
) )
.map_or(String::new(), |seat| { .map_or(Ok(String::new()), |seat| {
seat.3.lock().unwrap().as_ref().map_or( seat.3.lock().unwrap().as_ref().map_or(
String::new(), Ok(String::new()),
|primary_offer| { |primary_offer| {
let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC).unwrap(); let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC).unwrap();
let mut file = let mut file =
@ -375,8 +378,11 @@ fn clipboard_thread(
close(writefd).unwrap(); close(writefd).unwrap();
let mut contents = String::new(); let mut contents = String::new();
event_queue.sync_roundtrip().unwrap(); event_queue.sync_roundtrip().unwrap();
file.read_to_string(&mut contents).unwrap(); if let Err(err) = file.read_to_string(&mut contents) {
contents Err(err)
} else {
Ok(contents)
}
}, },
) )
}) })
@ -390,9 +396,9 @@ fn clipboard_thread(
&seat_name &seat_name
.unwrap_or_else(|| last_seat_name.lock().unwrap().clone()), .unwrap_or_else(|| last_seat_name.lock().unwrap().clone()),
) )
.map_or(String::new(), |seat| { .map_or(Ok(String::new()), |seat| {
seat.5.lock().unwrap().as_ref().map_or( seat.5.lock().unwrap().as_ref().map_or(
String::new(), Ok(String::new()),
|primary_offer| { |primary_offer| {
let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC).unwrap(); let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC).unwrap();
let mut file = let mut file =
@ -404,17 +410,20 @@ fn clipboard_thread(
close(writefd).unwrap(); close(writefd).unwrap();
let mut contents = String::new(); let mut contents = String::new();
event_queue.sync_roundtrip().unwrap(); event_queue.sync_roundtrip().unwrap();
file.read_to_string(&mut contents).unwrap(); if let Err(err) = file.read_to_string(&mut contents) {
contents Err(err)
} else {
Ok(contents)
}
}, },
) )
}) })
} else { } else {
String::new() Ok(String::new())
}; };
// Normalization should happen only on `text/plain;charset=utf-8`, in case we // Normalization should happen only on `text/plain;charset=utf-8`, in case we
// add other mime types consult gtk for normalization. // add other mime types consult gtk for normalization.
let contents = normilize_to_lf(contents); let contents = contents.and_then(|contents| Ok(normilize_to_lf(contents)));
load_send.send(contents).unwrap(); load_send.send(contents).unwrap();
} }
// Store text in the primary clipboard // Store text in the primary clipboard