Skip to content

Commit

Permalink
Fix prctl SET_NAME and GET_NAME behaviour.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vytautas Astrauskas committed Apr 30, 2020
1 parent 603ec0b commit 48da0cf
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 10 deletions.
10 changes: 8 additions & 2 deletions src/shims/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"<unnamed>"
}
}

Expand Down Expand Up @@ -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]
Expand Down
17 changes: 13 additions & 4 deletions tests/run-pass/libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"<unnamed>\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);
}
}

Expand Down

0 comments on commit 48da0cf

Please sign in to comment.