Skip to content

Commit 4520ff8

Browse files
authored
Merge pull request rust-lang#4035 from discord9/master
refactor: refine thread variant for windows
2 parents f953ed5 + cecf2b3 commit 4520ff8

File tree

4 files changed

+57
-32
lines changed

4 files changed

+57
-32
lines changed

src/tools/miri/src/concurrency/thread.rs

+5
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ impl ThreadId {
113113
self.0
114114
}
115115

116+
/// Create a new thread id from a `u32` without checking if this thread exists.
117+
pub fn new_unchecked(id: u32) -> Self {
118+
Self(id)
119+
}
120+
116121
pub const MAIN_THREAD: ThreadId = ThreadId(0);
117122
}
118123

src/tools/miri/src/shims/windows/foreign_items.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_span::Symbol;
77

88
use self::shims::windows::handle::{Handle, PseudoHandle};
99
use crate::shims::os_str::bytes_to_os_str;
10+
use crate::shims::windows::handle::HandleError;
1011
use crate::shims::windows::*;
1112
use crate::*;
1213

@@ -488,7 +489,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
488489
let thread_id =
489490
this.CreateThread(security, stacksize, start, arg, flags, thread)?;
490491

491-
this.write_scalar(Handle::Thread(thread_id.to_u32()).to_scalar(this), dest)?;
492+
this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?;
492493
}
493494
"WaitForSingleObject" => {
494495
let [handle, timeout] =
@@ -513,10 +514,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
513514
let handle = this.read_scalar(handle)?;
514515
let name = this.read_wide_str(this.read_pointer(name)?)?;
515516

516-
let thread = match Handle::from_scalar(handle, this)? {
517-
Some(Handle::Thread(thread)) => this.thread_id_try_from(thread),
518-
Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()),
519-
_ => this.invalid_handle("SetThreadDescription")?,
517+
let thread = match Handle::try_from_scalar(handle, this)? {
518+
Ok(Handle::Thread(thread)) => Ok(thread),
519+
Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()),
520+
Ok(_) | Err(HandleError::InvalidHandle) =>
521+
this.invalid_handle("SetThreadDescription")?,
522+
Err(HandleError::ThreadNotFound(e)) => Err(e),
520523
};
521524
let res = match thread {
522525
Ok(thread) => {
@@ -536,10 +539,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
536539
let handle = this.read_scalar(handle)?;
537540
let name_ptr = this.deref_pointer(name_ptr)?; // the pointer where we should store the ptr to the name
538541

539-
let thread = match Handle::from_scalar(handle, this)? {
540-
Some(Handle::Thread(thread)) => this.thread_id_try_from(thread),
541-
Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()),
542-
_ => this.invalid_handle("GetThreadDescription")?,
542+
let thread = match Handle::try_from_scalar(handle, this)? {
543+
Ok(Handle::Thread(thread)) => Ok(thread),
544+
Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()),
545+
Ok(_) | Err(HandleError::InvalidHandle) =>
546+
this.invalid_handle("GetThreadDescription")?,
547+
Err(HandleError::ThreadNotFound(e)) => Err(e),
543548
};
544549
let (name, res) = match thread {
545550
Ok(thread) => {

src/tools/miri/src/shims/windows/handle.rs

+35-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::mem::variant_count;
22

33
use rustc_abi::HasDataLayout;
44

5+
use crate::concurrency::thread::ThreadNotFound;
56
use crate::*;
67

78
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -14,7 +15,7 @@ pub enum PseudoHandle {
1415
pub enum Handle {
1516
Null,
1617
Pseudo(PseudoHandle),
17-
Thread(u32),
18+
Thread(ThreadId),
1819
}
1920

2021
impl PseudoHandle {
@@ -34,6 +35,14 @@ impl PseudoHandle {
3435
}
3536
}
3637

38+
/// Errors that can occur when constructing a [`Handle`] from a Scalar.
39+
pub enum HandleError {
40+
/// There is no thread with the given ID.
41+
ThreadNotFound(ThreadNotFound),
42+
/// Can't convert scalar to handle because it is structurally invalid.
43+
InvalidHandle,
44+
}
45+
3746
impl Handle {
3847
const NULL_DISCRIMINANT: u32 = 0;
3948
const PSEUDO_DISCRIMINANT: u32 = 1;
@@ -51,7 +60,7 @@ impl Handle {
5160
match self {
5261
Self::Null => 0,
5362
Self::Pseudo(pseudo_handle) => pseudo_handle.value(),
54-
Self::Thread(thread) => thread,
63+
Self::Thread(thread) => thread.to_u32(),
5564
}
5665
}
5766

@@ -95,7 +104,7 @@ impl Handle {
95104
match discriminant {
96105
Self::NULL_DISCRIMINANT if data == 0 => Some(Self::Null),
97106
Self::PSEUDO_DISCRIMINANT => Some(Self::Pseudo(PseudoHandle::from_value(data)?)),
98-
Self::THREAD_DISCRIMINANT => Some(Self::Thread(data)),
107+
Self::THREAD_DISCRIMINANT => Some(Self::Thread(ThreadId::new_unchecked(data))),
99108
_ => None,
100109
}
101110
}
@@ -126,21 +135,35 @@ impl Handle {
126135
Scalar::from_target_isize(signed_handle.into(), cx)
127136
}
128137

129-
pub fn from_scalar<'tcx>(
138+
/// Convert a scalar into a structured `Handle`.
139+
/// Structurally invalid handles return [`HandleError::InvalidHandle`].
140+
/// If the handle is structurally valid but semantically invalid, e.g. a for non-existent thread
141+
/// ID, returns [`HandleError::ThreadNotFound`].
142+
pub fn try_from_scalar<'tcx>(
130143
handle: Scalar,
131-
cx: &impl HasDataLayout,
132-
) -> InterpResult<'tcx, Option<Self>> {
144+
cx: &MiriInterpCx<'tcx>,
145+
) -> InterpResult<'tcx, Result<Self, HandleError>> {
133146
let sign_extended_handle = handle.to_target_isize(cx)?;
134147

135148
#[expect(clippy::cast_sign_loss)] // we want to lose the sign
136149
let handle = if let Ok(signed_handle) = i32::try_from(sign_extended_handle) {
137150
signed_handle as u32
138151
} else {
139152
// if a handle doesn't fit in an i32, it isn't valid.
140-
return interp_ok(None);
153+
return interp_ok(Err(HandleError::InvalidHandle));
141154
};
142155

143-
interp_ok(Self::from_packed(handle))
156+
match Self::from_packed(handle) {
157+
Some(Self::Thread(thread)) => {
158+
// validate the thread id
159+
match cx.machine.threads.thread_id_try_from(thread.to_u32()) {
160+
Ok(id) => interp_ok(Ok(Self::Thread(id))),
161+
Err(e) => interp_ok(Err(HandleError::ThreadNotFound(e))),
162+
}
163+
}
164+
Some(handle) => interp_ok(Ok(handle)),
165+
None => interp_ok(Err(HandleError::InvalidHandle)),
166+
}
144167
}
145168
}
146169

@@ -158,14 +181,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
158181
let this = self.eval_context_mut();
159182

160183
let handle = this.read_scalar(handle_op)?;
161-
let ret = match Handle::from_scalar(handle, this)? {
162-
Some(Handle::Thread(thread)) => {
163-
if let Ok(thread) = this.thread_id_try_from(thread) {
164-
this.detach_thread(thread, /*allow_terminated_joined*/ true)?;
165-
this.eval_windows("c", "TRUE")
166-
} else {
167-
this.invalid_handle("CloseHandle")?
168-
}
184+
let ret = match Handle::try_from_scalar(handle, this)? {
185+
Ok(Handle::Thread(thread)) => {
186+
this.detach_thread(thread, /*allow_terminated_joined*/ true)?;
187+
this.eval_windows("c", "TRUE")
169188
}
170189
_ => this.invalid_handle("CloseHandle")?,
171190
};

src/tools/miri/src/shims/windows/thread.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
6565
let handle = this.read_scalar(handle_op)?;
6666
let timeout = this.read_scalar(timeout_op)?.to_u32()?;
6767

68-
let thread = match Handle::from_scalar(handle, this)? {
69-
Some(Handle::Thread(thread)) =>
70-
match this.thread_id_try_from(thread) {
71-
Ok(thread) => thread,
72-
Err(_) => this.invalid_handle("WaitForSingleObject")?,
73-
},
68+
let thread = match Handle::try_from_scalar(handle, this)? {
69+
Ok(Handle::Thread(thread)) => thread,
7470
// Unlike on posix, the outcome of joining the current thread is not documented.
7571
// On current Windows, it just deadlocks.
76-
Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.active_thread(),
72+
Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.active_thread(),
7773
_ => this.invalid_handle("WaitForSingleObject")?,
7874
};
7975

0 commit comments

Comments
 (0)