From eb6504c3992c7a14f600d9220d464d7a0cd4573d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 12 Jan 2024 14:34:50 -0800 Subject: [PATCH] Fix errors with char signedness. When rustix is compiled with default-features = false, and linux-raw-sys is compiled with no_std, there is a difference in the signedness of `c_char`; fix rustix's code to handle this. Fixes #983. --- src/backend/linux_raw/net/netdevice.rs | 30 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/backend/linux_raw/net/netdevice.rs b/src/backend/linux_raw/net/netdevice.rs index 850b99f7a..333d27c03 100644 --- a/src/backend/linux_raw/net/netdevice.rs +++ b/src/backend/linux_raw/net/netdevice.rs @@ -1,20 +1,31 @@ #![allow(unsafe_code)] -#[cfg(feature = "alloc")] -use crate::alloc::string::String; use crate::backend::io::syscalls::ioctl; use crate::fd::AsFd; use crate::io; +use core::slice; +use core::str; +use linux_raw_sys::ctypes::c_char; use linux_raw_sys::ioctl::SIOCGIFINDEX; #[cfg(feature = "alloc")] use linux_raw_sys::ioctl::SIOCGIFNAME; use linux_raw_sys::net::{ifreq, ifreq__bindgen_ty_1, ifreq__bindgen_ty_2, IFNAMSIZ}; +#[cfg(feature = "alloc")] +use {alloc::borrow::ToOwned, alloc::string::String}; pub(crate) fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result { let if_name_bytes = if_name.as_bytes(); if if_name_bytes.len() >= IFNAMSIZ as usize { return Err(io::Errno::NODEV); } + if if_name_bytes.contains(&0) { + return Err(io::Errno::NODEV); + } + + // SAFETY: Convert `&[u8]` to `&[c_char]`. + let if_name_bytes = unsafe { + slice::from_raw_parts(if_name_bytes.as_ptr().cast::(), if_name_bytes.len()) + }; let mut ifreq = ifreq { ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, @@ -40,14 +51,17 @@ pub(crate) fn index_to_name(fd: impl AsFd, index: u32) -> io::Result { if let Some(nul_byte) = unsafe { ifreq.ifr_ifrn.ifrn_name } .iter() - .position(|char| *char == 0) + .position(|ch| *ch == 0) { - let name = unsafe { ifreq.ifr_ifrn.ifrn_name }[..nul_byte] - .iter() - .map(|v| *v as char) - .collect(); + let ifrn_name = unsafe { &ifreq.ifr_ifrn.ifrn_name[..nul_byte] }; + + // SAFETY: Convert `&[c_char]` to `&[u8]`. + let ifrn_name = + unsafe { slice::from_raw_parts(ifrn_name.as_ptr().cast::(), ifrn_name.len()) }; - Ok(name) + str::from_utf8(ifrn_name) + .map_err(|_| io::Errno::ILSEQ) + .map(ToOwned::to_owned) } else { Err(io::Errno::INVAL) }