about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorLeSeulArtichaut <leseulartichaut@gmail.com>2020-06-22 19:25:39 +0200
committerLeSeulArtichaut <leseulartichaut@gmail.com>2020-06-30 16:42:58 +0200
commit8a515e963cf2711192495802d7bbf2e49979cdf2 (patch)
tree6b5d4a3ccb13e27782c715f3adba5b57769904b2 /src/libcore
parent8ee1dec77b89d6341a147d91af8733f8e0b5efc7 (diff)
downloadrust-8a515e963cf2711192495802d7bbf2e49979cdf2.tar.gz
rust-8a515e963cf2711192495802d7bbf2e49979cdf2.zip
Deny unsafe ops in unsafe fns, part 2
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/hash/sip.rs11
-rw-r--r--src/libcore/iter/adapters/fuse.rs5
-rw-r--r--src/libcore/iter/adapters/mod.rs15
-rw-r--r--src/libcore/iter/adapters/zip.rs3
-rw-r--r--src/libcore/iter/mod.rs1
-rw-r--r--src/libcore/iter/range.rs30
-rw-r--r--src/libcore/mem/manually_drop.rs9
-rw-r--r--src/libcore/mem/maybe_uninit.rs42
-rw-r--r--src/libcore/mem/mod.rs24
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) }
     }
 }