diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 4789e2ed3b..5204e57705 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -34,12 +34,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_get_name_np" => { let [thread, name, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FreeBSD's pthread_get_name_np does not return anything. + // FreeBSD's pthread_get_name_np does not return anything + // and uses strlcpy, which truncates the resulting value, + // but always adds a null terminator (except for zero-sized buffers). + // https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144 this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, - false, + /* truncate */ true, )?; } diff --git a/tests/pass-dep/libc/pthread-threadname.rs b/tests/pass-dep/libc/pthread-threadname.rs index d0cd6e8d38..74b1546620 100644 --- a/tests/pass-dep/libc/pthread-threadname.rs +++ b/tests/pass-dep/libc/pthread-threadname.rs @@ -79,10 +79,9 @@ fn main() { // if the buffer is shorter than the thread name. #[cfg(any(target_os = "illumos", target_os = "solaris"))] assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE); - - // For libc implementation for macOS it's not an error - // for a buffer being too short for the thread name. - #[cfg(target_os = "macos")] + // On macOS and FreeBSD it's not an error for the buffer to be + // too short for the thread name -- they truncate instead. + #[cfg(any(target_os = "freebsd", target_os = "macos"))] { // Ensure that a zero sized buffer returns no error. assert_eq!(get_thread_name(&mut buf[..0]), 0); @@ -123,8 +122,8 @@ fn main() { // Also test directly calling pthread_setname to check its return value. assert_eq!(set_thread_name(&cstr), 0); - // But with a too long name it should fail (except on FreeBSD where the - // function has no return, hence cannot indicate failure). + // But with a too long name it should fail (except on FreeBSD where + // names of arbitrary size seem to be supported). // On macOS, the error code is different. #[cfg(not(any(target_os = "freebsd", target_os = "macos")))] assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE);