Skip to content

Commit b365233

Browse files
Deny unsafe ops in unsafe fns, part 5
1 parent c68f478 commit b365233

File tree

3 files changed

+108
-47
lines changed

3 files changed

+108
-47
lines changed

src/libcore/ffi.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![stable(feature = "", since = "1.30.0")]
22
#![allow(non_camel_case_types)]
3+
#![deny(unsafe_op_in_unsafe_fn)]
34

45
//! Utilities related to FFI bindings.
56
@@ -333,7 +334,8 @@ impl<'f> VaListImpl<'f> {
333334
/// Advance to the next arg.
334335
#[inline]
335336
pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
336-
va_arg(self)
337+
// SAFETY: the caller must uphold the safety contract for `va_arg`.
338+
unsafe { va_arg(self) }
337339
}
338340

339341
/// Copies the `va_list` at the current location.
@@ -343,7 +345,10 @@ impl<'f> VaListImpl<'f> {
343345
{
344346
let mut ap = self.clone();
345347
let ret = f(ap.as_va_list());
346-
va_end(&mut ap);
348+
// SAFETY: the caller must uphold the safety contract for `va_end`.
349+
unsafe {
350+
va_end(&mut ap);
351+
}
347352
ret
348353
}
349354
}

src/libcore/slice/mod.rs

+101-43
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! [`std::slice`]: ../../std/slice/index.html
99
1010
#![stable(feature = "rust1", since = "1.0.0")]
11+
#![deny(unsafe_op_in_unsafe_fn)]
1112

1213
// How this module is organized.
1314
//
@@ -310,7 +311,8 @@ impl<T> [T] {
310311
where
311312
I: SliceIndex<Self>,
312313
{
313-
index.get_unchecked(self)
314+
// SAFETY: the caller must uphold the safety requirements for `get_unchecked`.
315+
unsafe { index.get_unchecked(self) }
314316
}
315317

316318
/// Returns a mutable reference to an element or subslice, without doing
@@ -341,7 +343,8 @@ impl<T> [T] {
341343
where
342344
I: SliceIndex<Self>,
343345
{
344-
index.get_unchecked_mut(self)
346+
// SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`.
347+
unsafe { index.get_unchecked_mut(self) }
345348
}
346349

347350
/// Returns a raw pointer to the slice's buffer.
@@ -2519,18 +2522,21 @@ impl<T> [T] {
25192522
// First, find at what point do we split between the first and 2nd slice. Easy with
25202523
// ptr.align_offset.
25212524
let ptr = self.as_ptr();
2522-
let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
2525+
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
25232526
if offset > self.len() {
25242527
(self, &[], &[])
25252528
} else {
25262529
let (left, rest) = self.split_at(offset);
2527-
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
25282530
let (us_len, ts_len) = rest.align_to_offsets::<U>();
2529-
(
2530-
left,
2531-
from_raw_parts(rest.as_ptr() as *const U, us_len),
2532-
from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len),
2533-
)
2531+
// SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay,
2532+
// since the caller guarantees that we can transmute `T` to `U` safely.
2533+
unsafe {
2534+
(
2535+
left,
2536+
from_raw_parts(rest.as_ptr() as *const U, us_len),
2537+
from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len),
2538+
)
2539+
}
25342540
}
25352541
}
25362542

@@ -2575,21 +2581,23 @@ impl<T> [T] {
25752581
// First, find at what point do we split between the first and 2nd slice. Easy with
25762582
// ptr.align_offset.
25772583
let ptr = self.as_ptr();
2578-
let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
2584+
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
25792585
if offset > self.len() {
25802586
(self, &mut [], &mut [])
25812587
} else {
25822588
let (left, rest) = self.split_at_mut(offset);
2583-
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
25842589
let (us_len, ts_len) = rest.align_to_offsets::<U>();
25852590
let rest_len = rest.len();
25862591
let mut_ptr = rest.as_mut_ptr();
25872592
// We can't use `rest` again after this, that would invalidate its alias `mut_ptr`!
2588-
(
2589-
left,
2590-
from_raw_parts_mut(mut_ptr as *mut U, us_len),
2591-
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
2592-
)
2593+
// SAFETY: see comments for `align_to`.
2594+
unsafe {
2595+
(
2596+
left,
2597+
from_raw_parts_mut(mut_ptr as *mut U, us_len),
2598+
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
2599+
)
2600+
}
25932601
}
25942602
}
25952603

@@ -2914,12 +2922,18 @@ impl<T> SliceIndex<[T]> for usize {
29142922

29152923
#[inline]
29162924
unsafe fn get_unchecked(self, slice: &[T]) -> &T {
2917-
&*slice.as_ptr().add(self)
2925+
// SAFETY: `slice` cannot be longer than `isize::MAX` and
2926+
// the caller guarantees that `self` is in bounds of `slice`
2927+
// so `self` cannot overflow an `isize`, so the call to `add` is safe.
2928+
// The obtained pointer comes from a reference which is guaranteed
2929+
// to be valid.
2930+
unsafe { &*slice.as_ptr().add(self) }
29182931
}
29192932

29202933
#[inline]
29212934
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T {
2922-
&mut *slice.as_mut_ptr().add(self)
2935+
// SAFETY: see comments for `get_unchecked` above.
2936+
unsafe { &mut *slice.as_mut_ptr().add(self) }
29232937
}
29242938

29252939
#[inline]
@@ -2959,12 +2973,18 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
29592973

29602974
#[inline]
29612975
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
2962-
from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
2976+
// SAFETY: `slice` cannot be longer than `isize::MAX` and
2977+
// the caller guarantees that `self` is in bounds of `slice`
2978+
// so `self` cannot overflow an `isize`, so the call to `add` is safe.
2979+
// Also, since the caller guarantees that `self` is in bounds of `slice`,
2980+
// `from_raw_parts` will give a subslice of `slice` which is always safe.
2981+
unsafe { from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) }
29632982
}
29642983

29652984
#[inline]
29662985
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
2967-
from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
2986+
// SAFETY: see comments for `get_unchecked` above.
2987+
unsafe { from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) }
29682988
}
29692989

29702990
#[inline]
@@ -3004,12 +3024,14 @@ impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
30043024

30053025
#[inline]
30063026
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3007-
(0..self.end).get_unchecked(slice)
3027+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3028+
unsafe { (0..self.end).get_unchecked(slice) }
30083029
}
30093030

30103031
#[inline]
30113032
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3012-
(0..self.end).get_unchecked_mut(slice)
3033+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3034+
unsafe { (0..self.end).get_unchecked_mut(slice) }
30133035
}
30143036

30153037
#[inline]
@@ -3039,12 +3061,14 @@ impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
30393061

30403062
#[inline]
30413063
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3042-
(self.start..slice.len()).get_unchecked(slice)
3064+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3065+
unsafe { (self.start..slice.len()).get_unchecked(slice) }
30433066
}
30443067

30453068
#[inline]
30463069
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3047-
(self.start..slice.len()).get_unchecked_mut(slice)
3070+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3071+
unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
30483072
}
30493073

30503074
#[inline]
@@ -3113,12 +3137,14 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
31133137

31143138
#[inline]
31153139
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3116-
(*self.start()..self.end() + 1).get_unchecked(slice)
3140+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3141+
unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
31173142
}
31183143

31193144
#[inline]
31203145
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3121-
(*self.start()..self.end() + 1).get_unchecked_mut(slice)
3146+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3147+
unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
31223148
}
31233149

31243150
#[inline]
@@ -3154,12 +3180,14 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
31543180

31553181
#[inline]
31563182
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3157-
(0..=self.end).get_unchecked(slice)
3183+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3184+
unsafe { (0..=self.end).get_unchecked(slice) }
31583185
}
31593186

31603187
#[inline]
31613188
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3162-
(0..=self.end).get_unchecked_mut(slice)
3189+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3190+
unsafe { (0..=self.end).get_unchecked_mut(slice) }
31633191
}
31643192

31653193
#[inline]
@@ -3308,7 +3336,9 @@ macro_rules! iterator {
33083336
self.ptr.as_ptr()
33093337
} else {
33103338
let old = self.ptr.as_ptr();
3311-
self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().offset(offset));
3339+
// SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
3340+
// so this new pointer is inside `self` and thus guaranteed to be non-null.
3341+
self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) };
33123342
old
33133343
}
33143344
}
@@ -3322,7 +3352,10 @@ macro_rules! iterator {
33223352
zst_shrink!(self, offset);
33233353
self.ptr.as_ptr()
33243354
} else {
3325-
self.end = self.end.offset(-offset);
3355+
// SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
3356+
// which is guaranteed to not overflow an `isize`. Also, the resulting pointer
3357+
// is in bounds of `slice`, which fulfills the other requirements for `offset`.
3358+
self.end = unsafe { self.end.offset(-offset) };
33263359
self.end
33273360
}
33283361
}
@@ -4640,7 +4673,11 @@ impl<T> FusedIterator for Windows<'_, T> {}
46404673
#[doc(hidden)]
46414674
unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
46424675
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
4643-
from_raw_parts(self.v.as_ptr().add(i), self.size)
4676+
// SAFETY: since the caller guarantees that `i` is in bounds,
4677+
// which means that `i` cannot overflow an `isize`, and the
4678+
// slice created by `from_raw_parts` is a subslice of `self.v`
4679+
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
4680+
unsafe { from_raw_parts(self.v.as_ptr().add(i), self.size) }
46444681
}
46454682
fn may_have_side_effect() -> bool {
46464683
false
@@ -4784,7 +4821,14 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
47844821
None => self.v.len(),
47854822
Some(end) => cmp::min(end, self.v.len()),
47864823
};
4787-
from_raw_parts(self.v.as_ptr().add(start), end - start)
4824+
// SAFETY: the caller guarantees that `i` is in bounds,
4825+
// which means that `start` must be in bounds of the
4826+
// underlying `self.v` slice, and we made sure that `end`
4827+
// is also in bounds of `self.v`. Thus, `start` cannot overflow
4828+
// an `isize`, and the slice constructed by `from_raw_parts`
4829+
// is a subslice of `self.v` which is guaranteed to be valid
4830+
// for the lifetime `'a` of `self.v`.
4831+
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
47884832
}
47894833
fn may_have_side_effect() -> bool {
47904834
false
@@ -4926,7 +4970,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
49264970
None => self.v.len(),
49274971
Some(end) => cmp::min(end, self.v.len()),
49284972
};
4929-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start)
4973+
// SAFETY: see comments for `Chunks::get_unchecked`.
4974+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
49304975
}
49314976
fn may_have_side_effect() -> bool {
49324977
false
@@ -5063,7 +5108,8 @@ impl<T> FusedIterator for ChunksExact<'_, T> {}
50635108
unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
50645109
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
50655110
let start = i * self.chunk_size;
5066-
from_raw_parts(self.v.as_ptr().add(start), self.chunk_size)
5111+
// SAFETY: mostly identical to `Chunks::get_unchecked`.
5112+
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
50675113
}
50685114
fn may_have_side_effect() -> bool {
50695115
false
@@ -5197,7 +5243,8 @@ impl<T> FusedIterator for ChunksExactMut<'_, T> {}
51975243
unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
51985244
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
51995245
let start = i * self.chunk_size;
5200-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size)
5246+
// SAFETY: see comments for `ChunksExactMut::get_unchecked`.
5247+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
52015248
}
52025249
fn may_have_side_effect() -> bool {
52035250
false
@@ -5344,7 +5391,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
53445391
None => 0,
53455392
Some(start) => start,
53465393
};
5347-
from_raw_parts(self.v.as_ptr().add(start), end - start)
5394+
// SAFETY: mostly identical to `Chunks::get_unchecked`.
5395+
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
53485396
}
53495397
fn may_have_side_effect() -> bool {
53505398
false
@@ -5489,7 +5537,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
54895537
None => 0,
54905538
Some(start) => start,
54915539
};
5492-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start)
5540+
// SAFETY: see comments for `RChunks::get_unchecked`.
5541+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
54935542
}
54945543
fn may_have_side_effect() -> bool {
54955544
false
@@ -5630,7 +5679,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
56305679
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
56315680
let end = self.v.len() - i * self.chunk_size;
56325681
let start = end - self.chunk_size;
5633-
from_raw_parts(self.v.as_ptr().add(start), self.chunk_size)
5682+
// SAFETY: mostmy identical to `Chunks::get_unchecked`.
5683+
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
56345684
}
56355685
fn may_have_side_effect() -> bool {
56365686
false
@@ -5769,7 +5819,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
57695819
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
57705820
let end = self.v.len() - i * self.chunk_size;
57715821
let start = end - self.chunk_size;
5772-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size)
5822+
// SAFETY: see comments for `RChunksExact::get_unchecked`.
5823+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
57735824
}
57745825
fn may_have_side_effect() -> bool {
57755826
false
@@ -5865,7 +5916,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
58655916
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
58665917
"attempt to create slice covering at least half the address space"
58675918
);
5868-
&*ptr::slice_from_raw_parts(data, len)
5919+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
5920+
unsafe { &*ptr::slice_from_raw_parts(data, len) }
58695921
}
58705922

58715923
/// 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]
59055957
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
59065958
"attempt to create slice covering at least half the address space"
59075959
);
5908-
&mut *ptr::slice_from_raw_parts_mut(data, len)
5960+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
5961+
unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
59095962
}
59105963

59115964
/// Converts a reference to T into a slice of length 1 (without copying).
@@ -6181,7 +6234,11 @@ impl_marker_for!(BytewiseEquality,
61816234
#[doc(hidden)]
61826235
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
61836236
unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
6184-
&*self.ptr.as_ptr().add(i)
6237+
// SAFETY: the caller must guarantee that `i` is in bounds
6238+
// of the underlying slice, so `i` cannot overflow an `isize`,
6239+
// and the returned references is guaranteed to refer to an element
6240+
// of the slice and thus guaranteed to be valid.
6241+
unsafe { &*self.ptr.as_ptr().add(i) }
61856242
}
61866243
fn may_have_side_effect() -> bool {
61876244
false
@@ -6191,7 +6248,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
61916248
#[doc(hidden)]
61926249
unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
61936250
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
6194-
&mut *self.ptr.as_ptr().add(i)
6251+
// SAFETY: see comments for `Iter::get_unchecked`.
6252+
unsafe { &mut *self.ptr.as_ptr().add(i) }
61956253
}
61966254
fn may_have_side_effect() -> bool {
61976255
false

src/libcore/slice/rotate.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// ignore-tidy-undocumented-unsafe
22

3-
#![deny(unsafe_op_in_unsafe_fn)]
4-
53
use crate::cmp;
64
use crate::mem::{self, MaybeUninit};
75
use crate::ptr;

0 commit comments

Comments
 (0)