about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-03-30 13:11:37 +0200
committerRalf Jung <post@ralfj.de>2020-03-30 13:24:55 +0200
commit8f479e362fbfcb31e83396ef850ab5219a32821e (patch)
tree554fe3c0bb7f31547838633cc47b8b80b8498084 /src/liballoc
parent4eacf45c9cf6bd110dc019082c2a4a8fd9668d66 (diff)
downloadrust-8f479e362fbfcb31e83396ef850ab5219a32821e.tar.gz
rust-8f479e362fbfcb31e83396ef850ab5219a32821e.zip
fix aliasing in remove()
also add smoke test to detect relocation even in rustc runs
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/tests/vec.rs7
-rw-r--r--src/liballoc/vec.rs6
2 files changed, 8 insertions, 5 deletions
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 05fa7589639..a90bc58cbfd 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -1366,7 +1366,8 @@ fn test_stable_pointers() {
     v.push(13);
 
     // Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
-    let v0 = unsafe { &*(&v[0] as *const _) };
+    let v0 = &mut v[0];
+    let v0 = unsafe { &mut *(v0 as *mut _) };
     // Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
 
     // Pushing/inserting and popping/removing
@@ -1420,6 +1421,10 @@ fn test_stable_pointers() {
     assert_eq!(*v0, 13);
     next_then_drop(v.splice(5..6, vec![1; 10].into_iter().filter(|_| true))); // lower bound not exact
     assert_eq!(*v0, 13);
+
+    // Smoke test that would fire even outside Miri if an actual relocation happened.
+    *v0 -= 13;
+    assert_eq!(v[0], 0);
 }
 
 // https://github.com/rust-lang/rust/pull/49496 introduced specialization based on:
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 1c8c4428169..dc2a246f817 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1200,7 +1200,7 @@ impl<T> Vec<T> {
         } else {
             unsafe {
                 self.len -= 1;
-                Some(ptr::read(self.get_unchecked(self.len())))
+                Some(ptr::read(self.as_ptr().add(self.len())))
             }
         }
     }
@@ -2020,9 +2020,7 @@ where
                 let (lower, _) = iterator.size_hint();
                 let mut vector = Vec::with_capacity(lower.saturating_add(1));
                 unsafe {
-                    // `vector` is new, cannot have aliases, so us getting exclusive references
-                    // here is okay.
-                    ptr::write(vector.get_unchecked_mut(0), element);
+                    ptr::write(vector.as_mut_ptr(), element);
                     vector.set_len(1);
                 }
                 vector