FIX: Replace uses of <[T]>::get_unchecked_mut with raw pointer accessor

This is a soundness fix w.r.t unsafe coding guidelines.

In some of the instances, `get_unchecked_mut() -> &mut T as *mut T` was
used in places where the element was potentially uninitialized.

This was a problem in push. (Not a problem in IntoIter next/next_back,
where the whole range we're iterating is initialized).
This commit is contained in:
bluss
2019-10-09 10:09:07 +02:00
parent 1483c6d372
commit fd72321191
+11 -6
View File
@@ -238,10 +238,15 @@ impl<A: Array> ArrayVec<A> {
pub unsafe fn push_unchecked(&mut self, element: A::Item) { pub unsafe fn push_unchecked(&mut self, element: A::Item) {
let len = self.len(); let len = self.len();
debug_assert!(len < A::CAPACITY); debug_assert!(len < A::CAPACITY);
ptr::write(self.get_unchecked_mut(len), element); ptr::write(self.get_unchecked_ptr(len), element);
self.set_len(len + 1); self.set_len(len + 1);
} }
/// Get pointer to where element at `index` would be
unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item {
self.xs.ptr_mut().add(index)
}
/// Insert `element` at position `index`. /// Insert `element` at position `index`.
/// ///
/// Shift up all elements after `index`. /// Shift up all elements after `index`.
@@ -299,7 +304,7 @@ impl<A: Array> ArrayVec<A> {
unsafe { // infallible unsafe { // infallible
// The spot to put the new value // The spot to put the new value
{ {
let p: *mut _ = self.get_unchecked_mut(index); let p: *mut _ = self.get_unchecked_ptr(index);
// Shift everything over to make space. (Duplicating the // Shift everything over to make space. (Duplicating the
// `index`th element into two consecutive places.) // `index`th element into two consecutive places.)
ptr::copy(p, p.offset(1), len - index); ptr::copy(p, p.offset(1), len - index);
@@ -333,7 +338,7 @@ impl<A: Array> ArrayVec<A> {
unsafe { unsafe {
let new_len = self.len() - 1; let new_len = self.len() - 1;
self.set_len(new_len); self.set_len(new_len);
Some(ptr::read(self.get_unchecked_mut(new_len))) Some(ptr::read(self.get_unchecked_ptr(new_len)))
} }
} }
@@ -760,7 +765,7 @@ impl<A: Array> Iterator for IntoIter<A> {
unsafe { unsafe {
let index = self.index.to_usize(); let index = self.index.to_usize();
self.index = Index::from(index + 1); self.index = Index::from(index + 1);
Some(ptr::read(self.v.get_unchecked_mut(index))) Some(ptr::read(self.v.get_unchecked_ptr(index)))
} }
} }
} }
@@ -779,7 +784,7 @@ impl<A: Array> DoubleEndedIterator for IntoIter<A> {
unsafe { unsafe {
let new_len = self.v.len() - 1; let new_len = self.v.len() - 1;
self.v.set_len(new_len); self.v.set_len(new_len);
Some(ptr::read(self.v.get_unchecked_mut(new_len))) Some(ptr::read(self.v.get_unchecked_ptr(new_len)))
} }
} }
} }
@@ -795,7 +800,7 @@ impl<A: Array> Drop for IntoIter<A> {
unsafe { unsafe {
self.v.set_len(0); self.v.set_len(0);
let elements = slice::from_raw_parts_mut( let elements = slice::from_raw_parts_mut(
self.v.get_unchecked_mut(index), self.v.get_unchecked_ptr(index),
len - index); len - index);
ptr::drop_in_place(elements); ptr::drop_in_place(elements);
} }