diff options
| -rw-r--r-- | src/libcore/ffi.rs | 9 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 144 | ||||
| -rw-r--r-- | src/libcore/slice/rotate.rs | 2 |
3 files changed, 108 insertions, 47 deletions
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 7bc2866dc2e..dda1d3467b6 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -1,5 +1,6 @@ #![stable(feature = "", since = "1.30.0")] #![allow(non_camel_case_types)] +#![deny(unsafe_op_in_unsafe_fn)] //! Utilities related to FFI bindings. @@ -333,7 +334,8 @@ impl<'f> VaListImpl<'f> { /// Advance to the next arg. #[inline] pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T { - va_arg(self) + // SAFETY: the caller must uphold the safety contract for `va_arg`. + unsafe { va_arg(self) } } /// Copies the `va_list` at the current location. @@ -343,7 +345,10 @@ impl<'f> VaListImpl<'f> { { let mut ap = self.clone(); let ret = f(ap.as_va_list()); - va_end(&mut ap); + // SAFETY: the caller must uphold the safety contract for `va_end`. + unsafe { + va_end(&mut ap); + } ret } } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 6a50cdbc1d9..ad9c43eccc1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -8,6 +8,7 @@ //! [`std::slice`]: ../../std/slice/index.html #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] // How this module is organized. // @@ -310,7 +311,8 @@ impl<T> [T] { where I: SliceIndex<Self>, { - index.get_unchecked(self) + // SAFETY: the caller must uphold the safety requirements for `get_unchecked`. + unsafe { index.get_unchecked(self) } } /// Returns a mutable reference to an element or subslice, without doing @@ -341,7 +343,8 @@ impl<T> [T] { where I: SliceIndex<Self>, { - index.get_unchecked_mut(self) + // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`. + unsafe { index.get_unchecked_mut(self) } } /// Returns a raw pointer to the slice's buffer. @@ -2519,18 +2522,21 @@ impl<T> [T] { // First, find at what point do we split between the first and 2nd slice. Easy with // ptr.align_offset. let ptr = self.as_ptr(); - let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>()); + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) }; if offset > self.len() { (self, &[], &[]) } else { let (left, rest) = self.split_at(offset); - // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::<U>(); - ( - left, - from_raw_parts(rest.as_ptr() as *const U, us_len), - from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len), - ) + // SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay, + // since the caller guarantees that we can transmute `T` to `U` safely. + unsafe { + ( + left, + from_raw_parts(rest.as_ptr() as *const U, us_len), + from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len), + ) + } } } @@ -2575,21 +2581,23 @@ impl<T> [T] { // First, find at what point do we split between the first and 2nd slice. Easy with // ptr.align_offset. let ptr = self.as_ptr(); - let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>()); + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) }; if offset > self.len() { (self, &mut [], &mut []) } else { let (left, rest) = self.split_at_mut(offset); - // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::<U>(); let rest_len = rest.len(); let mut_ptr = rest.as_mut_ptr(); // We can't use `rest` again after this, that would invalidate its alias `mut_ptr`! - ( - left, - from_raw_parts_mut(mut_ptr as *mut U, us_len), - from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len), - ) + // SAFETY: see comments for `align_to`. + unsafe { + ( + left, + from_raw_parts_mut(mut_ptr as *mut U, us_len), + from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len), + ) + } } } @@ -2914,12 +2922,18 @@ impl<T> SliceIndex<[T]> for usize { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &T { - &*slice.as_ptr().add(self) + // SAFETY: `slice` cannot be longer than `isize::MAX` and + // the caller guarantees that `self` is in bounds of `slice` + // so `self` cannot overflow an `isize`, so the call to `add` is safe. + // The obtained pointer comes from a reference which is guaranteed + // to be valid. + unsafe { &*slice.as_ptr().add(self) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T { - &mut *slice.as_mut_ptr().add(self) + // SAFETY: see comments for `get_unchecked` above. + unsafe { &mut *slice.as_mut_ptr().add(self) } } #[inline] @@ -2959,12 +2973,18 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) + // SAFETY: `slice` cannot be longer than `isize::MAX` and + // the caller guarantees that `self` is in bounds of `slice` + // so `self` cannot overflow an `isize`, so the call to `add` is safe. + // Also, since the caller guarantees that `self` is in bounds of `slice`, + // `from_raw_parts` will give a subslice of `slice` which is always safe. + unsafe { from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) + // SAFETY: see comments for `get_unchecked` above. + unsafe { from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) } } #[inline] @@ -3004,12 +3024,14 @@ impl<T> SliceIndex<[T]> for ops::RangeTo<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0..self.end).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0..self.end).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..self.end).get_unchecked_mut(slice) } } #[inline] @@ -3039,12 +3061,14 @@ impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (self.start..slice.len()).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..slice.len()).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (self.start..slice.len()).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..slice.len()).get_unchecked_mut(slice) } } #[inline] @@ -3113,12 +3137,14 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (*self.start()..self.end() + 1).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (*self.start()..self.end() + 1).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) } } #[inline] @@ -3154,12 +3180,14 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0..=self.end).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..=self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0..=self.end).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..=self.end).get_unchecked_mut(slice) } } #[inline] @@ -3308,7 +3336,9 @@ macro_rules! iterator { self.ptr.as_ptr() } else { let old = self.ptr.as_ptr(); - self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)); + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // so this new pointer is inside `self` and thus guaranteed to be non-null. + self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) }; old } } @@ -3322,7 +3352,10 @@ macro_rules! iterator { zst_shrink!(self, offset); self.ptr.as_ptr() } else { - self.end = self.end.offset(-offset); + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // which is guaranteed to not overflow an `isize`. Also, the resulting pointer + // is in bounds of `slice`, which fulfills the other requirements for `offset`. + self.end = unsafe { self.end.offset(-offset) }; self.end } } @@ -4640,7 +4673,11 @@ impl<T> FusedIterator for Windows<'_, T> {} #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { - from_raw_parts(self.v.as_ptr().add(i), self.size) + // SAFETY: since the caller guarantees that `i` is in bounds, + // which means that `i` cannot overflow an `isize`, and the + // slice created by `from_raw_parts` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { from_raw_parts(self.v.as_ptr().add(i), self.size) } } fn may_have_side_effect() -> bool { false @@ -4784,7 +4821,14 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts(self.v.as_ptr().add(start), end - start) + // SAFETY: the caller guarantees that `i` is in bounds, + // which means that `start` must be in bounds of the + // underlying `self.v` slice, and we made sure that `end` + // is also in bounds of `self.v`. Thus, `start` cannot overflow + // an `isize`, and the slice constructed by `from_raw_parts` + // is a subslice of `self.v` which is guaranteed to be valid + // for the lifetime `'a` of `self.v`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -4926,7 +4970,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) + // SAFETY: see comments for `Chunks::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5063,7 +5108,8 @@ impl<T> FusedIterator for ChunksExact<'_, T> {} unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let start = i * self.chunk_size; - from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) + // SAFETY: mostly identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5197,7 +5243,8 @@ impl<T> FusedIterator for ChunksExactMut<'_, T> {} unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let start = i * self.chunk_size; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) + // SAFETY: see comments for `ChunksExactMut::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5344,7 +5391,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> { None => 0, Some(start) => start, }; - from_raw_parts(self.v.as_ptr().add(start), end - start) + // SAFETY: mostly identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5489,7 +5537,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> { None => 0, Some(start) => start, }; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) + // SAFETY: see comments for `RChunks::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5630,7 +5679,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let end = self.v.len() - i * self.chunk_size; let start = end - self.chunk_size; - from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) + // SAFETY: mostmy identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5769,7 +5819,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let end = self.v.len() - i * self.chunk_size; let start = end - self.chunk_size; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) + // SAFETY: see comments for `RChunksExact::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5865,7 +5916,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering at least half the address space" ); - &*ptr::slice_from_raw_parts(data, len) + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. + unsafe { &*ptr::slice_from_raw_parts(data, len) } } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -5905,7 +5957,8 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering at least half the address space" ); - &mut *ptr::slice_from_raw_parts_mut(data, len) + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. + unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) } } /// Converts a reference to T into a slice of length 1 (without copying). @@ -6181,7 +6234,11 @@ impl_marker_for!(BytewiseEquality, #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - &*self.ptr.as_ptr().add(i) + // SAFETY: the caller must guarantee that `i` is in bounds + // of the underlying slice, so `i` cannot overflow an `isize`, + // and the returned references is guaranteed to refer to an element + // of the slice and thus guaranteed to be valid. + unsafe { &*self.ptr.as_ptr().add(i) } } fn may_have_side_effect() -> bool { false @@ -6191,7 +6248,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - &mut *self.ptr.as_ptr().add(i) + // SAFETY: see comments for `Iter::get_unchecked`. + unsafe { &mut *self.ptr.as_ptr().add(i) } } fn may_have_side_effect() -> bool { false diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 7bdd7d009e1..a89596b15ef 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -1,7 +1,5 @@ // ignore-tidy-undocumented-unsafe -#![deny(unsafe_op_in_unsafe_fn)] - use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; |
