unsafe_op_in_unsafe_fn: ld_so, generic/redox-rt

There are a few functions where I allowed the lint. The lower level and
FFI nature of relibc means that there are areas with a lot of unsafe.
Some functions are basically long blocks of unsafe or contain lots of
small blocks of unsafe. unsafe_op_in_unsafe_fn doesn't add clarity to
these functions. Instead, it reduces readability by adding an indent or
small "unsafe { .. }" clutter.
This commit is contained in:
Josh Megnauth
2025-10-04 19:18:22 -04:00
parent 7ed934a01d
commit e39b27664f
12 changed files with 146 additions and 101 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ pub unsafe extern "C" fn relibc_crt0(sp: usize) -> ! {
) -> c_int,
) -> !;
}
relibc_start_v1(sp, main)
unsafe { relibc_start_v1(sp, main) }
}
#[linkage = "weak"]
+1 -1
View File
@@ -767,7 +767,7 @@ impl DSO {
unsafe fn get_array<'a, T>(ptr: Option<*const T>, len: Option<usize>) -> &'a [T] {
if let Some(ptr) = ptr {
let len = len.expect("dynamic entry was present without it's corresponding size");
core::slice::from_raw_parts(ptr, len)
unsafe { core::slice::from_raw_parts(ptr, len) }
} else {
assert!(len.is_none());
&[]
+3 -2
View File
@@ -3,6 +3,7 @@
// FIXME(andypython): remove this when #![allow(warnings, unused_variables)] is
// dropped from src/lib.rs.
#![warn(warnings, unused_variables)]
#![deny(unsafe_op_in_unsafe_fn)]
use core::{mem, ptr};
use object::{
@@ -200,9 +201,9 @@ pub unsafe fn init(
}
pub unsafe fn fini() {
if let Some(tcb) = Tcb::current() {
if let Some(tcb) = unsafe { Tcb::current() } {
if !tcb.linker_ptr.is_null() {
let linker = (*tcb.linker_ptr).lock();
let linker = unsafe { (*tcb.linker_ptr).lock() };
linker.fini();
}
}
+17 -11
View File
@@ -1,5 +1,7 @@
// Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
#![deny(unsafe_op_in_unsafe_fn)]
use alloc::{
borrow::ToOwned,
boxed::Box,
@@ -7,12 +9,14 @@ use alloc::{
string::{String, ToString},
vec::Vec,
};
use generic_rt::ExpectTlsFree;
use crate::{
ALLOCATOR,
c_str::CStr,
header::unistd,
header::{
sys_auxv::{AT_ENTRY, AT_PHDR},
unistd,
},
platform::{get_auxv, get_auxvs, types::c_char},
start::Stack,
sync::mutex::Mutex,
@@ -25,7 +29,8 @@ use super::{
linker::{Config, Linker},
tcb::Tcb,
};
use crate::header::sys_auxv::{AT_ENTRY, AT_PHDR};
use generic_rt::ExpectTlsFree;
#[cfg(target_pointer_width = "32")]
pub const SIZEOF_EHDR: usize = 52;
@@ -36,16 +41,16 @@ pub const SIZEOF_EHDR: usize = 64;
unsafe fn get_argv(mut ptr: *const usize) -> (Vec<String>, *const usize) {
//traverse the stack and collect argument vector
let mut argv = Vec::new();
while *ptr != 0 {
let arg = *ptr;
match CStr::from_ptr(arg as *const c_char).to_str() {
while unsafe { *ptr != 0 } {
let arg = unsafe { *ptr };
match unsafe { CStr::from_ptr(arg as *const c_char).to_str() } {
Ok(arg_str) => argv.push(arg_str.to_owned()),
_ => {
eprintln!("ld.so: failed to parse argv[{}]", argv.len());
unistd::_exit(1);
}
}
ptr = ptr.add(1);
ptr = unsafe { ptr.add(1) };
}
(argv, ptr)
@@ -54,9 +59,9 @@ unsafe fn get_argv(mut ptr: *const usize) -> (Vec<String>, *const usize) {
unsafe fn get_env(mut ptr: *const usize) -> (BTreeMap<String, String>, *const usize) {
//traverse the stack and collect argument environment variables
let mut envs = BTreeMap::new();
while *ptr != 0 {
let env = *ptr;
if let Ok(arg_str) = CStr::from_ptr(env as *const c_char).to_str() {
while unsafe { *ptr != 0 } {
let env = unsafe { *ptr };
if let Ok(arg_str) = unsafe { CStr::from_ptr(env as *const c_char).to_str() } {
let mut parts = arg_str.splitn(2, '=');
if let Some(key) = parts.next() {
if let Some(value) = parts.next() {
@@ -64,12 +69,13 @@ unsafe fn get_env(mut ptr: *const usize) -> (BTreeMap<String, String>, *const us
}
}
}
ptr = ptr.add(1);
ptr = unsafe { ptr.add(1) };
}
(envs, ptr)
}
#[allow(unsafe_op_in_unsafe_fn)]
unsafe fn adjust_stack(sp: &'static mut Stack) {
let mut argv = sp.argv() as *mut usize;
+29 -17
View File
@@ -1,3 +1,5 @@
#![deny(unsafe_op_in_unsafe_fn)]
use alloc::vec::Vec;
use core::{
cell::UnsafeCell,
@@ -32,7 +34,7 @@ pub struct Master {
impl Master {
/// The initial data for this TLS region
pub unsafe fn data(&self) -> &'static [u8] {
slice::from_raw_parts(self.ptr, self.len)
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
@@ -77,6 +79,7 @@ impl Tcb {
/// Create a new TCB
///
/// `size` is the size of the TLS in bytes.
#[allow(unsafe_op_in_unsafe_fn)]
pub unsafe fn new(size: usize) -> Result<&'static mut Self, DlError> {
let page_size = Sys::getpagesize();
let (_abi_page, tls, tcb_page) = Self::os_new(size.next_multiple_of(page_size))?;
@@ -117,7 +120,7 @@ impl Tcb {
/// Get the current TCB
pub unsafe fn current() -> Option<&'static mut Self> {
Some(&mut *GenericTcb::<OsSpecific>::current_ptr()?.cast())
unsafe { Some(&mut *GenericTcb::<OsSpecific>::current_ptr()?.cast()) }
}
/// A slice for all of the TLS data
@@ -125,8 +128,10 @@ impl Tcb {
if self.tls_end.is_null() || self.tls_len == 0 {
None
} else {
let tls_start = self.tls_end.sub(self.tls_len);
Some(slice::from_raw_parts_mut(tls_start, self.tls_len))
unsafe {
let tls_start = self.tls_end.sub(self.tls_len);
Some(slice::from_raw_parts_mut(tls_start, self.tls_len))
}
}
}
@@ -147,7 +152,7 @@ impl Tcb {
/// Copy data from masters
pub unsafe fn copy_masters(&mut self) -> Result<(), DlError> {
//TODO: Complain if masters or tls exist without the other
if let Some(tls) = self.tls() {
if let Some(tls) = unsafe { self.tls() } {
if let Some(masters) = self.masters() {
for master in masters
.iter()
@@ -161,7 +166,7 @@ impl Tcb {
master.offset..master.offset + master.len
};
if let Some(tls_data) = tls.get_mut(range) {
let data = master.data();
let data = unsafe { master.data() };
trace!(
"tls master: {:p}, {:#x}: {:p}, {:#x}",
data.as_ptr(),
@@ -201,13 +206,15 @@ impl Tcb {
/// Activate TLS
pub unsafe fn activate(&mut self, #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard) {
Self::os_arch_activate(
&self.os_specific,
self.tls_end as usize,
self.tls_len,
#[cfg(target_os = "redox")]
thr_fd,
);
unsafe {
Self::os_arch_activate(
&self.os_specific,
self.tls_end as usize,
self.tls_len,
#[cfg(target_os = "redox")]
thr_fd,
)
};
}
pub fn setup_dtv(&mut self, n: usize) {
@@ -255,6 +262,7 @@ impl Tcb {
}
/// Mapping with correct flags for TCB and TLS
#[allow(unsafe_op_in_unsafe_fn)]
unsafe fn map(size: usize) -> Result<&'static mut [u8], DlError> {
let ptr = Sys::mmap(
ptr::null_mut(),
@@ -317,7 +325,7 @@ impl Tcb {
size: usize,
) -> Result<(&'static mut [u8], &'static mut [u8], &'static mut [u8]), DlError> {
let page_size = Sys::getpagesize();
let abi_tls_tcb = Self::map(page_size + size + page_size)?;
let abi_tls_tcb = unsafe { Self::map(page_size + size + page_size)? };
let (abi, tls_tcb) = abi_tls_tcb.split_at_mut(page_size);
let (tls, tcb) = tls_tcb.split_at_mut(size);
Ok((abi, tls, tcb))
@@ -327,7 +335,9 @@ impl Tcb {
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
unsafe fn os_arch_activate(_os: &(), tls_end: usize, _tls_len: usize) {
const ARCH_SET_FS: usize = 0x1002;
syscall!(ARCH_PRCTL, ARCH_SET_FS, tls_end);
unsafe {
syscall!(ARCH_PRCTL, ARCH_SET_FS, tls_end);
}
}
#[cfg(target_os = "redox")]
@@ -337,8 +347,10 @@ impl Tcb {
tls_len: usize,
thr_fd: redox_rt::proc::FdGuard,
) {
os.thr_fd.get().write(Some(thr_fd));
redox_rt::tcb_activate(os, tls_end, tls_len)
unsafe {
os.thr_fd.get().write(Some(thr_fd));
redox_rt::tcb_activate(os, tls_end, tls_len)
}
}
}