@@ -113,16 +113,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
113113
114114 // Dynamically invoked syscalls
115115 "syscall" => {
116- // FIXME: The libc syscall() function is a variadic function.
117- // It's valid to call it with more arguments than a syscall
118- // needs, so none of these syscalls should use check_arg_count.
119- // It's even valid to call it with the wrong type of arguments,
120- // as long as they'd end up in the same place with the calling
121- // convention used. (E.g. using a `usize` instead of a pointer.)
122- // It's not directly clear which number, size, and type of arguments
123- // are acceptable in which cases and which aren't. (E.g. some
124- // types might take up the space of two registers.)
125- // So this needs to be researched first.
116+ // The syscall variadic function is legal to call with more arguments than needed,
117+ // extra arguments are simply ignored. However, all arguments need to be scalars;
118+ // other types might be treated differently by the calling convention.
119+ for arg in args {
120+ if !matches ! ( arg. layout. abi, rustc_target:: abi:: Abi :: Scalar ( _) ) {
121+ throw_ub_format ! ( "`syscall` arguments must all have scalar layout, but {} does not" , arg. layout. ty) ;
122+ }
123+ }
126124
127125 let sys_getrandom = this
128126 . eval_libc ( "SYS_getrandom" ) ?
@@ -144,22 +142,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
144142 // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
145143 id if id == sys_getrandom => {
146144 // The first argument is the syscall id, so skip over it.
147- let & [ _, ptr, len, flags] = check_arg_count ( args) ?;
148- getrandom ( this, ptr, len, flags, dest) ?;
145+ if args. len ( ) < 4 {
146+ throw_ub_format ! ( "incorrect number of arguments for `getrandom` syscall: got {}, expected at least 4" , args. len( ) ) ;
147+ }
148+ getrandom ( this, args[ 1 ] , args[ 2 ] , args[ 3 ] , dest) ?;
149149 }
150150 // `statx` is used by `libstd` to retrieve metadata information on `linux`
151151 // instead of using `stat`,`lstat` or `fstat` as on `macos`.
152152 id if id == sys_statx => {
153153 // The first argument is the syscall id, so skip over it.
154- let & [ _, dirfd, pathname, flags, mask, statxbuf] = check_arg_count ( args) ?;
155- let result = this. linux_statx ( dirfd, pathname, flags, mask, statxbuf) ?;
154+ if args. len ( ) < 6 {
155+ throw_ub_format ! ( "incorrect number of arguments for `statx` syscall: got {}, expected at least 6" , args. len( ) ) ;
156+ }
157+ let result = this. linux_statx ( args[ 1 ] , args[ 2 ] , args[ 3 ] , args[ 4 ] , args[ 5 ] ) ?;
156158 this. write_scalar ( Scalar :: from_machine_isize ( result. into ( ) , this) , dest) ?;
157159 }
158160 // `futex` is used by some synchonization primitives.
159161 id if id == sys_futex => {
160162 futex ( this, args, dest) ?;
161163 }
162- id => throw_unsup_format ! ( "miri does not support syscall ID {}" , id) ,
164+ id => throw_unsup_format ! ( "Miri does not support syscall ID {}" , id) ,
163165 }
164166 }
165167
0 commit comments