From c10a929ac5e1b7241fca72dddc616c19caa81020 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 18 Jul 2024 13:42:11 +0000 Subject: [PATCH] Safely enforce thread name requirements --- std/src/thread/mod.rs | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/std/src/thread/mod.rs b/std/src/thread/mod.rs index c8ee365392f8..87d5c2f742c4 100644 --- a/std/src/thread/mod.rs +++ b/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> = 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 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)) } }