Skip to content

Commit 48da0cf

Browse files
author
Vytautas Astrauskas
committed
Fix prctl SET_NAME and GET_NAME behaviour.
1 parent 603ec0b commit 48da0cf

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

src/shims/thread.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9999
let option = this.read_scalar(option)?.to_i32()?;
100100
if option == this.eval_libc_i32("PR_SET_NAME")? {
101101
let address = this.read_scalar(arg2)?.not_undef()?;
102-
let name = this.memory.read_c_str(address)?.to_owned();
102+
let mut name = this.memory.read_c_str(address)?.to_owned();
103+
// The name should be no more than 16 bytes, including the null
104+
// byte. Since `read_c_str` returns the string without the null
105+
// byte, we need to truncate to 15.
106+
name.truncate(15);
103107
this.set_active_thread_name(name)?;
104108
} else if option == this.eval_libc_i32("PR_GET_NAME")? {
105109
let address = this.read_scalar(arg2)?.not_undef()?;
106-
let name = this.get_active_thread_name()?.to_vec();
110+
let mut name = this.get_active_thread_name()?.to_vec();
111+
name.push(0u8);
112+
assert!(name.len() <= 16);
107113
this.memory.write_bytes(address, name)?;
108114
} else {
109115
throw_unsup_format!("unsupported prctl option {}", option);

src/thread.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
313313
}
314314

315315
/// Get the name of the active thread.
316-
fn get_thread_name(&self) -> InterpResult<'tcx, &[u8]> {
316+
fn get_thread_name(&self) -> &[u8] {
317317
if let Some(ref thread_name) = self.active_thread_ref().thread_name {
318-
Ok(thread_name)
318+
thread_name
319319
} else {
320-
throw_ub_format!("thread {:?} has no name set", self.active_thread)
320+
b"<unnamed>"
321321
}
322322
}
323323

@@ -574,7 +574,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
574574
'mir: 'c,
575575
{
576576
let this = self.eval_context_ref();
577-
this.machine.threads.get_thread_name()
577+
Ok(this.machine.threads.get_thread_name())
578578
}
579579

580580
#[inline]

tests/run-pass/libc.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,21 @@ fn test_rwlock_libc_static_initializer() {
147147
#[cfg(target_os = "linux")]
148148
fn test_prctl_thread_name() {
149149
use std::ffi::CString;
150+
use libc::c_long;
150151
unsafe {
152+
let mut buf = [255; 10];
153+
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);
154+
assert_eq!(b"<unnamed>\0", &buf);
151155
let thread_name = CString::new("hello").expect("CString::new failed");
152-
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);
153-
let mut buf = [0; 6];
154-
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);
155-
assert_eq!(thread_name.as_bytes_with_nul(), buf);
156+
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);
157+
let mut buf = [255; 6];
158+
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);
159+
assert_eq!(b"hello\0", &buf);
160+
let long_thread_name = CString::new("01234567890123456789").expect("CString::new failed");
161+
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);
162+
let mut buf = [255; 16];
163+
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);
164+
assert_eq!(b"012345678901234\0", &buf);
156165
}
157166
}
158167

0 commit comments

Comments
 (0)