diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-04-05 13:13:08 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-05 13:13:08 +0200 |
| commit | 7e4ed72d64eb7a6bd6a05d4f3222aa43975898e1 (patch) | |
| tree | f41410f4fc699afc25c019cecbf8c78233a4234b /src/liballoc/vec.rs | |
| parent | 7b657d340d715f48449189fea9d032350323a13f (diff) | |
| parent | 7e81c11aa8ddcebf64c01579754b44930ecf4d04 (diff) | |
| download | rust-7e4ed72d64eb7a6bd6a05d4f3222aa43975898e1.tar.gz rust-7e4ed72d64eb7a6bd6a05d4f3222aa43975898e1.zip | |
Rollup merge of #70558 - RalfJung:vec-extend-aliasing, r=Amanieu
Fix some aliasing issues in Vec `Vec::extend` and `Vec::truncate` invalidated references into the vector even without reallocation, because they (implicitly) created a mutable reference covering the *entire* initialized part of the vector. Fixes https://github.com/rust-lang/rust/issues/70301 I verified the fix by adding some new tests here that I ran in Miri.
Diffstat (limited to 'src/liballoc/vec.rs')
| -rw-r--r-- | src/liballoc/vec.rs | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 80574efe062..a48e48d7da3 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -740,7 +740,8 @@ impl<T> Vec<T> { if len > self.len { return; } - let s = self.get_unchecked_mut(len..) as *mut _; + let remaining_len = self.len - len; + let s = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); self.len = len; ptr::drop_in_place(s); } @@ -963,13 +964,15 @@ impl<T> Vec<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn swap_remove(&mut self, index: usize) -> T { + let len = self.len(); + assert!(index < len); unsafe { // We replace self[index] with the last element. Note that if the - // bounds check on hole succeeds there must be a last element (which + // bounds check above succeeds there must be a last element (which // can be self[index] itself). - let hole: *mut T = &mut self[index]; - let last = ptr::read(self.get_unchecked(self.len - 1)); - self.len -= 1; + let last = ptr::read(self.as_ptr().add(len - 1)); + let hole: *mut T = self.as_mut_ptr().add(index); + self.set_len(len - 1); ptr::replace(hole, last) } } @@ -1200,7 +1203,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,7 +2023,7 @@ where let (lower, _) = iterator.size_hint(); let mut vector = Vec::with_capacity(lower.saturating_add(1)); unsafe { - ptr::write(vector.get_unchecked_mut(0), element); + ptr::write(vector.as_mut_ptr(), element); vector.set_len(1); } vector @@ -2122,8 +2125,9 @@ where self.reserve(slice.len()); unsafe { let len = self.len(); + let dst_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), slice.len()); + dst_slice.copy_from_slice(slice); self.set_len(len + slice.len()); - self.get_unchecked_mut(len..).copy_from_slice(slice); } } } @@ -2144,7 +2148,7 @@ impl<T> Vec<T> { self.reserve(lower.saturating_add(1)); } unsafe { - ptr::write(self.get_unchecked_mut(len), element); + ptr::write(self.as_mut_ptr().add(len), element); // NB can't overflow since we would have had to alloc the address space self.set_len(len + 1); } |
