diff options
| author | LeSeulArtichaut <leseulartichaut@gmail.com> | 2020-06-22 19:25:39 +0200 |
|---|---|---|
| committer | LeSeulArtichaut <leseulartichaut@gmail.com> | 2020-06-30 16:42:58 +0200 |
| commit | 8a515e963cf2711192495802d7bbf2e49979cdf2 (patch) | |
| tree | 6b5d4a3ccb13e27782c715f3adba5b57769904b2 /src | |
| parent | 8ee1dec77b89d6341a147d91af8733f8e0b5efc7 (diff) | |
| download | rust-8a515e963cf2711192495802d7bbf2e49979cdf2.tar.gz rust-8a515e963cf2711192495802d7bbf2e49979cdf2.zip | |
Deny unsafe ops in unsafe fns, part 2
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/hash/sip.rs | 11 | ||||
| -rw-r--r-- | src/libcore/iter/adapters/fuse.rs | 5 | ||||
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 15 | ||||
| -rw-r--r-- | src/libcore/iter/adapters/zip.rs | 3 | ||||
| -rw-r--r-- | src/libcore/iter/mod.rs | 1 | ||||
| -rw-r--r-- | src/libcore/iter/range.rs | 30 | ||||
| -rw-r--r-- | src/libcore/mem/manually_drop.rs | 9 | ||||
| -rw-r--r-- | src/libcore/mem/maybe_uninit.rs | 42 | ||||
| -rw-r--r-- | src/libcore/mem/mod.rs | 24 |
9 files changed, 103 insertions, 37 deletions
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index ac058609f45..84148058d03 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -1,6 +1,7 @@ //! An implementation of SipHash. #![allow(deprecated)] // the types in this module are deprecated +#![deny(unsafe_op_in_unsafe_fn)] use crate::cmp; use crate::marker::PhantomData; @@ -130,15 +131,19 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { let mut i = 0; // current byte index (from LSB) in the output u64 let mut out = 0; if i + 3 < len { - out = load_int_le!(buf, start + i, u32) as u64; + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; i += 4; } if i + 1 < len { - out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8); + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8); i += 2 } if i < len { - out |= (*buf.get_unchecked(start + i) as u64) << (i * 8); + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); i += 1; } debug_assert_eq!(i, len); diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 502fc2e6315..d2e2fc04a2b 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -178,9 +178,10 @@ where { unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { match self.iter { - Some(ref mut iter) => iter.get_unchecked(i), + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + Some(ref mut iter) => unsafe { iter.get_unchecked(i) }, // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. - None => intrinsics::unreachable(), + None => unsafe { intrinsics::unreachable() }, } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 00529f0e2d5..133643a0c7f 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -272,7 +272,8 @@ where T: Copy, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - *self.it.get_unchecked(i) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { *self.it.get_unchecked(i) } } #[inline] @@ -402,7 +403,8 @@ where T: Clone, { default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - self.it.get_unchecked(i).clone() + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { self.it.get_unchecked(i) }.clone() } #[inline] @@ -418,7 +420,8 @@ where T: Copy, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - *self.it.get_unchecked(i) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { *self.it.get_unchecked(i) } } #[inline] @@ -930,7 +933,8 @@ where F: FnMut(I::Item) -> B, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - (self.f)(self.iter.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + (self.f)(unsafe { self.iter.get_unchecked(i) }) } #[inline] fn may_have_side_effect() -> bool { @@ -1392,7 +1396,8 @@ where I: TrustedRandomAccess, { unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) { - (self.count + i, self.iter.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + (self.count + i, unsafe { self.iter.get_unchecked(i) }) } fn may_have_side_effect() -> bool { diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index e83d36a580f..985e6561665 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -271,7 +271,8 @@ where B: TrustedRandomAccess, { unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) { - (self.a.get_unchecked(i), self.b.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { (self.a.get_unchecked(i), self.b.get_unchecked(i)) } } fn may_have_side_effect() -> bool { diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 080b70c6368..4a1f6418bb5 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -309,6 +309,7 @@ //! [`min`]: trait.Iterator.html#method.min #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] use crate::ops::Try; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index bd7e6cfa5a7..ee53b6a13f8 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -189,12 +189,14 @@ macro_rules! step_identical_methods { () => { #[inline] unsafe fn forward_unchecked(start: Self, n: usize) -> Self { - start.unchecked_add(n as Self) + // SAFETY: the caller has to guarantee that `start + n` doesn't overflow. + unsafe { start.unchecked_add(n as Self) } } #[inline] unsafe fn backward_unchecked(start: Self, n: usize) -> Self { - start.unchecked_sub(n as Self) + // SAFETY: the caller has to guarantee that `start - n` doesn't overflow. + unsafe { start.unchecked_sub(n as Self) } } #[inline] @@ -450,21 +452,33 @@ unsafe impl Step for char { #[inline] unsafe fn forward_unchecked(start: char, count: usize) -> char { let start = start as u32; - let mut res = Step::forward_unchecked(start, count); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::forward_unchecked(start, count) }; if start < 0xD800 && 0xD800 <= res { - res = Step::forward_unchecked(res, 0x800); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::forward_unchecked(res, 0x800) }; } - char::from_u32_unchecked(res) + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } } #[inline] unsafe fn backward_unchecked(start: char, count: usize) -> char { let start = start as u32; - let mut res = Step::backward_unchecked(start, count); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::backward_unchecked(start, count) }; if start >= 0xE000 && 0xE000 > res { - res = Step::backward_unchecked(res, 0x800); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::backward_unchecked(res, 0x800) }; } - char::from_u32_unchecked(res) + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } } } diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 18767c482c7..920f5e9c0bd 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -122,7 +122,9 @@ impl<T> ManuallyDrop<T> { #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { - ptr::read(&slot.value) + // SAFETY: we are reading from a reference, which is guaranteed + // to be valid for reads. + unsafe { ptr::read(&slot.value) } } } @@ -152,7 +154,10 @@ impl<T: ?Sized> ManuallyDrop<T> { #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { - ptr::drop_in_place(&mut slot.value) + // SAFETY: we are dropping the value pointed to by a mutable reference + // which is guaranteed to be valid for writes. + // It is up to the caller to make sure that `slot` isn't dropped again. + unsafe { ptr::drop_in_place(&mut slot.value) } } } diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 499016545e9..7732525a0fc 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -494,8 +494,12 @@ impl<T> MaybeUninit<T> { #[inline(always)] #[rustc_diagnostic_item = "assume_init"] pub unsafe fn assume_init(self) -> T { - intrinsics::assert_inhabited::<T>(); - ManuallyDrop::into_inner(self.value) + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + ManuallyDrop::into_inner(self.value) + } } /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject @@ -558,8 +562,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { - intrinsics::assert_inhabited::<T>(); - self.as_ptr().read() + // SAFETY: the caller must guarantee that `self` is initialized. + // Reading from `self.as_ptr()` is safe since `self` should be initialized. + unsafe { + intrinsics::assert_inhabited::<T>(); + self.as_ptr().read() + } } /// Gets a shared reference to the contained value. @@ -620,8 +628,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { - intrinsics::assert_inhabited::<T>(); - &*self.value + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + &*self.value + } } /// Gets a mutable (unique) reference to the contained value. @@ -738,8 +750,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { - intrinsics::assert_inhabited::<T>(); - &mut *self.value + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + &mut *self.value + } } /// Assuming all the elements are initialized, get a slice to them. @@ -752,7 +768,11 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] #[inline(always)] pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { - &*(slice as *const [Self] as *const [T]) + // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that + // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`. + // The pointer obtained is valid since it refers to memory owned by `slice` which is a + // reference and thus guaranteed to be valid for reads. + unsafe { &*(slice as *const [Self] as *const [T]) } } /// Assuming all the elements are initialized, get a mutable slice to them. @@ -765,7 +785,9 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] #[inline(always)] pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { - &mut *(slice as *mut [Self] as *mut [T]) + // SAFETY: similar to safety notes for `slice_get_ref`, but we have a + // mutable reference which is also guaranteed to be valid for writes. + unsafe { &mut *(slice as *mut [Self] as *mut [T]) } } /// Gets a pointer to the first element of the array. diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 46e6ea7cd18..20ea83fd063 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -4,6 +4,7 @@ //! types, initializing and manipulating memory. #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] use crate::clone; use crate::cmp; @@ -623,8 +624,11 @@ pub const fn needs_drop<T>() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] pub unsafe fn zeroed<T>() -> T { - intrinsics::assert_zero_valid::<T>(); - MaybeUninit::zeroed().assume_init() + // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. + unsafe { + intrinsics::assert_zero_valid::<T>(); + MaybeUninit::zeroed().assume_init() + } } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -656,8 +660,11 @@ pub unsafe fn zeroed<T>() -> T { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_uninitialized"] pub unsafe fn uninitialized<T>() -> T { - intrinsics::assert_uninit_valid::<T>(); - MaybeUninit::uninit().assume_init() + // SAFETY: the caller must guarantee that an unitialized value is valid for `T`. + unsafe { + intrinsics::assert_uninit_valid::<T>(); + MaybeUninit::uninit().assume_init() + } } /// Swaps the values at two mutable locations, without deinitializing either one. @@ -922,9 +929,14 @@ pub fn drop<T>(_x: T) {} pub unsafe fn transmute_copy<T, U>(src: &T) -> U { // If U has a higher alignment requirement, src may not be suitably aligned. if align_of::<U>() > align_of::<T>() { - ptr::read_unaligned(src as *const T as *const U) + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read_unaligned(src as *const T as *const U) } } else { - ptr::read(src as *const T as *const U) + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // We just checked that `src as *const U` was properly aligned. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read(src as *const T as *const U) } } } |
