Skip to content

Commit d08ca24

Browse files
LeSeulArtichautindirect
authored andcommitted
Deny unsafe ops in unsafe fns, part 5
1 parent e56f8a4 commit d08ca24

File tree

3 files changed

+108
-47
lines changed

3 files changed

+108
-47
lines changed

src/libcore/ffi.rs

Lines changed: 7 additions & 2 deletions
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

Lines changed: 101 additions & 43 deletions
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.
@@ -2581,18 +2584,21 @@ impl<T> [T] {
25812584
// First, find at what point do we split between the first and 2nd slice. Easy with
25822585
// ptr.align_offset.
25832586
let ptr = self.as_ptr();
2584-
let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
2587+
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
25852588
if offset > self.len() {
25862589
(self, &[], &[])
25872590
} else {
25882591
let (left, rest) = self.split_at(offset);
2589-
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
25902592
let (us_len, ts_len) = rest.align_to_offsets::<U>();
2591-
(
2592-
left,
2593-
from_raw_parts(rest.as_ptr() as *const U, us_len),
2594-
from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len),
2595-
)
2593+
// SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay,
2594+
// since the caller guarantees that we can transmute `T` to `U` safely.
2595+
unsafe {
2596+
(
2597+
left,
2598+
from_raw_parts(rest.as_ptr() as *const U, us_len),
2599+
from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len),
2600+
)
2601+
}
25962602
}
25972603
}
25982604

@@ -2637,21 +2643,23 @@ impl<T> [T] {
26372643
// First, find at what point do we split between the first and 2nd slice. Easy with
26382644
// ptr.align_offset.
26392645
let ptr = self.as_ptr();
2640-
let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
2646+
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
26412647
if offset > self.len() {
26422648
(self, &mut [], &mut [])
26432649
} else {
26442650
let (left, rest) = self.split_at_mut(offset);
2645-
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
26462651
let (us_len, ts_len) = rest.align_to_offsets::<U>();
26472652
let rest_len = rest.len();
26482653
let mut_ptr = rest.as_mut_ptr();
26492654
// We can't use `rest` again after this, that would invalidate its alias `mut_ptr`!
2650-
(
2651-
left,
2652-
from_raw_parts_mut(mut_ptr as *mut U, us_len),
2653-
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
2654-
)
2655+
// SAFETY: see comments for `align_to`.
2656+
unsafe {
2657+
(
2658+
left,
2659+
from_raw_parts_mut(mut_ptr as *mut U, us_len),
2660+
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
2661+
)
2662+
}
26552663
}
26562664
}
26572665

@@ -2976,12 +2984,18 @@ impl<T> SliceIndex<[T]> for usize {
29762984

29772985
#[inline]
29782986
unsafe fn get_unchecked(self, slice: &[T]) -> &T {
2979-
&*slice.as_ptr().add(self)
2987+
// SAFETY: `slice` cannot be longer than `isize::MAX` and
2988+
// the caller guarantees that `self` is in bounds of `slice`
2989+
// so `self` cannot overflow an `isize`, so the call to `add` is safe.
2990+
// The obtained pointer comes from a reference which is guaranteed
2991+
// to be valid.
2992+
unsafe { &*slice.as_ptr().add(self) }
29802993
}
29812994

29822995
#[inline]
29832996
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T {
2984-
&mut *slice.as_mut_ptr().add(self)
2997+
// SAFETY: see comments for `get_unchecked` above.
2998+
unsafe { &mut *slice.as_mut_ptr().add(self) }
29852999
}
29863000

29873001
#[inline]
@@ -3021,12 +3035,18 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
30213035

30223036
#[inline]
30233037
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3024-
from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
3038+
// SAFETY: `slice` cannot be longer than `isize::MAX` and
3039+
// the caller guarantees that `self` is in bounds of `slice`
3040+
// so `self` cannot overflow an `isize`, so the call to `add` is safe.
3041+
// Also, since the caller guarantees that `self` is in bounds of `slice`,
3042+
// `from_raw_parts` will give a subslice of `slice` which is always safe.
3043+
unsafe { from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) }
30253044
}
30263045

30273046
#[inline]
30283047
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3029-
from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
3048+
// SAFETY: see comments for `get_unchecked` above.
3049+
unsafe { from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) }
30303050
}
30313051

30323052
#[inline]
@@ -3066,12 +3086,14 @@ impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
30663086

30673087
#[inline]
30683088
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3069-
(0..self.end).get_unchecked(slice)
3089+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3090+
unsafe { (0..self.end).get_unchecked(slice) }
30703091
}
30713092

30723093
#[inline]
30733094
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3074-
(0..self.end).get_unchecked_mut(slice)
3095+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3096+
unsafe { (0..self.end).get_unchecked_mut(slice) }
30753097
}
30763098

30773099
#[inline]
@@ -3101,12 +3123,14 @@ impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
31013123

31023124
#[inline]
31033125
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3104-
(self.start..slice.len()).get_unchecked(slice)
3126+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3127+
unsafe { (self.start..slice.len()).get_unchecked(slice) }
31053128
}
31063129

31073130
#[inline]
31083131
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3109-
(self.start..slice.len()).get_unchecked_mut(slice)
3132+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3133+
unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
31103134
}
31113135

31123136
#[inline]
@@ -3175,12 +3199,14 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
31753199

31763200
#[inline]
31773201
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3178-
(*self.start()..self.end() + 1).get_unchecked(slice)
3202+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3203+
unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
31793204
}
31803205

31813206
#[inline]
31823207
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3183-
(*self.start()..self.end() + 1).get_unchecked_mut(slice)
3208+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3209+
unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
31843210
}
31853211

31863212
#[inline]
@@ -3216,12 +3242,14 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
32163242

32173243
#[inline]
32183244
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
3219-
(0..=self.end).get_unchecked(slice)
3245+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
3246+
unsafe { (0..=self.end).get_unchecked(slice) }
32203247
}
32213248

32223249
#[inline]
32233250
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
3224-
(0..=self.end).get_unchecked_mut(slice)
3251+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
3252+
unsafe { (0..=self.end).get_unchecked_mut(slice) }
32253253
}
32263254

32273255
#[inline]
@@ -3370,7 +3398,9 @@ macro_rules! iterator {
33703398
self.ptr.as_ptr()
33713399
} else {
33723400
let old = self.ptr.as_ptr();
3373-
self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().offset(offset));
3401+
// SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
3402+
// so this new pointer is inside `self` and thus guaranteed to be non-null.
3403+
self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) };
33743404
old
33753405
}
33763406
}
@@ -3384,7 +3414,10 @@ macro_rules! iterator {
33843414
zst_shrink!(self, offset);
33853415
self.ptr.as_ptr()
33863416
} else {
3387-
self.end = self.end.offset(-offset);
3417+
// SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`,
3418+
// which is guaranteed to not overflow an `isize`. Also, the resulting pointer
3419+
// is in bounds of `slice`, which fulfills the other requirements for `offset`.
3420+
self.end = unsafe { self.end.offset(-offset) };
33883421
self.end
33893422
}
33903423
}
@@ -4702,7 +4735,11 @@ impl<T> FusedIterator for Windows<'_, T> {}
47024735
#[doc(hidden)]
47034736
unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
47044737
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
4705-
from_raw_parts(self.v.as_ptr().add(i), self.size)
4738+
// SAFETY: since the caller guarantees that `i` is in bounds,
4739+
// which means that `i` cannot overflow an `isize`, and the
4740+
// slice created by `from_raw_parts` is a subslice of `self.v`
4741+
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
4742+
unsafe { from_raw_parts(self.v.as_ptr().add(i), self.size) }
47064743
}
47074744
fn may_have_side_effect() -> bool {
47084745
false
@@ -4846,7 +4883,14 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
48464883
None => self.v.len(),
48474884
Some(end) => cmp::min(end, self.v.len()),
48484885
};
4849-
from_raw_parts(self.v.as_ptr().add(start), end - start)
4886+
// SAFETY: the caller guarantees that `i` is in bounds,
4887+
// which means that `start` must be in bounds of the
4888+
// underlying `self.v` slice, and we made sure that `end`
4889+
// is also in bounds of `self.v`. Thus, `start` cannot overflow
4890+
// an `isize`, and the slice constructed by `from_raw_parts`
4891+
// is a subslice of `self.v` which is guaranteed to be valid
4892+
// for the lifetime `'a` of `self.v`.
4893+
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
48504894
}
48514895
fn may_have_side_effect() -> bool {
48524896
false
@@ -4988,7 +5032,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
49885032
None => self.v.len(),
49895033
Some(end) => cmp::min(end, self.v.len()),
49905034
};
4991-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start)
5035+
// SAFETY: see comments for `Chunks::get_unchecked`.
5036+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
49925037
}
49935038
fn may_have_side_effect() -> bool {
49945039
false
@@ -5125,7 +5170,8 @@ impl<T> FusedIterator for ChunksExact<'_, T> {}
51255170
unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
51265171
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
51275172
let start = i * self.chunk_size;
5128-
from_raw_parts(self.v.as_ptr().add(start), self.chunk_size)
5173+
// SAFETY: mostly identical to `Chunks::get_unchecked`.
5174+
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
51295175
}
51305176
fn may_have_side_effect() -> bool {
51315177
false
@@ -5259,7 +5305,8 @@ impl<T> FusedIterator for ChunksExactMut<'_, T> {}
52595305
unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
52605306
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
52615307
let start = i * self.chunk_size;
5262-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size)
5308+
// SAFETY: see comments for `ChunksExactMut::get_unchecked`.
5309+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
52635310
}
52645311
fn may_have_side_effect() -> bool {
52655312
false
@@ -5406,7 +5453,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
54065453
None => 0,
54075454
Some(start) => start,
54085455
};
5409-
from_raw_parts(self.v.as_ptr().add(start), end - start)
5456+
// SAFETY: mostly identical to `Chunks::get_unchecked`.
5457+
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
54105458
}
54115459
fn may_have_side_effect() -> bool {
54125460
false
@@ -5551,7 +5599,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
55515599
None => 0,
55525600
Some(start) => start,
55535601
};
5554-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start)
5602+
// SAFETY: see comments for `RChunks::get_unchecked`.
5603+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
55555604
}
55565605
fn may_have_side_effect() -> bool {
55575606
false
@@ -5692,7 +5741,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
56925741
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
56935742
let end = self.v.len() - i * self.chunk_size;
56945743
let start = end - self.chunk_size;
5695-
from_raw_parts(self.v.as_ptr().add(start), self.chunk_size)
5744+
// SAFETY: mostmy identical to `Chunks::get_unchecked`.
5745+
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
56965746
}
56975747
fn may_have_side_effect() -> bool {
56985748
false
@@ -5831,7 +5881,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
58315881
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
58325882
let end = self.v.len() - i * self.chunk_size;
58335883
let start = end - self.chunk_size;
5834-
from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size)
5884+
// SAFETY: see comments for `RChunksExact::get_unchecked`.
5885+
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
58355886
}
58365887
fn may_have_side_effect() -> bool {
58375888
false
@@ -5927,7 +5978,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
59275978
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
59285979
"attempt to create slice covering at least half the address space"
59295980
);
5930-
&*ptr::slice_from_raw_parts(data, len)
5981+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
5982+
unsafe { &*ptr::slice_from_raw_parts(data, len) }
59315983
}
59325984

59335985
/// Performs the same functionality as [`from_raw_parts`], except that a
@@ -5967,7 +6019,8 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T]
59676019
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
59686020
"attempt to create slice covering at least half the address space"
59696021
);
5970-
&mut *ptr::slice_from_raw_parts_mut(data, len)
6022+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
6023+
unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
59716024
}
59726025

59736026
/// Converts a reference to T into a slice of length 1 (without copying).
@@ -6243,7 +6296,11 @@ impl_marker_for!(BytewiseEquality,
62436296
#[doc(hidden)]
62446297
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
62456298
unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
6246-
&*self.ptr.as_ptr().add(i)
6299+
// SAFETY: the caller must guarantee that `i` is in bounds
6300+
// of the underlying slice, so `i` cannot overflow an `isize`,
6301+
// and the returned references is guaranteed to refer to an element
6302+
// of the slice and thus guaranteed to be valid.
6303+
unsafe { &*self.ptr.as_ptr().add(i) }
62476304
}
62486305
fn may_have_side_effect() -> bool {
62496306
false
@@ -6253,7 +6310,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
62536310
#[doc(hidden)]
62546311
unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
62556312
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
6256-
&mut *self.ptr.as_ptr().add(i)
6313+
// SAFETY: see comments for `Iter::get_unchecked`.
6314+
unsafe { &mut *self.ptr.as_ptr().add(i) }
62576315
}
62586316
fn may_have_side_effect() -> bool {
62596317
false

src/libcore/slice/rotate.rs

Lines changed: 0 additions & 2 deletions
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)