@@ -2,6 +2,7 @@ use std::mem::variant_count;
2
2
3
3
use rustc_abi:: HasDataLayout ;
4
4
5
+ use crate :: concurrency:: thread:: ThreadNotFound ;
5
6
use crate :: * ;
6
7
7
8
#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
@@ -14,7 +15,7 @@ pub enum PseudoHandle {
14
15
pub enum Handle {
15
16
Null ,
16
17
Pseudo ( PseudoHandle ) ,
17
- Thread ( u32 ) ,
18
+ Thread ( ThreadId ) ,
18
19
}
19
20
20
21
impl PseudoHandle {
@@ -34,6 +35,14 @@ impl PseudoHandle {
34
35
}
35
36
}
36
37
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
+
37
46
impl Handle {
38
47
const NULL_DISCRIMINANT : u32 = 0 ;
39
48
const PSEUDO_DISCRIMINANT : u32 = 1 ;
@@ -51,7 +60,7 @@ impl Handle {
51
60
match self {
52
61
Self :: Null => 0 ,
53
62
Self :: Pseudo ( pseudo_handle) => pseudo_handle. value ( ) ,
54
- Self :: Thread ( thread) => thread,
63
+ Self :: Thread ( thread) => thread. to_u32 ( ) ,
55
64
}
56
65
}
57
66
@@ -95,7 +104,7 @@ impl Handle {
95
104
match discriminant {
96
105
Self :: NULL_DISCRIMINANT if data == 0 => Some ( Self :: Null ) ,
97
106
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) ) ) ,
99
108
_ => None ,
100
109
}
101
110
}
@@ -126,21 +135,35 @@ impl Handle {
126
135
Scalar :: from_target_isize ( signed_handle. into ( ) , cx)
127
136
}
128
137
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 > (
130
143
handle : Scalar ,
131
- cx : & impl HasDataLayout ,
132
- ) -> InterpResult < ' tcx , Option < Self > > {
144
+ cx : & MiriInterpCx < ' tcx > ,
145
+ ) -> InterpResult < ' tcx , Result < Self , HandleError > > {
133
146
let sign_extended_handle = handle. to_target_isize ( cx) ?;
134
147
135
148
#[ expect( clippy:: cast_sign_loss) ] // we want to lose the sign
136
149
let handle = if let Ok ( signed_handle) = i32:: try_from ( sign_extended_handle) {
137
150
signed_handle as u32
138
151
} else {
139
152
// 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 ) ) ;
141
154
} ;
142
155
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
+ }
144
167
}
145
168
}
146
169
@@ -158,14 +181,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
158
181
let this = self . eval_context_mut ( ) ;
159
182
160
183
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" )
169
188
}
170
189
_ => this. invalid_handle ( "CloseHandle" ) ?,
171
190
} ;
0 commit comments