@@ -328,22 +328,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
328
328
329
329
this. check_no_isolation ( "fcntl" ) ?;
330
330
331
- let ( fd, cmd, start) = if args. len ( ) == 2 {
332
- let & [ fd, cmd] = check_arg_count ( args) ?;
333
- ( fd, cmd, None )
334
- } else {
335
- // If args.len() isn't 2 or 3 this will error appropriately.
336
- let & [ fd, cmd, start] = check_arg_count ( args) ?;
337
- ( fd, cmd, Some ( start) )
338
- } ;
339
- let fd = this. read_scalar ( fd) ?. to_i32 ( ) ?;
340
- let cmd = this. read_scalar ( cmd) ?. to_i32 ( ) ?;
331
+ if args. len ( ) < 2 {
332
+ throw_ub_format ! ( "incorrect number of arguments for fcntl: got {}, expected at least 2" , args. len( ) ) ;
333
+ }
334
+ let cmd = this. read_scalar ( args[ 1 ] ) ?. to_i32 ( ) ?;
341
335
// We only support getting the flags for a descriptor.
342
336
if cmd == this. eval_libc_i32 ( "F_GETFD" ) ? {
343
337
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
344
338
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
345
339
// always sets this flag when opening a file. However we still need to check that the
346
340
// file itself is open.
341
+ let & [ fd, _] = check_arg_count ( args) ?;
342
+ let fd = this. read_scalar ( fd) ?. to_i32 ( ) ?;
347
343
if this. machine . file_handler . handles . contains_key ( & fd) {
348
344
Ok ( this. eval_libc_i32 ( "FD_CLOEXEC" ) ?)
349
345
} else {
@@ -356,15 +352,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
356
352
// because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
357
353
// differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor,
358
354
// thus they can share the same implementation here.
355
+ let & [ fd, _, start] = check_arg_count ( args) ?;
356
+ let fd = this. read_scalar ( fd) ?. to_i32 ( ) ?;
357
+ let start = this. read_scalar ( start) ?. to_i32 ( ) ?;
359
358
if fd < MIN_NORMAL_FILE_FD {
360
359
throw_unsup_format ! ( "duplicating file descriptors for stdin, stdout, or stderr is not supported" )
361
360
}
362
- let start = start. ok_or_else ( || {
363
- err_unsup_format ! (
364
- "fcntl with command F_DUPFD or F_DUPFD_CLOEXEC requires a third argument"
365
- )
366
- } ) ?;
367
- let start = this. read_scalar ( start) ?. to_i32 ( ) ?;
368
361
let fh = & mut this. machine . file_handler ;
369
362
let ( file_result, writable) = match fh. handles . get ( & fd) {
370
363
Some ( FileHandle { file, writable } ) => ( file. try_clone ( ) , * writable) ,
0 commit comments