@@ -164,24 +164,52 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
164
164
// Threading
165
165
"pthread_setname_np" => {
166
166
let [ name] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
167
+
168
+ // The real implementation has logic in two places:
169
+ // * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200,
170
+ // * in kernel at https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/kern/proc_info.c#L3218-L3227.
171
+ //
172
+ // The function in libc calls the kernel to validate
173
+ // the security policies and the input. If all of the requirements
174
+ // are met, then the name is set and 0 is returned. Otherwise, if
175
+ // the specified name is lomnger than MAXTHREADNAMESIZE, then
176
+ // ENAMETOOLONG is returned.
177
+ //
178
+ // FIXME: the real implementation maybe returns ESRCH if the thread ID is invalid.
167
179
let thread = this. pthread_self ( ) ?;
168
- let max_len = this. eval_libc ( "MAXTHREADNAMESIZE" ) . to_target_usize ( this) ?;
169
- let res = this. pthread_setname_np (
180
+ let res = if this. pthread_setname_np (
170
181
thread,
171
182
this. read_scalar ( name) ?,
172
- max_len. try_into ( ) . unwrap ( ) ,
173
- ) ?;
183
+ this. eval_libc ( "MAXTHREADNAMESIZE" ) . to_target_usize ( this) ?. try_into ( ) . unwrap ( ) ,
184
+ ) ? {
185
+ Scalar :: from_u32 ( 0 )
186
+ } else {
187
+ this. eval_libc ( "ENAMETOOLONG" )
188
+ } ;
174
189
// Contrary to the manpage, `pthread_setname_np` on macOS still
175
190
// returns an integer indicating success.
176
191
this. write_scalar ( res, dest) ?;
177
192
}
178
193
"pthread_getname_np" => {
179
194
let [ thread, name, len] =
180
195
this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
181
- let res = this. pthread_getname_np (
196
+
197
+ // The function's behavior isn't portable between platforms.
198
+ // In case of macOS, a truncated name (due to a too small buffer)
199
+ // does not lead to an error.
200
+ //
201
+ // For details, see the implementation at
202
+ // https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1160-L1175.
203
+ // The key part is the strlcpy, which truncates the resulting value,
204
+ // but always null terminates (except for zero sized buffers).
205
+ //
206
+ // FIXME: the real implementation returns ESRCH if the thread ID is invalid.
207
+ let res = Scalar :: from_u32 ( 0 ) ;
208
+ this. pthread_getname_np (
182
209
this. read_scalar ( thread) ?,
183
210
this. read_scalar ( name) ?,
184
211
this. read_scalar ( len) ?,
212
+ /* truncate */ true ,
185
213
) ?;
186
214
this. write_scalar ( res, dest) ?;
187
215
}
0 commit comments