diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 1be3acf5d4365..69c721c5efca8 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -240,7 +240,8 @@ pub trait CommandExt: Sealed { /// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values. /// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe. /// - /// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute. + /// The `attribute` parameter specifies the raw attribute to be set, while the `value_ptr` parameter holds the pointer to the value associated with that attribute, + /// and the `value_size` parameter indicates the size of the value in bytes. /// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings. /// /// # Note @@ -257,7 +258,8 @@ pub trait CommandExt: Sealed { /// /// ```rust /// #![feature(windows_process_extensions_raw_attribute)] - /// use std::os::windows::{process::CommandExt, io::AsRawHandle}; + /// use std::mem; + /// use std::os::windows::{process::CommandExt, io::AsRawHandle, io::RawHandle}; /// use std::process::Command; /// /// # struct ProcessDropGuard(std::process::Child); @@ -266,15 +268,17 @@ pub trait CommandExt: Sealed { /// # let _ = self.0.kill(); /// # } /// # } - /// + /// # /// let parent = Command::new("cmd").spawn()?; - /// /// let mut child_cmd = Command::new("cmd"); /// /// const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000; - /// /// unsafe { - /// child_cmd.raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.as_raw_handle() as isize); + /// child_cmd.raw_attribute( + /// PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + /// parent.as_raw_handle(), + /// mem::size_of::() + /// ); /// } /// # /// # let parent = ProcessDropGuard(parent); @@ -289,10 +293,11 @@ pub trait CommandExt: Sealed { /// /// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used. #[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")] - unsafe fn raw_attribute( + unsafe fn raw_attribute( &mut self, attribute: usize, - value: T, + value_ptr: *const T, + value_size: usize, ) -> &mut process::Command; } @@ -322,12 +327,13 @@ impl CommandExt for process::Command { self } - unsafe fn raw_attribute( + unsafe fn raw_attribute( &mut self, attribute: usize, - value: T, + value_ptr: *const T, + value_size: usize, ) -> &mut process::Command { - self.as_inner_mut().raw_attribute(attribute, value); + self.as_inner_mut().raw_attribute(attribute, value_ptr, value_size); self } } diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 07d4de5c1a26e..25bebcc0a2e55 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -482,8 +482,11 @@ fn test_proc_thread_attributes() { let mut child_cmd = Command::new("cmd"); unsafe { - child_cmd - .raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize); + child_cmd.raw_attribute( + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + parent.0.as_raw_handle(), + mem::size_of::(), + ); } let child = ProcessDropGuard(child_cmd.spawn().unwrap()); diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index e4ab2ca7da1ce..7ba2f42a53236 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -248,14 +248,15 @@ impl Command { self.cwd.as_ref().map(Path::new) } - pub unsafe fn raw_attribute( + pub unsafe fn raw_attribute( &mut self, attribute: usize, - value: T, + ptr: *const T, + size: usize, ) { self.proc_thread_attributes.insert( attribute, - ProcThreadAttributeValue { size: mem::size_of::(), data: Box::new(value) }, + ProcThreadAttributeValue { ptr: mem::transmute::<*const T, *const c_void>(ptr), size }, ); } @@ -890,10 +891,13 @@ impl Drop for ProcThreadAttributeList { /// Wrapper around the value data to be used as a Process Thread Attribute. struct ProcThreadAttributeValue { - data: Box, + ptr: *const c_void, size: usize, } +unsafe impl Send for ProcThreadAttributeValue {} +unsafe impl Sync for ProcThreadAttributeValue {} + fn make_proc_thread_attribute_list( attributes: &BTreeMap, ) -> io::Result { @@ -935,13 +939,12 @@ fn make_proc_thread_attribute_list( // It's theoretically possible for the attribute count to exceed a u32 value. // Therefore, we ensure that we don't add more attributes than the buffer was initialized for. for (&attribute, value) in attributes.iter().take(attribute_count as usize) { - let value_ptr = core::ptr::addr_of!(*value.data) as _; cvt(unsafe { c::UpdateProcThreadAttribute( proc_thread_attribute_list.0.as_mut_ptr() as _, 0, attribute, - value_ptr, + value.ptr, value.size, ptr::null_mut(), ptr::null_mut(),