11use std:: collections:: HashMap ;
2- use std:: convert:: TryFrom ;
2+ use std:: convert:: { TryInto , TryFrom } ;
33use std:: fs:: { remove_file, File , OpenOptions } ;
44use std:: io:: { Read , Write } ;
55use std:: path:: PathBuf ;
@@ -304,19 +304,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
304304 } ;
305305
306306 let pathname: PathBuf = this. read_os_str_from_c_str ( pathname_scalar) ?. into ( ) ;
307- let flags = this. read_scalar ( flags_op) ?. to_machine_isize ( & * this. tcx ) ? as i32 ;
307+ // This argument should be a `c_int` but the syscall API just returns a pointer sized
308+ // integer.
309+ let flags: i32 = this. try_from_ptr_sized_operand ( flags_op) ?;
308310
309- let at_empty_path = this. eval_libc_i32 ( "AT_EMPTY_PATH" ) ?;
310311 let at_fdcwd = this. eval_libc_i32 ( "AT_FDCWD" ) ?;
311-
312312 // Now we need to resolve the path of the target file. This was done following the manual
313313 // entry for `statx`
314314
315315 // If `pathname` is absolute we can ignore `dirfd`.
316316 let path = if pathname. is_absolute ( ) {
317317 pathname
318318 } else {
319- let dirfd = this. read_scalar ( dirfd_op) ?. to_machine_isize ( & * this. tcx ) ? as i32 ;
319+ // This argument should be a `c_int` but the syscall API just returns a pointer sized
320+ // integer.
321+ let dirfd: i32 = this. try_from_ptr_sized_operand ( dirfd_op) ?;
320322 // If `dirfd` is `AT_FDCWD`, `pathname` is relative to the current directory.
321323 if dirfd == at_fdcwd {
322324 match std:: env:: current_dir ( ) {
@@ -327,32 +329,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
327329 }
328330 }
329331 } else {
330- if let Some ( path) = & this
331- . machine
332- . file_handler
333- . handles
334- . get ( & dirfd)
335- . map ( |h| & h. path )
336- {
337- // If `dirfd` points to a directory, `pathname` is relative to that directory
338- if path. is_dir ( ) {
339- path. join ( pathname)
340- } else {
341- // If `pathname` is empty and the `AT_EMPTY_PATH` flag is set, we use the path of `dirfd`.
342- if pathname. as_os_str ( ) . is_empty ( ) && ( flags & at_empty_path != 0 ) {
343- ( * path) . clone ( )
344- } else {
345- // It is not specified what should happen here.
346- throw_unsup_format ! (
347- "the file descriptor `{}` and path `{:?}` combination is invalid." ,
348- dirfd,
349- path
350- ) ;
351- }
352- }
353- } else {
354- return this. handle_not_found ( ) ;
355- }
332+ // This behavior is specified but cannot be tested from `libstd`. If you found this
333+ // error please open an issue reporting it.
334+ throw_unsup_format ! (
335+ "Using statx with a fildes different from `AT_FDCWD` is not supported"
336+ )
356337 }
357338 } ;
358339
@@ -385,15 +366,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
385366 // The `mode` field specifies the type of the file and the permissions over the file for
386367 // the owner, its group and other users. Given that we can only provide the file type
387368 // without using platform specific methods, we only set the bits corresponding to the file
388- // type.
369+ // type. This argument should be an `__u16` but the syscall API just returns a pointer sized
370+ // integer.
389371 let mode = if file_type. is_file ( ) {
390372 this. eval_libc ( "S_IFREG" ) ?
391373 } else if file_type. is_dir ( ) {
392374 this. eval_libc ( "S_IFDIR" ) ?
393375 } else {
394376 this. eval_libc ( "S_IFLNK" ) ?
395- }
396- . to_u32 ( ) ? as u16 ;
377+ } . to_u32 ( ) ?;
378+
379+ let mode: u16 = mode. try_into ( ) . map_err ( |e|
380+ err_unsup_format ! ( "Failed to convert 32-bit operand to u16: {}" ,
381+ e
382+ ) ) ?;
397383
398384 let size = metadata. len ( ) ;
399385
0 commit comments