mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 13:56:10 +02:00
Port unsafe_op_in_unsafe_fn
fix to FreeBSD (#16275)
Same general idea as https://github.com/nushell/nushell/pull/16266 Fixes the 2024 edition [`unsafe_op_in_unsafe_fn`](https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html) lint for FreeBSD as well Add safety comments to both implementations and an assertion before `MaybeUninit::assume_init`
This commit is contained in:
committed by
GitHub
parent
28a796d5cb
commit
00ac34d716
@ -213,19 +213,39 @@ fn get_proc_args(pid: i32) -> io::Result<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For getting simple values from the sysctl interface
|
/// For getting simple values from the sysctl interface
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `T` needs to be of the structure that is expected to be returned by `sysctl` for the given
|
||||||
|
/// `ctl_name` sequence and will then be assumed to be of correct layout.
|
||||||
|
/// Thus only use it for primitive types or well defined fixed size types. For variable length
|
||||||
|
/// arrays that can be returned from `sysctl` use it directly (or write a proper wrapper handling
|
||||||
|
/// capacity management)
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// If the size of the returned data diverges from the size of the expected `T`
|
||||||
unsafe fn get_ctl<T>(ctl_name: &[i32]) -> io::Result<T> {
|
unsafe fn get_ctl<T>(ctl_name: &[i32]) -> io::Result<T> {
|
||||||
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
|
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
|
||||||
let mut value_len = mem::size_of_val(&value);
|
let mut value_len = mem::size_of_val(&value);
|
||||||
check(sysctl(
|
// SAFETY: lengths to the pointers is provided, uninitialized data with checked length provided
|
||||||
ctl_name.as_ptr(),
|
// Only assume initialized when the written data doesn't diverge in length, layout is the
|
||||||
ctl_name.len() as u32,
|
// safety responsibility of the caller.
|
||||||
value.as_mut_ptr() as *mut libc::c_void,
|
check(unsafe {
|
||||||
&mut value_len,
|
sysctl(
|
||||||
ptr::null(),
|
ctl_name.as_ptr(),
|
||||||
0,
|
ctl_name.len() as u32,
|
||||||
))?;
|
value.as_mut_ptr() as *mut libc::c_void,
|
||||||
Ok(value.assume_init())
|
&mut value_len,
|
||||||
|
ptr::null(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
assert_eq!(
|
||||||
|
value_len,
|
||||||
|
mem::size_of_val(&value),
|
||||||
|
"Data requested from from `sysctl` diverged in size from the expected return type. For variable length data you need to manually truncate the data to the valid returned size!"
|
||||||
|
);
|
||||||
|
Ok(unsafe { value.assume_init() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pagesize() -> io::Result<libc::c_int> {
|
fn get_pagesize() -> io::Result<libc::c_int> {
|
||||||
|
@ -93,7 +93,15 @@ fn check(err: libc::c_int) -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call `sysctl()` in read mode (i.e. the last two arguments are NULL and zero)
|
/// Call `sysctl()` in read mode (i.e. the last two arguments to set new values are NULL and zero)
|
||||||
|
///
|
||||||
|
/// `name` is a flag array.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `data` needs to be writable for `data_len` or be a `ptr::null()` paired with `data_len = 0` to
|
||||||
|
/// poll for the expected length in the `data_len` out parameter.
|
||||||
|
///
|
||||||
|
/// For more details see: https://man.netbsd.org/sysctl.3
|
||||||
unsafe fn sysctl_get(
|
unsafe fn sysctl_get(
|
||||||
name: *const i32,
|
name: *const i32,
|
||||||
name_len: u32,
|
name_len: u32,
|
||||||
@ -250,20 +258,37 @@ fn get_proc_args(pid: i32, what: i32) -> io::Result<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For getting simple values from the sysctl interface
|
/// For getting simple values from the sysctl interface
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `T` needs to be of the structure that is expected to be returned by `sysctl` for the given
|
||||||
|
/// `ctl_name` sequence and will then be assumed to be of correct layout.
|
||||||
|
/// Thus only use it for primitive types or well defined fixed size types. For variable length
|
||||||
|
/// arrays that can be returned from `sysctl` use it directly (or write a proper wrapper handling
|
||||||
|
/// capacity management)
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// If the size of the returned data diverges from the size of the expected `T`
|
||||||
unsafe fn get_ctl<T>(ctl_name: &[i32]) -> io::Result<T> {
|
unsafe fn get_ctl<T>(ctl_name: &[i32]) -> io::Result<T> {
|
||||||
// Safety: Call to unsafe function `netbsd::sysctl_get`
|
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
|
||||||
unsafe {
|
let mut value_len = mem::size_of_val(&value);
|
||||||
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
|
// SAFETY: lengths to the pointers is provided, uninitialized data with checked length provided
|
||||||
let mut value_len = mem::size_of_val(&value);
|
// Only assume initialized when the written data doesn't diverge in length, layout is the
|
||||||
check(sysctl_get(
|
// safety responsibility of the caller.
|
||||||
|
check(unsafe {
|
||||||
|
sysctl_get(
|
||||||
ctl_name.as_ptr(),
|
ctl_name.as_ptr(),
|
||||||
ctl_name.len() as u32,
|
ctl_name.len() as u32,
|
||||||
value.as_mut_ptr() as *mut libc::c_void,
|
value.as_mut_ptr() as *mut libc::c_void,
|
||||||
&mut value_len,
|
&mut value_len,
|
||||||
))?;
|
)
|
||||||
Ok(value.assume_init())
|
})?;
|
||||||
}
|
assert_eq!(
|
||||||
|
value_len,
|
||||||
|
mem::size_of_val(&value),
|
||||||
|
"Data requested from from `sysctl` diverged in size from the expected return type. For variable length data you need to manually truncate the data to the valid returned size!"
|
||||||
|
);
|
||||||
|
Ok(unsafe { value.assume_init() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pagesize() -> io::Result<libc::c_int> {
|
fn get_pagesize() -> io::Result<libc::c_int> {
|
||||||
|
Reference in New Issue
Block a user