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:
+11
-6
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user