Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix undefined behavior reported by miri when reading or writing slices #351

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/api/from/from_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ macro_rules! impl_from_array {
mod [<$id _from>] {
use super::*;
#[test]
#[cfg_attr(miri, ignore)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test itself does something weird and I don't have a good idea what the intention here was. I'm open to re-enabling it, the benefit of ignoring it is that cargo miri test -- array fully passes.

fn array() {
let vec: $id = Default::default();

Expand Down
16 changes: 6 additions & 10 deletions src/api/minimal/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ macro_rules! impl_minimal_p {
pub fn from_slice_aligned(slice: &[$elem_ty]) -> Self {
unsafe {
assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked(0) as *const $elem_ty;
let target_ptr = slice.as_ptr();
assert!(
target_ptr.align_offset(crate::mem::align_of::<Self>())
== 0
Expand Down Expand Up @@ -615,7 +615,7 @@ macro_rules! impl_minimal_p {
pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty])
-> Self {
#[allow(clippy::cast_ptr_alignment)]
*(slice.get_unchecked(0) as *const $elem_ty as *const Self)
*(slice.as_ptr().cast())
}

/// Instantiates a new vector with the values of the `slice`.
Expand All @@ -628,8 +628,7 @@ macro_rules! impl_minimal_p {
slice: &[$elem_ty],
) -> Self {
use crate::mem::size_of;
let target_ptr =
slice.get_unchecked(0) as *const $elem_ty as *const u8;
let target_ptr = slice.as_ptr().cast();
let mut x = Self::splat(crate::ptr::null_mut() as $elem_ty);
let self_ptr = &mut x as *mut Self as *mut u8;
crate::ptr::copy_nonoverlapping(
Expand Down Expand Up @@ -798,8 +797,7 @@ macro_rules! impl_minimal_p {
pub fn write_to_slice_aligned(self, slice: &mut [$elem_ty]) {
unsafe {
assert!(slice.len() >= $elem_count);
let target_ptr =
slice.get_unchecked_mut(0) as *mut $elem_ty;
let target_ptr = slice.as_mut_ptr();
assert!(
target_ptr.align_offset(crate::mem::align_of::<Self>())
== 0
Expand Down Expand Up @@ -833,8 +831,7 @@ macro_rules! impl_minimal_p {
self, slice: &mut [$elem_ty],
) {
#[allow(clippy::cast_ptr_alignment)]
*(slice.get_unchecked_mut(0) as *mut $elem_ty as *mut Self) =
self;
*(slice.as_mut_ptr().cast()) = self;
}

/// Writes the values of the vector to the `slice`.
Expand All @@ -846,8 +843,7 @@ macro_rules! impl_minimal_p {
pub unsafe fn write_to_slice_unaligned_unchecked(
self, slice: &mut [$elem_ty],
) {
let target_ptr =
slice.get_unchecked_mut(0) as *mut $elem_ty as *mut u8;
let target_ptr = slice.as_mut_ptr().cast();
let self_ptr = &self as *const Self as *const u8;
crate::ptr::copy_nonoverlapping(
self_ptr,
Expand Down
6 changes: 3 additions & 3 deletions src/api/slice/from_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ macro_rules! impl_slice_from_slice {
pub fn from_slice_aligned(slice: &[$elem_ty]) -> Self {
unsafe {
assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked(0) as *const $elem_ty;
let target_ptr = slice.as_ptr();
assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
Self::from_slice_aligned_unchecked(slice)
}
Expand Down Expand Up @@ -41,7 +41,7 @@ macro_rules! impl_slice_from_slice {
#[inline]
pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty]) -> Self {
debug_assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked(0) as *const $elem_ty;
let target_ptr = slice.as_ptr();
debug_assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);

#[allow(clippy::cast_ptr_alignment)]
Expand All @@ -57,7 +57,7 @@ macro_rules! impl_slice_from_slice {
pub unsafe fn from_slice_unaligned_unchecked(slice: &[$elem_ty]) -> Self {
use crate::mem::size_of;
debug_assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked(0) as *const $elem_ty as *const u8;
let target_ptr = slice.as_ptr().cast();
let mut x = Self::splat(0 as $elem_ty);
let self_ptr = &mut x as *mut Self as *mut u8;
crate::ptr::copy_nonoverlapping(target_ptr, self_ptr, size_of::<Self>());
Expand Down
6 changes: 3 additions & 3 deletions src/api/slice/write_to_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ macro_rules! impl_slice_write_to_slice {
pub fn write_to_slice_aligned(self, slice: &mut [$elem_ty]) {
unsafe {
assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked_mut(0) as *mut $elem_ty;
let target_ptr = slice.as_mut_ptr();
assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
self.write_to_slice_aligned_unchecked(slice);
}
Expand Down Expand Up @@ -42,7 +42,7 @@ macro_rules! impl_slice_write_to_slice {
#[inline]
pub unsafe fn write_to_slice_aligned_unchecked(self, slice: &mut [$elem_ty]) {
debug_assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked_mut(0) as *mut $elem_ty;
let target_ptr = slice.as_mut_ptr();
debug_assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);

#[allow(clippy::cast_ptr_alignment)]
Expand All @@ -60,7 +60,7 @@ macro_rules! impl_slice_write_to_slice {
#[inline]
pub unsafe fn write_to_slice_unaligned_unchecked(self, slice: &mut [$elem_ty]) {
debug_assert!(slice.len() >= $elem_count);
let target_ptr = slice.get_unchecked_mut(0) as *mut $elem_ty as *mut u8;
let target_ptr = slice.as_mut_ptr().cast();
let self_ptr = &self as *const Self as *const u8;
crate::ptr::copy_nonoverlapping(self_ptr, target_ptr, crate::mem::size_of::<Self>());
}
Expand Down
Loading