@@ -164,24 +164,52 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
164164 // Threading
165165 "pthread_setname_np" => {
166166 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.
167179 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 (
170181 thread,
171182 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+ } ;
174189 // Contrary to the manpage, `pthread_setname_np` on macOS still
175190 // returns an integer indicating success.
176191 this. write_scalar ( res, dest) ?;
177192 }
178193 "pthread_getname_np" => {
179194 let [ thread, name, len] =
180195 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 (
182209 this. read_scalar ( thread) ?,
183210 this. read_scalar ( name) ?,
184211 this. read_scalar ( len) ?,
212+ /* truncate */ true ,
185213 ) ?;
186214 this. write_scalar ( res, dest) ?;
187215 }
0 commit comments