diff --git a/src/shims/thread.rs b/src/shims/thread.rs index 3aca9520f6..2f553c1c72 100644 --- a/src/shims/thread.rs +++ b/src/shims/thread.rs @@ -99,11 +99,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let option = this.read_scalar(option)?.to_i32()?; if option == this.eval_libc_i32("PR_SET_NAME")? { let address = this.read_scalar(arg2)?.not_undef()?; - let name = this.memory.read_c_str(address)?.to_owned(); + let mut name = this.memory.read_c_str(address)?.to_owned(); + // The name should be no more than 16 bytes, including the null + // byte. Since `read_c_str` returns the string without the null + // byte, we need to truncate to 15. + name.truncate(15); this.set_active_thread_name(name)?; } else if option == this.eval_libc_i32("PR_GET_NAME")? { let address = this.read_scalar(arg2)?.not_undef()?; - let name = this.get_active_thread_name()?.to_vec(); + let mut name = this.get_active_thread_name()?.to_vec(); + name.push(0u8); + assert!(name.len() <= 16); this.memory.write_bytes(address, name)?; } else { throw_unsup_format!("unsupported prctl option {}", option); diff --git a/src/thread.rs b/src/thread.rs index 7d394c9002..376920e225 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -313,11 +313,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { } /// Get the name of the active thread. - fn get_thread_name(&self) -> InterpResult<'tcx, &[u8]> { + fn get_thread_name(&self) -> &[u8] { if let Some(ref thread_name) = self.active_thread_ref().thread_name { - Ok(thread_name) + thread_name } else { - throw_ub_format!("thread {:?} has no name set", self.active_thread) + b"" } } @@ -574,7 +574,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 'mir: 'c, { let this = self.eval_context_ref(); - this.machine.threads.get_thread_name() + Ok(this.machine.threads.get_thread_name()) } #[inline] diff --git a/tests/run-pass/libc.rs b/tests/run-pass/libc.rs index 36805fc83e..04ca5c0b3b 100644 --- a/tests/run-pass/libc.rs +++ b/tests/run-pass/libc.rs @@ -147,12 +147,21 @@ fn test_rwlock_libc_static_initializer() { #[cfg(target_os = "linux")] fn test_prctl_thread_name() { use std::ffi::CString; + use libc::c_long; unsafe { + let mut buf = [255; 10]; + assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0); + assert_eq!(b"\0", &buf); let thread_name = CString::new("hello").expect("CString::new failed"); - assert_eq!(libc::prctl(libc::PR_SET_NAME, thread_name.as_ptr() as libc::c_long, 0 as libc::c_long, 0 as libc::c_long, 0 as libc::c_long), 0); - let mut buf = [0; 6]; - assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as libc::c_long, 0 as libc::c_long, 0 as libc::c_long, 0 as libc::c_long), 0); - assert_eq!(thread_name.as_bytes_with_nul(), buf); + assert_eq!(libc::prctl(libc::PR_SET_NAME, thread_name.as_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0); + let mut buf = [255; 6]; + assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0); + assert_eq!(b"hello\0", &buf); + let long_thread_name = CString::new("01234567890123456789").expect("CString::new failed"); + assert_eq!(libc::prctl(libc::PR_SET_NAME, long_thread_name.as_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0); + let mut buf = [255; 16]; + assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0); + assert_eq!(b"012345678901234\0", &buf); } }