diff --git a/Cargo.toml b/Cargo.toml index e352032de5..a667b737f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,6 +189,9 @@ wasm-bindgen = "0.2.100" [workspace.lints.rust] unsafe_code = "allow" +unsafe_op_in_unsafe_fn = "deny" +missing_unsafe_on_extern = "deny" +unsafe_attr_outside_unsafe = "deny" [workspace.lints.clippy] perf = "warn" diff --git a/common/src/boxvec.rs b/common/src/boxvec.rs index 9b73fa0103..3b1f7e90a0 100644 --- a/common/src/boxvec.rs +++ b/common/src/boxvec.rs @@ -87,13 +87,16 @@ impl BoxVec { pub unsafe fn push_unchecked(&mut self, element: T) { let len = self.len(); debug_assert!(len < self.capacity()); - ptr::write(self.get_unchecked_ptr(len), element); - self.set_len(len + 1); + // SAFETY: len < capacity + unsafe { + ptr::write(self.get_unchecked_ptr(len), element); + self.set_len(len + 1); + } } /// Get pointer to where element at `index` would be unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { - self.xs.as_mut_ptr().add(index).cast() + unsafe { self.xs.as_mut_ptr().add(index).cast() } } pub fn insert(&mut self, index: usize, element: T) { @@ -568,7 +571,7 @@ unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { // Special case for ZST (ptr as usize).wrapping_add(offset) as _ } else { - ptr.add(offset) + unsafe { ptr.add(offset) } } } @@ -576,7 +579,7 @@ unsafe fn raw_ptr_write(ptr: *mut T, value: T) { if mem::size_of::() == 0 { /* nothing */ } else { - ptr::write(ptr, value) + unsafe { ptr::write(ptr, value) } } } diff --git a/common/src/crt_fd.rs b/common/src/crt_fd.rs index 14f61b8059..64d4df98a5 100644 --- a/common/src/crt_fd.rs +++ b/common/src/crt_fd.rs @@ -6,7 +6,7 @@ use std::{cmp, ffi, io}; #[cfg(windows)] use libc::commit as fsync; #[cfg(windows)] -extern "C" { +unsafe extern "C" { #[link_name = "_chsize_s"] fn ftruncate(fd: i32, len: i64) -> i32; } @@ -74,7 +74,7 @@ impl Fd { #[cfg(windows)] pub fn to_raw_handle(&self) -> io::Result { - extern "C" { + unsafe extern "C" { fn _get_osfhandle(fd: i32) -> libc::intptr_t; } let handle = unsafe { suppress_iph!(_get_osfhandle(self.0)) }; diff --git a/common/src/encodings.rs b/common/src/encodings.rs index 4e0c1de56a..858d3b8c6b 100644 --- a/common/src/encodings.rs +++ b/common/src/encodings.rs @@ -42,8 +42,8 @@ struct DecodeError<'a> { /// # Safety /// `v[..valid_up_to]` must be valid utf8 unsafe fn make_decode_err(v: &[u8], valid_up_to: usize, err_len: Option) -> DecodeError<'_> { - let valid_prefix = core::str::from_utf8_unchecked(v.get_unchecked(..valid_up_to)); - let rest = v.get_unchecked(valid_up_to..); + let (valid_prefix, rest) = unsafe { v.split_at_unchecked(valid_up_to) }; + let valid_prefix = unsafe { core::str::from_utf8_unchecked(valid_prefix) }; DecodeError { valid_prefix, rest, diff --git a/common/src/fileutils.rs b/common/src/fileutils.rs index dcb78675d8..8713e11229 100644 --- a/common/src/fileutils.rs +++ b/common/src/fileutils.rs @@ -94,7 +94,7 @@ pub mod windows { } } - extern "C" { + unsafe extern "C" { fn _get_osfhandle(fd: i32) -> libc::intptr_t; } diff --git a/common/src/linked_list.rs b/common/src/linked_list.rs index 3040bab0b9..7f55d727fb 100644 --- a/common/src/linked_list.rs +++ b/common/src/linked_list.rs @@ -208,37 +208,39 @@ impl LinkedList { /// The caller **must** ensure that `node` is currently contained by /// `self` or not contained by any other list. pub unsafe fn remove(&mut self, node: NonNull) -> Option { - if let Some(prev) = L::pointers(node).as_ref().get_prev() { - debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node)); - L::pointers(prev) - .as_mut() - .set_next(L::pointers(node).as_ref().get_next()); - } else { - if self.head != Some(node) { - return None; + unsafe { + if let Some(prev) = L::pointers(node).as_ref().get_prev() { + debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node)); + L::pointers(prev) + .as_mut() + .set_next(L::pointers(node).as_ref().get_next()); + } else { + if self.head != Some(node) { + return None; + } + + self.head = L::pointers(node).as_ref().get_next(); } - self.head = L::pointers(node).as_ref().get_next(); + if let Some(next) = L::pointers(node).as_ref().get_next() { + debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node)); + L::pointers(next) + .as_mut() + .set_prev(L::pointers(node).as_ref().get_prev()); + } else { + // // This might be the last item in the list + // if self.tail != Some(node) { + // return None; + // } + + // self.tail = L::pointers(node).as_ref().get_prev(); + } + + L::pointers(node).as_mut().set_next(None); + L::pointers(node).as_mut().set_prev(None); + + Some(L::from_raw(node)) } - - if let Some(next) = L::pointers(node).as_ref().get_next() { - debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node)); - L::pointers(next) - .as_mut() - .set_prev(L::pointers(node).as_ref().get_prev()); - } else { - // // This might be the last item in the list - // if self.tail != Some(node) { - // return None; - // } - - // self.tail = L::pointers(node).as_ref().get_prev(); - } - - L::pointers(node).as_mut().set_next(None); - L::pointers(node).as_mut().set_prev(None); - - Some(L::from_raw(node)) } // pub fn last(&self) -> Option<&L::Target> { diff --git a/common/src/lock/cell_lock.rs b/common/src/lock/cell_lock.rs index b10101f269..1edd622a20 100644 --- a/common/src/lock/cell_lock.rs +++ b/common/src/lock/cell_lock.rs @@ -140,12 +140,12 @@ unsafe impl RawRwLockUpgrade for RawCellRwLock { #[inline] unsafe fn unlock_upgradable(&self) { - self.unlock_shared() + unsafe { self.unlock_shared() } } #[inline] unsafe fn upgrade(&self) { - if !self.try_upgrade() { + if !unsafe { self.try_upgrade() } { deadlock("upgrade ", "RwLock") } } diff --git a/common/src/lock/thread_mutex.rs b/common/src/lock/thread_mutex.rs index ba36898780..35b0b9ac6d 100644 --- a/common/src/lock/thread_mutex.rs +++ b/common/src/lock/thread_mutex.rs @@ -65,7 +65,7 @@ impl RawThreadMutex { /// This method may only be called if the mutex is held by the current thread. pub unsafe fn unlock(&self) { self.owner.store(0, Ordering::Relaxed); - self.mutex.unlock(); + unsafe { self.mutex.unlock() }; } } diff --git a/common/src/macros.rs b/common/src/macros.rs index 318ab06986..08d00e592d 100644 --- a/common/src/macros.rs +++ b/common/src/macros.rs @@ -41,7 +41,7 @@ pub mod __macro_private { libc::uintptr_t, ); #[cfg(target_env = "msvc")] - extern "C" { + unsafe extern "C" { pub fn _set_thread_local_invalid_parameter_handler( pNew: InvalidParamHandler, ) -> InvalidParamHandler; diff --git a/common/src/os.rs b/common/src/os.rs index c16ec014c5..8a832270bc 100644 --- a/common/src/os.rs +++ b/common/src/os.rs @@ -23,7 +23,7 @@ pub fn last_os_error() -> io::Error { let err = io::Error::last_os_error(); // FIXME: probably not ideal, we need a bigger dichotomy between GetLastError and errno if err.raw_os_error() == Some(0) { - extern "C" { + unsafe extern "C" { fn _get_errno(pValue: *mut i32) -> i32; } let mut errno = 0; @@ -44,7 +44,7 @@ pub fn last_os_error() -> io::Error { pub fn last_posix_errno() -> i32 { let err = io::Error::last_os_error(); if err.raw_os_error() == Some(0) { - extern "C" { + unsafe extern "C" { fn _get_errno(pValue: *mut i32) -> i32; } let mut errno = 0; diff --git a/compiler/core/src/bytecode.rs b/compiler/core/src/bytecode.rs index 21d342b541..11e49a47db 100644 --- a/compiler/core/src/bytecode.rs +++ b/compiler/core/src/bytecode.rs @@ -293,10 +293,8 @@ impl Arg { /// # Safety /// T::from_op_arg(self) must succeed pub unsafe fn get_unchecked(self, arg: OpArg) -> T { - match T::from_op_arg(arg.0) { - Some(t) => t, - None => std::hint::unreachable_unchecked(), - } + // SAFETY: requirements forwarded from caller + unsafe { T::from_op_arg(arg.0).unwrap_unchecked() } } } diff --git a/jit/src/lib.rs b/jit/src/lib.rs index 99bfb45c78..78619eaf62 100644 --- a/jit/src/lib.rs +++ b/jit/src/lib.rs @@ -152,12 +152,14 @@ impl CompiledCode { } unsafe fn invoke_raw(&self, cif_args: &[libffi::middle::Arg]) -> Option { - let cif = self.sig.to_cif(); - let value = cif.call::( - libffi::middle::CodePtr::from_ptr(self.code as *const _), - cif_args, - ); - self.sig.ret.as_ref().map(|ty| value.to_typed(ty)) + unsafe { + let cif = self.sig.to_cif(); + let value = cif.call::( + libffi::middle::CodePtr::from_ptr(self.code as *const _), + cif_args, + ); + self.sig.ret.as_ref().map(|ty| value.to_typed(ty)) + } } } @@ -290,10 +292,12 @@ union UnTypedAbiValue { impl UnTypedAbiValue { unsafe fn to_typed(self, ty: &JitType) -> AbiValue { - match ty { - JitType::Int => AbiValue::Int(self.int), - JitType::Float => AbiValue::Float(self.float), - JitType::Bool => AbiValue::Bool(self.boolean != 0), + unsafe { + match ty { + JitType::Int => AbiValue::Int(self.int), + JitType::Float => AbiValue::Float(self.float), + JitType::Bool => AbiValue::Bool(self.boolean != 0), + } } } } diff --git a/src/lib.rs b/src/lib.rs index 0e35a6ad83..9fa38b968c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static) -> ExitCode { // don't translate newlines (\r\n <=> \n) #[cfg(windows)] { - extern "C" { + unsafe extern "C" { fn _setmode(fd: i32, flags: i32) -> i32; } unsafe { diff --git a/stdlib/src/locale.rs b/stdlib/src/locale.rs index bbe1008e53..8e44508fb6 100644 --- a/stdlib/src/locale.rs +++ b/stdlib/src/locale.rs @@ -30,7 +30,7 @@ struct lconv { } #[cfg(windows)] -extern "C" { +unsafe extern "C" { fn localeconv() -> *mut lconv; } @@ -78,11 +78,13 @@ mod _locale { return vm.ctx.new_list(group_vec); } - let mut ptr = group; - while ![0, libc::c_char::MAX].contains(&*ptr) { - let val = vm.ctx.new_int(*ptr); - group_vec.push(val.into()); - ptr = ptr.add(1); + unsafe { + let mut ptr = group; + while ![0, libc::c_char::MAX].contains(&*ptr) { + let val = vm.ctx.new_int(*ptr); + group_vec.push(val.into()); + ptr = ptr.add(1); + } } // https://github.com/python/cpython/blob/677320348728ce058fa3579017e985af74a236d4/Modules/_localemodule.c#L80 if !group_vec.is_empty() { diff --git a/stdlib/src/select.rs b/stdlib/src/select.rs index af76d86c8a..6554064d53 100644 --- a/stdlib/src/select.rs +++ b/stdlib/src/select.rs @@ -36,28 +36,30 @@ mod platform { // based off winsock2.h: https://gist.github.com/piscisaureus/906386#file-winsock2-h-L128-L141 pub unsafe fn FD_SET(fd: RawFd, set: *mut fd_set) { - let mut slot = (&raw mut (*set).fd_array).cast::(); - let fd_count = (*set).fd_count; - for _ in 0..fd_count { - if *slot == fd { - return; + unsafe { + let mut slot = (&raw mut (*set).fd_array).cast::(); + let fd_count = (*set).fd_count; + for _ in 0..fd_count { + if *slot == fd { + return; + } + slot = slot.add(1); + } + // slot == &fd_array[fd_count] at this point + if fd_count < FD_SETSIZE { + *slot = fd as RawFd; + (*set).fd_count += 1; } - slot = slot.add(1); - } - // slot == &fd_array[fd_count] at this point - if fd_count < FD_SETSIZE { - *slot = fd as RawFd; - (*set).fd_count += 1; } } pub unsafe fn FD_ZERO(set: *mut fd_set) { - (*set).fd_count = 0; + unsafe { (*set).fd_count = 0 }; } pub unsafe fn FD_ISSET(fd: RawFd, set: *mut fd_set) -> bool { use WinSock::__WSAFDIsSet; - __WSAFDIsSet(fd as _, set) != 0 + unsafe { __WSAFDIsSet(fd as _, set) != 0 } } pub fn check_err(x: i32) -> bool { @@ -82,7 +84,7 @@ mod platform { #[allow(non_snake_case)] pub unsafe fn FD_ISSET(fd: RawFd, set: *const fd_set) -> bool { - let set = &*set; + let set = unsafe { &*set }; let n = set.__nfds; for p in &set.__fds[..n] { if *p == fd { @@ -94,7 +96,7 @@ mod platform { #[allow(non_snake_case)] pub unsafe fn FD_SET(fd: RawFd, set: *mut fd_set) { - let set = &mut *set; + let set = unsafe { &mut *set }; let n = set.__nfds; for p in &set.__fds[..n] { if *p == fd { @@ -107,11 +109,11 @@ mod platform { #[allow(non_snake_case)] pub unsafe fn FD_ZERO(set: *mut fd_set) { - let set = &mut *set; + let set = unsafe { &mut *set }; set.__nfds = 0; } - extern "C" { + unsafe extern "C" { pub fn select( nfds: libc::c_int, readfds: *mut fd_set, diff --git a/stdlib/src/socket.rs b/stdlib/src/socket.rs index bf2f5ecd30..4172c5bb35 100644 --- a/stdlib/src/socket.rs +++ b/stdlib/src/socket.rs @@ -1788,7 +1788,7 @@ mod _socket { } unsafe fn slice_as_uninit(v: &mut [T]) -> &mut [MaybeUninit] { - &mut *(v as *mut [T] as *mut [MaybeUninit]) + unsafe { &mut *(v as *mut [T] as *mut [MaybeUninit]) } } enum IoOrPyException { @@ -2312,12 +2312,12 @@ mod _socket { #[cfg(unix)] { use std::os::unix::io::FromRawFd; - Socket::from_raw_fd(fileno) + unsafe { Socket::from_raw_fd(fileno) } } #[cfg(windows)] { use std::os::windows::io::FromRawSocket; - Socket::from_raw_socket(fileno) + unsafe { Socket::from_raw_socket(fileno) } } } pub(super) fn sock_fileno(sock: &Socket) -> RawSocket { diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 6cb3deae7d..9225ccbc50 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -76,7 +76,7 @@ mod _sqlite { ffi::{c_int, c_longlong, c_uint, c_void, CStr}, fmt::Debug, ops::Deref, - ptr::{null, null_mut}, + ptr::{null, null_mut, NonNull}, thread::ThreadId, }; @@ -381,7 +381,7 @@ mod _sqlite { } struct CallbackData { - obj: *const PyObject, + obj: NonNull, vm: *const VirtualMachine, } @@ -394,11 +394,11 @@ mod _sqlite { } fn retrieve(&self) -> (&PyObject, &VirtualMachine) { - unsafe { (&*self.obj, &*self.vm) } + unsafe { (self.obj.as_ref(), &*self.vm) } } unsafe extern "C" fn destructor(data: *mut c_void) { - drop(Box::from_raw(data.cast::())); + drop(unsafe { Box::from_raw(data.cast::()) }); } unsafe extern "C" fn func_callback( @@ -407,8 +407,8 @@ mod _sqlite { argv: *mut *mut sqlite3_value, ) { let context = SqliteContext::from(context); - let (func, vm) = (*context.user_data::()).retrieve(); - let args = std::slice::from_raw_parts(argv, argc as usize); + let (func, vm) = unsafe { (*context.user_data::()).retrieve() }; + let args = unsafe { std::slice::from_raw_parts(argv, argc as usize) }; let f = || -> PyResult<()> { let db = context.db_handle(); @@ -434,12 +434,12 @@ mod _sqlite { argv: *mut *mut sqlite3_value, ) { let context = SqliteContext::from(context); - let (cls, vm) = (*context.user_data::()).retrieve(); - let args = std::slice::from_raw_parts(argv, argc as usize); + let (cls, vm) = unsafe { (*context.user_data::()).retrieve() }; + let args = unsafe { std::slice::from_raw_parts(argv, argc as usize) }; let instance = context.aggregate_context::<*const PyObject>(); - if (*instance).is_null() { + if unsafe { (*instance).is_null() } { match cls.call((), vm) { - Ok(obj) => *instance = obj.into_raw(), + Ok(obj) => unsafe { *instance = obj.into_raw().as_ptr() }, Err(exc) => { return context.result_exception( vm, @@ -449,16 +449,16 @@ mod _sqlite { } } } - let instance = &**instance; + let instance = unsafe { &**instance }; Self::call_method_with_args(context, instance, "step", args, vm); } unsafe extern "C" fn finalize_callback(context: *mut sqlite3_context) { let context = SqliteContext::from(context); - let (_, vm) = (*context.user_data::()).retrieve(); + let (_, vm) = unsafe { (*context.user_data::()).retrieve() }; let instance = context.aggregate_context::<*const PyObject>(); - let Some(instance) = (*instance).as_ref() else { + let Some(instance) = (unsafe { (*instance).as_ref() }) else { return; }; @@ -472,7 +472,7 @@ mod _sqlite { b_len: c_int, b_ptr: *const c_void, ) -> c_int { - let (callable, vm) = (*data.cast::()).retrieve(); + let (callable, vm) = unsafe { (*data.cast::()).retrieve() }; let f = || -> PyResult { let text1 = ptr_to_string(a_ptr.cast(), a_len, null_mut(), vm)?; @@ -499,9 +499,9 @@ mod _sqlite { unsafe extern "C" fn value_callback(context: *mut sqlite3_context) { let context = SqliteContext::from(context); - let (_, vm) = (*context.user_data::()).retrieve(); + let (_, vm) = unsafe { (*context.user_data::()).retrieve() }; let instance = context.aggregate_context::<*const PyObject>(); - let instance = &**instance; + let instance = unsafe { &**instance }; Self::callback_result_from_method(context, instance, "value", vm); } @@ -512,10 +512,10 @@ mod _sqlite { argv: *mut *mut sqlite3_value, ) { let context = SqliteContext::from(context); - let (_, vm) = (*context.user_data::()).retrieve(); - let args = std::slice::from_raw_parts(argv, argc as usize); + let (_, vm) = unsafe { (*context.user_data::()).retrieve() }; + let args = unsafe { std::slice::from_raw_parts(argv, argc as usize) }; let instance = context.aggregate_context::<*const PyObject>(); - let instance = &**instance; + let instance = unsafe { &**instance }; Self::call_method_with_args(context, instance, "inverse", args, vm); } @@ -528,7 +528,7 @@ mod _sqlite { db_name: *const libc::c_char, access: *const libc::c_char, ) -> c_int { - let (callable, vm) = (*data.cast::()).retrieve(); + let (callable, vm) = unsafe { (*data.cast::()).retrieve() }; let f = || -> PyResult { let arg1 = ptr_to_str(arg1, vm)?; let arg2 = ptr_to_str(arg2, vm)?; @@ -551,8 +551,8 @@ mod _sqlite { stmt: *mut c_void, sql: *mut c_void, ) -> c_int { - let (callable, vm) = (*data.cast::()).retrieve(); - let expanded = sqlite3_expanded_sql(stmt.cast()); + let (callable, vm) = unsafe { (*data.cast::()).retrieve() }; + let expanded = unsafe { sqlite3_expanded_sql(stmt.cast()) }; let f = || -> PyResult<()> { let stmt = ptr_to_str(expanded, vm).or_else(|_| ptr_to_str(sql.cast(), vm))?; callable.call((stmt,), vm)?; @@ -563,7 +563,7 @@ mod _sqlite { } unsafe extern "C" fn progress_callback(data: *mut c_void) -> c_int { - let (callable, vm) = (*data.cast::()).retrieve(); + let (callable, vm) = unsafe { (*data.cast::()).retrieve() }; if let Ok(val) = callable.call((), vm) { if let Ok(val) = val.is_true(vm) { return val as c_int; diff --git a/stdlib/src/ssl.rs b/stdlib/src/ssl.rs index 3622b74d1a..eb757f9a71 100644 --- a/stdlib/src/ssl.rs +++ b/stdlib/src/ssl.rs @@ -4,7 +4,8 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { // if openssl is vendored, it doesn't know the locations of system certificates #[cfg(feature = "ssl-vendor")] if let None | Some("0") = option_env!("OPENSSL_NO_VENDOR") { - openssl_probe::init_ssl_cert_env_vars(); + // TODO: use openssl_probe::probe() instead + unsafe { openssl_probe::init_openssl_env_vars() }; } openssl::init(); _ssl::make_module(vm) @@ -283,7 +284,7 @@ mod _ssl { if ptr.is_null() { None } else { - Some(Asn1Object::from_ptr(ptr)) + Some(unsafe { Asn1Object::from_ptr(ptr) }) } } diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index f5a340836c..f37a004297 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -313,7 +313,7 @@ impl PyStr { /// # Safety /// Given `bytes` must be ascii pub unsafe fn new_ascii_unchecked(bytes: Vec) -> Self { - Self::new_str_unchecked(bytes, PyStrKind::Ascii) + unsafe { Self::new_str_unchecked(bytes, PyStrKind::Ascii) } } pub fn new_ref(zelf: impl Into, ctx: &Context) -> PyRef { diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index 15df5ff3c5..c3fc28cd60 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -69,7 +69,7 @@ pub struct PointerSlot(NonNull); impl PointerSlot { pub unsafe fn borrow_static(&self) -> &'static T { - self.0.as_ref() + unsafe { self.0.as_ref() } } } diff --git a/vm/src/function/method.rs b/vm/src/function/method.rs index c8652ffb50..adf53d7d93 100644 --- a/vm/src/function/method.rs +++ b/vm/src/function/method.rs @@ -274,7 +274,7 @@ impl HeapMethodDef { impl Py { pub(crate) unsafe fn method(&self) -> &'static PyMethodDef { - &*(&self.method as *const _) + unsafe { &*(&self.method as *const _) } } pub fn build_function(&self, vm: &VirtualMachine) -> PyRef { diff --git a/vm/src/intern.rs b/vm/src/intern.rs index 45bd45d965..5bb657f222 100644 --- a/vm/src/intern.rs +++ b/vm/src/intern.rs @@ -117,7 +117,7 @@ impl CachedPyStrRef { /// the given cache must be alive while returned reference is alive #[inline] unsafe fn as_interned_str(&self) -> &'static PyStrInterned { - std::mem::transmute_copy(self) + unsafe { std::mem::transmute_copy(self) } } #[inline] diff --git a/vm/src/object/core.rs b/vm/src/object/core.rs index b326935464..61c31a02e3 100644 --- a/vm/src/object/core.rs +++ b/vm/src/object/core.rs @@ -77,19 +77,19 @@ use std::{ pub(super) struct Erased; pub(super) unsafe fn drop_dealloc_obj(x: *mut PyObject) { - drop(Box::from_raw(x as *mut PyInner)); + drop(unsafe { Box::from_raw(x as *mut PyInner) }); } pub(super) unsafe fn debug_obj( x: &PyObject, f: &mut fmt::Formatter, ) -> fmt::Result { - let x = &*(x as *const PyObject as *const PyInner); + let x = unsafe { &*(x as *const PyObject as *const PyInner) }; fmt::Debug::fmt(x, f) } /// Call `try_trace` on payload pub(super) unsafe fn try_trace_obj(x: &PyObject, tracer_fn: &mut TraverseFn) { - let x = &*(x as *const PyObject as *const PyInner); + let x = unsafe { &*(x as *const PyObject as *const PyInner) }; let payload = &x.payload; payload.try_traverse(tracer_fn) } @@ -278,7 +278,7 @@ impl WeakRefList { } unsafe fn dealloc(ptr: NonNull>) { - drop(Box::from_raw(ptr.as_ptr())); + drop(unsafe { Box::from_raw(ptr.as_ptr()) }); } fn get_weak_references(&self) -> Vec> { @@ -317,12 +317,14 @@ unsafe impl Link for WeakLink { #[inline(always)] unsafe fn from_raw(ptr: NonNull) -> Self::Handle { - PyRef::from_raw(ptr.as_ptr()) + // SAFETY: requirements forwarded from caller + unsafe { PyRef::from_raw(ptr.as_ptr()) } } #[inline(always)] unsafe fn pointers(target: NonNull) -> NonNull> { - NonNull::new_unchecked(&raw mut (*target.as_ptr()).0.payload.pointers) + // SAFETY: requirements forwarded from caller + unsafe { NonNull::new_unchecked(&raw mut (*target.as_ptr()).0.payload.pointers) } } } @@ -352,7 +354,7 @@ impl PyWeak { if !obj_ptr.as_ref().0.ref_count.safe_inc() { return None; } - Some(PyObjectRef::from_raw(obj_ptr.as_ptr())) + Some(PyObjectRef::from_raw(obj_ptr)) } } @@ -506,8 +508,8 @@ impl ToOwned for PyObject { impl PyObjectRef { #[inline(always)] - pub fn into_raw(self) -> *const PyObject { - let ptr = self.as_raw(); + pub fn into_raw(self) -> NonNull { + let ptr = self.ptr; std::mem::forget(self); ptr } @@ -518,10 +520,8 @@ impl PyObjectRef { /// dropped more than once due to mishandling the reference count by calling this function /// too many times. #[inline(always)] - pub unsafe fn from_raw(ptr: *const PyObject) -> Self { - Self { - ptr: NonNull::new_unchecked(ptr as *mut PyObject), - } + pub unsafe fn from_raw(ptr: NonNull) -> Self { + Self { ptr } } /// Attempt to downcast this reference to a subclass. @@ -567,7 +567,8 @@ impl PyObjectRef { #[inline(always)] pub unsafe fn downcast_unchecked_ref(&self) -> &Py { debug_assert!(self.payload_is::()); - &*(self as *const PyObjectRef as *const PyRef) + // SAFETY: requirements forwarded from caller + unsafe { &*(self as *const PyObjectRef as *const PyRef) } } // ideally we'd be able to define these in pyobject.rs, but method visibility rules are weird @@ -752,7 +753,8 @@ impl PyObject { #[inline(always)] pub unsafe fn downcast_unchecked_ref(&self) -> &Py { debug_assert!(self.payload_is::()); - &*(self as *const PyObject as *const Py) + // SAFETY: requirements forwarded from caller + unsafe { &*(self as *const PyObject as *const Py) } } #[inline(always)] @@ -814,13 +816,13 @@ impl PyObject { /// Can only be called when ref_count has dropped to zero. `ptr` must be valid #[inline(never)] unsafe fn drop_slow(ptr: NonNull) { - if let Err(()) = ptr.as_ref().drop_slow_inner() { + if let Err(()) = unsafe { ptr.as_ref().drop_slow_inner() } { // abort drop for whatever reason return; } - let drop_dealloc = ptr.as_ref().0.vtable.drop_dealloc; + let drop_dealloc = unsafe { ptr.as_ref().0.vtable.drop_dealloc }; // call drop only when there are no references in scope - stacked borrows stuff - drop_dealloc(ptr.as_ptr()) + unsafe { drop_dealloc(ptr.as_ptr()) } } /// # Safety @@ -1022,7 +1024,7 @@ impl PyRef { #[inline(always)] pub(crate) unsafe fn from_raw(raw: *const Py) -> Self { Self { - ptr: NonNull::new_unchecked(raw as *mut _), + ptr: unsafe { NonNull::new_unchecked(raw as *mut _) }, } } diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index f7247bc5e0..129a6a79bb 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -12,7 +12,13 @@ use crate::{ vm::Context, VirtualMachine, }; -use std::{borrow::Borrow, fmt, marker::PhantomData, ops::Deref, ptr::null_mut}; +use std::{ + borrow::Borrow, + fmt, + marker::PhantomData, + ops::Deref, + ptr::{null_mut, NonNull}, +}; /* Python objects and references. @@ -60,7 +66,7 @@ impl PyExact { /// Given reference must be exact type of payload T #[inline(always)] pub unsafe fn ref_unchecked(r: &Py) -> &Self { - &*(r as *const _ as *const Self) + unsafe { &*(r as *const _ as *const Self) } } } @@ -294,7 +300,7 @@ impl PyAtomicRef { pub unsafe fn swap(&self, pyref: PyRef) -> PyRef { let py = PyRef::leak(pyref) as *const Py as *mut _; let old = Radium::swap(&self.inner, py, Ordering::AcqRel); - PyRef::from_raw(old.cast()) + unsafe { PyRef::from_raw(old.cast()) } } pub fn swap_to_temporary_refs(&self, pyref: PyRef, vm: &VirtualMachine) { @@ -352,7 +358,7 @@ impl From for PyAtomicRef { fn from(obj: PyObjectRef) -> Self { let obj = obj.into_raw(); Self { - inner: Radium::new(obj as *mut _), + inner: Radium::new(obj.cast().as_ptr()), _phantom: Default::default(), } } @@ -379,8 +385,8 @@ impl PyAtomicRef { #[must_use] pub unsafe fn swap(&self, obj: PyObjectRef) -> PyObjectRef { let obj = obj.into_raw(); - let old = Radium::swap(&self.inner, obj as *mut _, Ordering::AcqRel); - PyObjectRef::from_raw(old as _) + let old = Radium::swap(&self.inner, obj.cast().as_ptr(), Ordering::AcqRel); + unsafe { PyObjectRef::from_raw(NonNull::new_unchecked(old.cast())) } } pub fn swap_to_temporary_refs(&self, obj: PyObjectRef, vm: &VirtualMachine) { @@ -393,7 +399,9 @@ impl PyAtomicRef { impl From> for PyAtomicRef> { fn from(obj: Option) -> Self { - let val = obj.map(|x| x.into_raw() as *mut _).unwrap_or(null_mut()); + let val = obj + .map(|x| x.into_raw().as_ptr().cast()) + .unwrap_or(null_mut()); Self { inner: Radium::new(val), _phantom: Default::default(), @@ -420,11 +428,11 @@ impl PyAtomicRef> { /// until no more reference can be used via PyAtomicRef::deref() #[must_use] pub unsafe fn swap(&self, obj: Option) -> Option { - let val = obj.map(|x| x.into_raw() as *mut _).unwrap_or(null_mut()); + let val = obj + .map(|x| x.into_raw().as_ptr().cast()) + .unwrap_or(null_mut()); let old = Radium::swap(&self.inner, val, Ordering::AcqRel); - old.cast::() - .as_ref() - .map(|x| PyObjectRef::from_raw(x)) + unsafe { NonNull::new(old.cast::()).map(|x| PyObjectRef::from_raw(x)) } } pub fn swap_to_temporary_refs(&self, obj: Option, vm: &VirtualMachine) { diff --git a/vm/src/protocol/buffer.rs b/vm/src/protocol/buffer.rs index 3783ccf4b6..0dfe3f0027 100644 --- a/vm/src/protocol/buffer.rs +++ b/vm/src/protocol/buffer.rs @@ -133,8 +133,11 @@ impl PyBuffer { // after this function, the owner should use forget() // or wrap PyBuffer in the ManaullyDrop to prevent drop() pub(crate) unsafe fn drop_without_release(&mut self) { - std::ptr::drop_in_place(&mut self.obj); - std::ptr::drop_in_place(&mut self.desc); + // SAFETY: requirements forwarded from caller + unsafe { + std::ptr::drop_in_place(&mut self.obj); + std::ptr::drop_in_place(&mut self.desc); + } } } diff --git a/vm/src/stdlib/msvcrt.rs b/vm/src/stdlib/msvcrt.rs index 03ddb44f22..2572494671 100644 --- a/vm/src/stdlib/msvcrt.rs +++ b/vm/src/stdlib/msvcrt.rs @@ -24,7 +24,7 @@ mod msvcrt { unsafe { suppress_iph!(_setmode(fd, libc::O_BINARY)) }; } - extern "C" { + unsafe extern "C" { fn _getch() -> i32; fn _getwch() -> u32; fn _getche() -> i32; @@ -70,7 +70,7 @@ mod msvcrt { Ok(()) } - extern "C" { + unsafe extern "C" { fn _setmode(fd: i32, flags: i32) -> i32; } @@ -84,7 +84,7 @@ mod msvcrt { } } - extern "C" { + unsafe extern "C" { fn _open_osfhandle(osfhandle: isize, flags: i32) -> i32; fn _get_osfhandle(fd: i32) -> libc::intptr_t; } diff --git a/vm/src/stdlib/nt.rs b/vm/src/stdlib/nt.rs index d2785f42dd..09d26ba279 100644 --- a/vm/src/stdlib/nt.rs +++ b/vm/src/stdlib/nt.rs @@ -116,7 +116,7 @@ pub(crate) mod module { // cwait is available on MSVC only (according to CPython) #[cfg(target_env = "msvc")] - extern "C" { + unsafe extern "C" { fn _cwait(termstat: *mut i32, procHandle: intptr_t, action: i32) -> intptr_t; } @@ -194,7 +194,7 @@ pub(crate) mod module { } #[cfg(target_env = "msvc")] - extern "C" { + unsafe extern "C" { fn _wexecv(cmdname: *const u16, argv: *const *const u16) -> intptr_t; } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index e07dca82ef..61b54f18fd 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -966,7 +966,7 @@ pub(super) mod _os { #[pyfunction] fn abort() { - extern "C" { + unsafe extern "C" { fn abort(); } unsafe { abort() } diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index 1b843bab60..77ebf9e620 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -971,7 +971,7 @@ pub mod module { #[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "netbsd",))] #[pyfunction] fn lchmod(path: OsPath, mode: u32, vm: &VirtualMachine) -> PyResult<()> { - extern "C" { + unsafe extern "C" { fn lchmod(path: *const libc::c_char, mode: libc::mode_t) -> libc::c_int; } let c_path = path.clone().into_cstring(vm)?; @@ -1605,7 +1605,7 @@ pub mod module { // from libstd: // https://github.com/rust-lang/rust/blob/daecab3a784f28082df90cebb204998051f3557d/src/libstd/sys/unix/fs.rs#L1251 #[cfg(target_os = "macos")] - extern "C" { + unsafe extern "C" { fn fcopyfile( in_fd: libc::c_int, out_fd: libc::c_int, @@ -2299,7 +2299,7 @@ pub mod module { #[cfg(target_os = "linux")] unsafe fn sys_getrandom(buf: *mut libc::c_void, buflen: usize, flags: u32) -> isize { - libc::syscall(libc::SYS_getrandom, buf, buflen, flags as usize) as _ + unsafe { libc::syscall(libc::SYS_getrandom, buf, buflen, flags as usize) as _ } } #[cfg(target_os = "linux")] diff --git a/vm/src/stdlib/signal.rs b/vm/src/stdlib/signal.rs index 8c5db53d17..da7c934552 100644 --- a/vm/src/stdlib/signal.rs +++ b/vm/src/stdlib/signal.rs @@ -78,7 +78,7 @@ pub(crate) mod _signal { pub const SIG_ERR: sighandler_t = -1 as _; #[cfg(all(unix, not(target_os = "redox")))] - extern "C" { + unsafe extern "C" { fn siginterrupt(sig: i32, flag: i32) -> i32; } diff --git a/vm/src/stdlib/time.rs b/vm/src/stdlib/time.rs index 5a493c3472..3c87550f93 100644 --- a/vm/src/stdlib/time.rs +++ b/vm/src/stdlib/time.rs @@ -17,7 +17,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef { #[cfg(not(target_env = "msvc"))] #[cfg(not(target_arch = "wasm32"))] -extern "C" { +unsafe extern "C" { #[cfg(not(target_os = "freebsd"))] #[link_name = "daylight"] static c_daylight: std::ffi::c_int; @@ -209,7 +209,9 @@ mod decl { use crate::builtins::tuple::IntoPyTuple; unsafe fn to_str(s: *const std::ffi::c_char) -> String { - std::ffi::CStr::from_ptr(s).to_string_lossy().into_owned() + unsafe { std::ffi::CStr::from_ptr(s) } + .to_string_lossy() + .into_owned() } unsafe { (to_str(super::c_tzname[0]), to_str(super::c_tzname[1])) }.into_pytuple(vm) } diff --git a/vm/src/vm/context.rs b/vm/src/vm/context.rs index f67035d0f3..9f031f01ce 100644 --- a/vm/src/vm/context.rs +++ b/vm/src/vm/context.rs @@ -62,7 +62,7 @@ macro_rules! declare_const_name { impl ConstName { unsafe fn new(pool: &StringPool, typ: &PyTypeRef) -> Self { Self { - $($name: pool.intern(stringify!($name), typ.clone()),)* + $($name: unsafe { pool.intern(stringify!($name), typ.clone()) },)* } } }