From 91a7f7aa54c14b93de89acac17427a734e76b700 Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 9 Oct 2019 13:45:26 +0200 Subject: [PATCH 1/2] 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). (Backported fix to 0.4 from the master/0.5 branch) --- src/lib.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1e05e59a..efd5ebd3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,10 +243,15 @@ impl ArrayVec { pub unsafe fn push_unchecked(&mut self, element: A::Item) { let len = self.len(); 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); } + /// 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().offset(index as isize) + } + /// Insert `element` at position `index`. /// /// Shift up all elements after `index`. @@ -304,7 +309,7 @@ impl ArrayVec { unsafe { // infallible // 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 // `index`th element into two consecutive places.) ptr::copy(p, p.offset(1), len - index); @@ -338,7 +343,7 @@ impl ArrayVec { unsafe { let new_len = self.len() - 1; self.set_len(new_len); - Some(ptr::read(self.get_unchecked_mut(new_len))) + Some(ptr::read(self.get_unchecked_ptr(new_len))) } } @@ -701,7 +706,7 @@ impl Iterator for IntoIter { unsafe { let index = self.index.to_usize(); self.index = Index::from(index + 1); - Some(ptr::read(self.v.get_unchecked_mut(index))) + Some(ptr::read(self.v.get_unchecked_ptr(index))) } } } @@ -721,7 +726,7 @@ impl DoubleEndedIterator for IntoIter { unsafe { let new_len = self.v.len() - 1; 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))) } } } @@ -737,7 +742,7 @@ impl Drop for IntoIter { unsafe { self.v.set_len(0); let elements = slice::from_raw_parts_mut( - self.v.get_unchecked_mut(index), + self.v.get_unchecked_ptr(index), len - index); ptr::drop_in_place(elements); } @@ -1022,13 +1027,10 @@ impl> io::Write for ArrayVec { fn write(&mut self, data: &[u8]) -> io::Result { unsafe { let len = self.len(); - let mut tail = slice::from_raw_parts_mut(self.get_unchecked_mut(len), - A::capacity() - len); - let result = tail.write(data); - if let Ok(written) = result { - self.set_len(len + written); - } - result + let write_len = cmp::min(A::capacity() - len, data.len()); + ptr::copy_nonoverlapping(data.as_ptr(), self.get_unchecked_ptr(len), write_len); + self.set_len(len + write_len); + Ok(write_len) } } fn flush(&mut self) -> io::Result<()> { Ok(()) } From f88c62e59fc130edf1185b6c33720eb4874c814a Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 9 Oct 2019 16:29:14 +0200 Subject: [PATCH 2/2] 0.4.12 --- Cargo.toml | 3 ++- README.rst | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0d1eb8ea..1c117f72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arrayvec" -version = "0.4.11" +version = "0.4.12" authors = ["bluss"] license = "MIT/Apache-2.0" @@ -52,3 +52,4 @@ features = ["serde-1"] [package.metadata.release] no-dev-version = true +tag-name = "{{version}}" diff --git a/README.rst b/README.rst index 6f6476fe..d20556a6 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,11 @@ __ https://docs.rs/arrayvec Recent Changes (arrayvec) ------------------------- +- 0.4.12 + + - Use raw pointers instead of ``get_unchecked_mut`` where the target may be + uninitialized a everywhere relevant in the ArrayVec implementation. + - 0.4.11 - In Rust 1.36 or later, use newly stable MaybeUninit. This extends the