summaryrefslogtreecommitdiff
path: root/dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch')
-rw-r--r--dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch181
1 files changed, 181 insertions, 0 deletions
diff --git a/dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch b/dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch
new file mode 100644
index 000000000000..20373f42d307
--- /dev/null
+++ b/dev-lang/rust/files/rustc-1.51.0-backport-pr81728.patch
@@ -0,0 +1,181 @@
+From 70f17ca715d3d7e2fd79cc909b95fd3a6357c13e Mon Sep 17 00:00:00 2001
+From: Yechan Bae <yechan@gatech.edu>
+Date: Wed, 3 Feb 2021 16:36:33 -0500
+Subject: [PATCH 1/2] Fixes #80335
+
+---
+ library/alloc/src/str.rs | 42 ++++++++++++++++++++++----------------
+ library/alloc/tests/str.rs | 30 +++++++++++++++++++++++++++
+ 2 files changed, 54 insertions(+), 18 deletions(-)
+
+diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
+index 70e0c7dba5ea..a7584c6b6510 100644
+--- a/library/alloc/src/str.rs
++++ b/library/alloc/src/str.rs
+@@ -90,8 +90,8 @@ fn join(slice: &Self, sep: &str) -> String {
+ }
+ }
+
+-macro_rules! spezialize_for_lengths {
+- ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {
++macro_rules! specialize_for_lengths {
++ ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{
+ let mut target = $target;
+ let iter = $iter;
+ let sep_bytes = $separator;
+@@ -102,7 +102,8 @@ macro_rules! spezialize_for_lengths {
+ $num => {
+ for s in iter {
+ copy_slice_and_advance!(target, sep_bytes);
+- copy_slice_and_advance!(target, s.borrow().as_ref());
++ let content_bytes = s.borrow().as_ref();
++ copy_slice_and_advance!(target, content_bytes);
+ }
+ },
+ )*
+@@ -110,11 +111,13 @@ macro_rules! spezialize_for_lengths {
+ // arbitrary non-zero size fallback
+ for s in iter {
+ copy_slice_and_advance!(target, sep_bytes);
+- copy_slice_and_advance!(target, s.borrow().as_ref());
++ let content_bytes = s.borrow().as_ref();
++ copy_slice_and_advance!(target, content_bytes);
+ }
+ }
+ }
+- };
++ target
++ }}
+ }
+
+ macro_rules! copy_slice_and_advance {
+@@ -153,7 +156,7 @@ fn join_generic_copy<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
+ // if the `len` calculation overflows, we'll panic
+ // we would have run out of memory anyway and the rest of the function requires
+ // the entire Vec pre-allocated for safety
+- let len = sep_len
++ let reserved_len = sep_len
+ .checked_mul(iter.len())
+ .and_then(|n| {
+ slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add)
+@@ -161,22 +164,25 @@ fn join_generic_copy<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
+ .expect("attempt to join into collection with len > usize::MAX");
+
+ // crucial for safety
+- let mut result = Vec::with_capacity(len);
+- assert!(result.capacity() >= len);
++ let mut result = Vec::with_capacity(reserved_len);
++ debug_assert!(result.capacity() >= reserved_len);
+
+ result.extend_from_slice(first.borrow().as_ref());
+
+ unsafe {
+- {
+- let pos = result.len();
+- let target = result.get_unchecked_mut(pos..len);
+-
+- // copy separator and slices over without bounds checks
+- // generate loops with hardcoded offsets for small separators
+- // massive improvements possible (~ x2)
+- spezialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
+- }
+- result.set_len(len);
++ let pos = result.len();
++ let target = result.get_unchecked_mut(pos..reserved_len);
++
++ // copy separator and slices over without bounds checks
++ // generate loops with hardcoded offsets for small separators
++ // massive improvements possible (~ x2)
++ let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
++
++ // issue #80335: A weird borrow implementation can return different
++ // slices for the length calculation and the actual copy, so
++ // `remain.len()` might be non-zero.
++ let result_len = reserved_len - remain.len();
++ result.set_len(result_len);
+ }
+ result
+ }
+diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
+index 604835e6cc4a..6df8d8c2f354 100644
+--- a/library/alloc/tests/str.rs
++++ b/library/alloc/tests/str.rs
+@@ -160,6 +160,36 @@ fn test_join_for_different_lengths_with_long_separator() {
+ test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
+ }
+
++#[test]
++fn test_join_isue_80335() {
++ use core::{borrow::Borrow, cell::Cell};
++
++ struct WeirdBorrow {
++ state: Cell<bool>,
++ }
++
++ impl Default for WeirdBorrow {
++ fn default() -> Self {
++ WeirdBorrow { state: Cell::new(false) }
++ }
++ }
++
++ impl Borrow<str> for WeirdBorrow {
++ fn borrow(&self) -> &str {
++ let state = self.state.get();
++ if state {
++ "0"
++ } else {
++ self.state.set(true);
++ "123456"
++ }
++ }
++ }
++
++ let arr: [WeirdBorrow; 3] = Default::default();
++ test_join!("0-0-0", arr, "-");
++}
++
+ #[test]
+ #[cfg_attr(miri, ignore)] // Miri is too slow
+ fn test_unsafe_slice() {
+--
+2.31.1
+
+
+From 10020817d2e6756be1ff2ac3c182af97cf7fe904 Mon Sep 17 00:00:00 2001
+From: Yechan Bae <yechan@gatech.edu>
+Date: Sat, 20 Mar 2021 13:42:54 -0400
+Subject: [PATCH 2/2] Update the comment
+
+---
+ library/alloc/src/str.rs | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
+index a7584c6b6510..4d1e876457b8 100644
+--- a/library/alloc/src/str.rs
++++ b/library/alloc/src/str.rs
+@@ -163,7 +163,7 @@ fn join_generic_copy<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
+ })
+ .expect("attempt to join into collection with len > usize::MAX");
+
+- // crucial for safety
++ // prepare an uninitialized buffer
+ let mut result = Vec::with_capacity(reserved_len);
+ debug_assert!(result.capacity() >= reserved_len);
+
+@@ -178,9 +178,9 @@ fn join_generic_copy<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
+ // massive improvements possible (~ x2)
+ let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
+
+- // issue #80335: A weird borrow implementation can return different
+- // slices for the length calculation and the actual copy, so
+- // `remain.len()` might be non-zero.
++ // A weird borrow implementation may return different
++ // slices for the length calculation and the actual copy.
++ // Make sure we don't expose uninitialized bytes to the caller.
+ let result_len = reserved_len - remain.len();
+ result.set_len(result_len);
+ }
+--
+2.31.1
+