Skip to content

Commit a94c325

Browse files
committed
socket: accept a filesystem-encoded hostname in sethostname
`socket.sethostname` took `PyUtf8StrRef`, so it rejected `bytes` outright and refused a `str` carrying a surrogate escape. `socketmodule.c socket_sethostname` accepts a bytes object directly, falls back to `PyUnicode_FSConverter` for anything else, and hands the syscall the resulting buffer and its length — the name is never required to be UTF-8. Take `FsPath`, the converter `if_nametoindex` in this same module already uses, and pass its bytes down. `host_env::socket::sethostname` correspondingly takes `&[u8]` and builds the `OsStr` from them; `nix::unistd::sethostname` accepts `AsRef<OsStr>` and passes pointer and length to the syscall, so nothing on the path needs a NUL terminator or valid UTF-8. `Lib/test/test_socket.py test_sethostname` covers this: it calls `socket.sethostname(b'bar')` and asserts the hostname changed. The test is skipped unless run as root, which is why the gap went unnoticed. Assisted-by: Claude
1 parent 1613741 commit a94c325

2 files changed

Lines changed: 10 additions & 4 deletions

File tree

‎crates/host_env/src/socket.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,15 @@ pub use libc::{AF_ALG, AF_CAN};
4444
#[cfg(target_os = "linux")]
4545
pub use libc::{sockaddr_alg, sockaddr_can};
4646

47+
/// Set the system's hostname from its filesystem-encoded bytes.
48+
///
49+
/// `socketmodule.c socket_sethostname` reads the argument as a buffer and
50+
/// passes `buf.buf`/`buf.len` straight to the syscall, so a name is not
51+
/// required to be UTF-8; taking `&[u8]` keeps that true here as well.
4752
#[cfg(all(unix, not(target_os = "redox")))]
48-
pub fn sethostname(hostname: &str) -> io::Result<()> {
49-
nix::unistd::sethostname(hostname).map_err(io::Error::from)
53+
pub fn sethostname(hostname: &[u8]) -> io::Result<()> {
54+
use std::os::unix::ffi::OsStrExt;
55+
nix::unistd::sethostname(std::ffi::OsStr::from_bytes(hostname)).map_err(io::Error::from)
5056
}
5157

5258
#[cfg(unix)]

‎crates/stdlib/src/socket.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,8 +2325,8 @@ mod _socket {
23252325

23262326
#[cfg(all(unix, not(any(target_os = "redox", target_os = "android"))))]
23272327
#[pyfunction]
2328-
fn sethostname(hostname: PyUtf8StrRef) -> std::io::Result<()> {
2329-
host_socket::sethostname(hostname.as_str())
2328+
fn sethostname(hostname: FsPath) -> std::io::Result<()> {
2329+
host_socket::sethostname(hostname.as_bytes())
23302330
}
23312331

23322332
#[pyfunction]

0 commit comments

Comments
 (0)