Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply unsafe_op_in_unsafe_fn to the standard library #136986

Merged
merged 8 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion library/core/src/alloc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ use crate::{cmp, ptr};
/// {
/// return null_mut();
/// };
/// self.arena.get().cast::<u8>().add(allocated)
/// unsafe { self.arena.get().cast::<u8>().add(allocated) }
/// }
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
/// }
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use crate::{intrinsics, ub_checks};
/// // Safety: `divisor` can't be zero because of `prepare_inputs`,
/// // but the compiler does not know about this. We *promise*
/// // that we always call `prepare_inputs`.
/// std::hint::unreachable_unchecked()
/// unsafe { std::hint::unreachable_unchecked() }
/// }
/// // The compiler would normally introduce a check here that prevents
/// // a division by zero. However, if `divisor` was zero, the branch
Expand Down
8 changes: 4 additions & 4 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1703,12 +1703,12 @@ pub const fn forget<T: ?Sized>(_: T) {
/// ```
/// struct R<'a>(&'a i32);
/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
/// std::mem::transmute::<R<'b>, R<'static>>(r)
/// unsafe { std::mem::transmute::<R<'b>, R<'static>>(r) }
/// }
///
/// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
/// -> &'b mut R<'c> {
/// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
/// unsafe { std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r) }
/// }
/// ```
///
Expand Down Expand Up @@ -4498,11 +4498,11 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
///
/// // SAFETY: Our precondition ensures the source is aligned and valid,
/// // and `Vec::with_capacity` ensures that we have usable space to write them.
/// ptr::copy(ptr, dst.as_mut_ptr(), elts);
/// unsafe { ptr::copy(ptr, dst.as_mut_ptr(), elts); }
///
/// // SAFETY: We created it with this much capacity earlier,
/// // and the previous `copy` has initialized these elements.
/// dst.set_len(elts);
/// unsafe { dst.set_len(elts); }
/// dst
/// }
/// ```
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ use crate::{fmt, intrinsics, ptr, slice};
///
/// unsafe fn make_vec(out: *mut Vec<i32>) {
/// // `write` does not drop the old contents, which is important.
/// out.write(vec![1, 2, 3]);
/// unsafe { out.write(vec![1, 2, 3]); }
/// }
///
/// let mut v = MaybeUninit::uninit();
Expand Down Expand Up @@ -844,7 +844,7 @@ impl<T> MaybeUninit<T> {
/// # #![allow(unexpected_cfgs)]
/// use std::mem::MaybeUninit;
///
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] }
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { unsafe { *buf = [0; 1024] } }
/// # #[cfg(FALSE)]
/// extern "C" {
/// /// Initializes *all* the bytes of the input buffer.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/mem/transmutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
/// src: ManuallyDrop::new(src),
/// };
///
/// let dst = transmute.dst;
/// let dst = unsafe { transmute.dst };
///
/// ManuallyDrop::into_inner(dst)
/// }
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,13 +724,13 @@ impl<T: ?Sized> *const T {
/// that their safety preconditions are met:
/// ```rust
/// # #![feature(ptr_sub_ptr)]
/// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool {
/// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe {
/// ptr.sub_ptr(origin) == count
/// # &&
/// origin.add(count) == ptr
/// # &&
/// ptr.sub(count) == origin
/// # }
/// # } }
/// ```
///
/// # Safety
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,13 +896,13 @@ impl<T: ?Sized> *mut T {
/// that their safety preconditions are met:
/// ```rust
/// # #![feature(ptr_sub_ptr)]
/// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool {
/// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe {
/// ptr.sub_ptr(origin) == count
/// # &&
/// origin.add(count) == ptr
/// # &&
/// ptr.sub(count) == origin
/// # }
/// # } }
/// ```
///
/// # Safety
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,13 +857,13 @@ impl<T: ?Sized> NonNull<T> {
/// that their safety preconditions are met:
/// ```rust
/// # #![feature(ptr_sub_ptr)]
/// # unsafe fn blah(ptr: std::ptr::NonNull<u32>, origin: std::ptr::NonNull<u32>, count: usize) -> bool {
/// # unsafe fn blah(ptr: std::ptr::NonNull<u32>, origin: std::ptr::NonNull<u32>, count: usize) -> bool { unsafe {
/// ptr.sub_ptr(origin) == count
/// # &&
/// origin.add(count) == ptr
/// # &&
/// ptr.sub(count) == origin
/// # }
/// # } }
/// ```
///
/// # Safety
Expand Down
18 changes: 10 additions & 8 deletions library/panic_abort/src/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> ();
// Weakly resolve the symbol for android_set_abort_message. This function is only available
// for API >= 21.
pub(crate) unsafe fn android_set_abort_message(payload: &mut dyn PanicPayload) {
let func_addr =
let func_addr = unsafe {
libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char)
as usize;
as usize
};
if func_addr == 0 {
return;
}
Expand All @@ -37,13 +38,14 @@ pub(crate) unsafe fn android_set_abort_message(payload: &mut dyn PanicPayload) {

// Allocate a new buffer to append the null byte.
let size = msg.len() + 1usize;
let buf = libc::malloc(size) as *mut libc::c_char;
let buf = unsafe { libc::malloc(size) as *mut libc::c_char };
if buf.is_null() {
return; // allocation failure
}
copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len());
buf.add(msg.len()).write(0);

let func = transmute::<usize, SetAbortMessageType>(func_addr);
func(buf);
unsafe {
copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len());
buf.add(msg.len()).write(0);
let func = transmute::<usize, SetAbortMessageType>(func_addr);
func(buf);
}
}
31 changes: 22 additions & 9 deletions library/panic_abort/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![allow(internal_features)]
#![deny(unsafe_op_in_unsafe_fn)]

#[cfg(target_os = "android")]
mod android;
Expand All @@ -36,16 +37,22 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
// Android has the ability to attach a message as part of the abort.
#[cfg(target_os = "android")]
android::android_set_abort_message(_payload);
unsafe {
android::android_set_abort_message(_payload);
}
#[cfg(target_os = "zkvm")]
zkvm::zkvm_set_abort_message(_payload);
unsafe {
zkvm::zkvm_set_abort_message(_payload);
}

abort();
unsafe {
abort();
}

cfg_if::cfg_if! {
if #[cfg(any(unix, target_os = "solid_asp3"))] {
unsafe fn abort() -> ! {
libc::abort();
unsafe { libc::abort(); }
}
} else if #[cfg(any(target_os = "hermit",
all(target_vendor = "fortanix", target_env = "sgx"),
Expand All @@ -57,7 +64,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
unsafe extern "C" {
pub fn __rust_abort() -> !;
}
__rust_abort();
unsafe { __rust_abort(); }
}
} else if #[cfg(all(windows, not(miri)))] {
// On Windows, use the processor-specific __fastfail mechanism. In Windows 8
Expand All @@ -75,11 +82,17 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
unsafe {
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
}
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
unsafe {
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
}
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
unsafe {
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
}
} else {
core::intrinsics::abort();
}
Expand All @@ -93,7 +106,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
}

unsafe fn abort() -> ! {
teeos::TEE_Panic(1);
unsafe { teeos::TEE_Panic(1); }
}
} else {
unsafe fn abort() -> ! {
Expand Down
4 changes: 3 additions & 1 deletion library/panic_abort/src/zkvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ pub(crate) unsafe fn zkvm_set_abort_message(payload: &mut dyn PanicPayload) {
fn sys_panic(msg_ptr: *const u8, len: usize) -> !;
}

sys_panic(msg.as_ptr(), msg.len());
unsafe {
sys_panic(msg.as_ptr(), msg.len());
}
}
60 changes: 32 additions & 28 deletions library/panic_unwind/src/emcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,42 +71,46 @@ pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
ptr: *mut u8,
is_rust_panic: bool,
}
let catch_data = &*(ptr as *mut CatchData);
unsafe {
let catch_data = &*(ptr as *mut CatchData);

let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
if !catch_data.is_rust_panic {
super::__rust_foreign_exception();
}
let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
if !catch_data.is_rust_panic {
super::__rust_foreign_exception();
}

let canary = (&raw const (*adjusted_ptr).canary).read();
if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
super::__rust_foreign_exception();
}
let canary = (&raw const (*adjusted_ptr).canary).read();
if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
super::__rust_foreign_exception();
}

let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::Relaxed);
if was_caught {
// Since cleanup() isn't allowed to panic, we just abort instead.
intrinsics::abort();
let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::Relaxed);
if was_caught {
// Since cleanup() isn't allowed to panic, we just abort instead.
intrinsics::abort();
}
let out = (*adjusted_ptr).data.take().unwrap();
__cxa_end_catch();
out
}
let out = (*adjusted_ptr).data.take().unwrap();
__cxa_end_catch();
out
}

pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
if exception.is_null() {
return uw::_URC_FATAL_PHASE1_ERROR as u32;
unsafe {
let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
if exception.is_null() {
return uw::_URC_FATAL_PHASE1_ERROR as u32;
}
ptr::write(
exception,
Exception {
canary: &EXCEPTION_TYPE_INFO,
caught: AtomicBool::new(false),
data: Some(data),
},
);
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
}
ptr::write(
exception,
Exception {
canary: &EXCEPTION_TYPE_INFO,
caught: AtomicBool::new(false),
data: Some(data),
},
);
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
}

extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void {
Expand Down
40 changes: 21 additions & 19 deletions library/panic_unwind/src/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
cause: data,
});
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
return uw::_Unwind_RaiseException(exception_param) as u32;
return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 };

extern "C" fn exception_cleanup(
_unwind_code: uw::_Unwind_Reason_Code,
Expand All @@ -83,26 +83,28 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
}

pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
let exception = ptr as *mut uw::_Unwind_Exception;
if (*exception).exception_class != RUST_EXCEPTION_CLASS {
uw::_Unwind_DeleteException(exception);
super::__rust_foreign_exception();
}
unsafe {
let exception = ptr as *mut uw::_Unwind_Exception;
if (*exception).exception_class != RUST_EXCEPTION_CLASS {
uw::_Unwind_DeleteException(exception);
super::__rust_foreign_exception();
}

let exception = exception.cast::<Exception>();
// Just access the canary field, avoid accessing the entire `Exception` as
// it can be a foreign Rust exception.
let canary = (&raw const (*exception).canary).read();
if !ptr::eq(canary, &CANARY) {
// A foreign Rust exception, treat it slightly differently from other
// foreign exceptions, because call into `_Unwind_DeleteException` will
// call into `__rust_drop_panic` which produces a confusing
// "Rust panic must be rethrown" message.
super::__rust_foreign_exception();
}
let exception = exception.cast::<Exception>();
// Just access the canary field, avoid accessing the entire `Exception` as
// it can be a foreign Rust exception.
let canary = (&raw const (*exception).canary).read();
if !ptr::eq(canary, &CANARY) {
// A foreign Rust exception, treat it slightly differently from other
// foreign exceptions, because call into `_Unwind_DeleteException` will
// call into `__rust_drop_panic` which produces a confusing
// "Rust panic must be rethrown" message.
super::__rust_foreign_exception();
}

let exception = Box::from_raw(exception as *mut Exception);
exception.cause
let exception = Box::from_raw(exception as *mut Exception);
exception.cause
}
}

// Rust's exception class identifier. This is used by personality routines to
Expand Down
8 changes: 6 additions & 2 deletions library/panic_unwind/src/hermit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
unsafe extern "C" {
fn __rust_abort() -> !;
}
__rust_abort();
unsafe {
__rust_abort();
}
}

pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
unsafe extern "C" {
fn __rust_abort() -> !;
}
__rust_abort();
unsafe {
__rust_abort();
}
}
Loading
Loading