diff options
| author | Chris Denton <chris@chrisdenton.dev> | 2024-07-18 13:42:11 +0000 |
|---|---|---|
| committer | Chris Denton <chris@chrisdenton.dev> | 2024-07-18 13:45:20 +0000 |
| commit | a605e2f498ce9383d2b9ee44a796e5316c7a5e6c (patch) | |
| tree | 63eb56bc02dc7df92a0d997a39a97d75d1cd5ea2 | |
| parent | b01a977b0737e177f9b03949b908c250020d0119 (diff) | |
| download | rust-a605e2f498ce9383d2b9ee44a796e5316c7a5e6c.tar.gz rust-a605e2f498ce9383d2b9ee44a796e5316c7a5e6c.zip | |
Safely enforce thread name requirements
| -rw-r--r-- | library/std/src/thread/mod.rs | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index c8ee365392f..87d5c2f742c 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -161,7 +161,7 @@ mod tests; use crate::any::Any; use crate::cell::{OnceCell, UnsafeCell}; use crate::env; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::fmt; use crate::io; use crate::marker::PhantomData; @@ -487,11 +487,7 @@ impl Builder { amt }); - let my_thread = name.map_or_else(Thread::new_unnamed, |name| unsafe { - Thread::new( - CString::new(name).expect("thread name may not contain interior null bytes"), - ) - }); + let my_thread = name.map_or_else(Thread::new_unnamed, |name| Thread::new(name.into())); let their_thread = my_thread.clone(); let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { @@ -1273,10 +1269,34 @@ impl ThreadId { /// The internal representation of a `Thread`'s name. enum ThreadName { Main, - Other(CString), + Other(ThreadNameString), Unnamed, } +// This module ensures private fields are kept private, which is necessary to enforce the safety requirements. +mod thread_name_string { + use crate::ffi::{CStr, CString}; + + /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated. + pub(crate) struct ThreadNameString { + inner: CString, + } + impl core::ops::Deref for ThreadNameString { + type Target = CStr; + fn deref(&self) -> &CStr { + &self.inner + } + } + impl From<String> for ThreadNameString { + fn from(s: String) -> Self { + Self { + inner: CString::new(s).expect("thread name may not contain interior null bytes"), + } + } + } +} +pub(crate) use thread_name_string::ThreadNameString; + /// The internal representation of a `Thread` handle struct Inner { name: ThreadName, // Guaranteed to be UTF-8 @@ -1316,10 +1336,7 @@ pub struct Thread { impl Thread { /// Used only internally to construct a thread object without spawning. - /// - /// # Safety - /// `name` must be valid UTF-8. - pub(crate) unsafe fn new(name: CString) -> Thread { + pub(crate) fn new(name: ThreadNameString) -> Thread { unsafe { Self::new_inner(ThreadName::Other(name)) } } |
