From 04b07ed4c9f275e749ad5219849b5b71216d8cee Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 6 Jun 2021 17:32:51 +0200 Subject: [PATCH 1/4] gtk: 'Document' an unsafe block Signed-off-by: Uli Schlachter --- druid-shell/src/platform/gtk/clipboard.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/druid-shell/src/platform/gtk/clipboard.rs b/druid-shell/src/platform/gtk/clipboard.rs index 1bf8230ee6..50f171adf1 100644 --- a/druid-shell/src/platform/gtk/clipboard.rs +++ b/druid-shell/src/platform/gtk/clipboard.rs @@ -130,7 +130,8 @@ impl Clipboard { let targets = clipboard.wait_for_targets().unwrap_or_default(); targets .iter() - .map(|atom| unsafe { format!("{} ({})", atom.name(), atom.value()) }) + // SAFETY: Atom::value() is 'self.0 as usize'. No idea why that is unsafe. + .map(|atom| format!("{} ({})", atom.name(), unsafe { atom.value() })) .collect() } } From 7953ca1ba5bd3cd954b45f62fdaa9392cc598f6e Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 6 Jun 2021 17:41:37 +0200 Subject: [PATCH 2/4] gtk: Replace unsound std::str::from_utf8_unchecked When putting text data into the clipboard, the platform code was calling std::str::from_utf8_unchecked() on the data. That's not really valid, because the caller can provide arbitrary bytes. Thus, this commit replaces that with a call to std::str::from_utf8(). In case invalid utf8 was provided, the selection is instead set as raw bytes. I am not sure what will happen "down the road" with this, but it seems to be the best that can be done. Fixes: https://github.com/linebender/druid/issues/1814 Signed-off-by: Uli Schlachter --- druid-shell/src/platform/gtk/clipboard.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/druid-shell/src/platform/gtk/clipboard.rs b/druid-shell/src/platform/gtk/clipboard.rs index 50f171adf1..02937fea16 100644 --- a/druid-shell/src/platform/gtk/clipboard.rs +++ b/druid-shell/src/platform/gtk/clipboard.rs @@ -64,9 +64,17 @@ impl Clipboard { let idx = idx as usize; if idx < formats.len() { let item = &formats[idx]; + let mut not_set = true; if item.identifier == ClipboardFormat::TEXT { - sel.set_text(unsafe { std::str::from_utf8_unchecked(&item.data) }); - } else { + if let Ok(data) = std::str::from_utf8(&item.data) { + sel.set_text(data); + not_set = false; + } else { + tracing::warn!("Failed to put invalid utf8 text into the clipboard"); + // The code below will at least put it as "raw bytes" + } + } + if not_set { let atom = Atom::intern(item.identifier); let stride = 8; sel.set(&atom, stride, item.data.as_slice()); From 035da5abee004079b990049f6a1d84e4a8074954 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 6 Jun 2021 17:46:37 +0200 Subject: [PATCH 3/4] Update changelog Signed-off-by: Uli Schlachter --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f11655e8f..ae5e9a1e37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ You can find its changes [documented below](#070---2021-01-01). - `Notification`s will not be delivered to the widget that sends them ([#1640] by [@cmyr]) - `TextBox` can handle standard keyboard shortcuts without needing menus ([#1660] by [@cmyr]) - GTK Shell: Prevent mangling of newline characters in clipboard ([#1695] by [@ForLoveOfCats]) +- GTK: Replaced call to `std::str::from_utf8_unchecked` with `from_utf8` ([#1820] by [@psychon]) - Use correct fill rule when rendering SVG paths ([#1606] by [@SecondFlight]) - Correctly capture and use stroke properties when rendering SVG paths ([#1647] by [@SecondFlight]) - focus-chain now only includes non hidden (`should_propagate_to_hidden()` on `Event` and `Lifecylce`) widgets ([#1724] by [@xarvic]) @@ -726,6 +727,7 @@ Last release without a changelog :( [#1772]: https://github.com/linebender/druid/pull/1772 [#1787]: https://github.com/linebender/druid/pull/1787 [#1802]: https://github.com/linebender/druid/pull/1802 +[#1820]: https://github.com/linebender/druid/pull/1820 [Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master [0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0 From 76c6e7dc09fce46de69d795d15eff1ce9177b293 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 6 Jun 2021 21:27:18 +0200 Subject: [PATCH 4/4] Apply @jneem's code suggestion Signed-off-by: Uli Schlachter --- druid-shell/src/platform/gtk/clipboard.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/druid-shell/src/platform/gtk/clipboard.rs b/druid-shell/src/platform/gtk/clipboard.rs index 02937fea16..e4eaa01e63 100644 --- a/druid-shell/src/platform/gtk/clipboard.rs +++ b/druid-shell/src/platform/gtk/clipboard.rs @@ -64,17 +64,11 @@ impl Clipboard { let idx = idx as usize; if idx < formats.len() { let item = &formats[idx]; - let mut not_set = true; - if item.identifier == ClipboardFormat::TEXT { - if let Ok(data) = std::str::from_utf8(&item.data) { - sel.set_text(data); - not_set = false; - } else { - tracing::warn!("Failed to put invalid utf8 text into the clipboard"); - // The code below will at least put it as "raw bytes" - } - } - if not_set { + if let (ClipboardFormat::TEXT, Ok(data)) = + (item.identifier, std::str::from_utf8(&item.data)) + { + sel.set_text(data); + } else { let atom = Atom::intern(item.identifier); let stride = 8; sel.set(&atom, stride, item.data.as_slice());