1+ use crate :: helpers:: check_min_arg_count;
12use crate :: * ;
23
34/// Implementation of the SYS_futex syscall.
4- /// `args` is the arguments *after * the syscall number.
5+ /// `args` is the arguments *including * the syscall number.
56pub fn futex < ' tcx > (
67 this : & mut MiriInterpCx < ' tcx > ,
78 args : & [ OpTy < ' tcx > ] ,
@@ -15,12 +16,7 @@ pub fn futex<'tcx>(
1516 // may or may not be left out from the `syscall()` call.
1617 // Therefore we don't use `check_arg_count` here, but only check for the
1718 // number of arguments to fall within a range.
18- let [ addr, op, val, ..] = args else {
19- throw_ub_format ! (
20- "incorrect number of arguments for `futex` syscall: got {}, expected at least 3" ,
21- args. len( )
22- ) ;
23- } ;
19+ let [ _, addr, op, val] = check_min_arg_count ( "`syscall(SYS_futex, ...)`" , args) ?;
2420
2521 // The first three arguments (after the syscall number itself) are the same to all futex operations:
2622 // (int *addr, int op, int val).
@@ -54,24 +50,16 @@ pub fn futex<'tcx>(
5450 op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => {
5551 let wait_bitset = op & !futex_realtime == futex_wait_bitset;
5652
57- let bitset = if wait_bitset {
58- let [ _, _, _, timeout, uaddr2, bitset, ..] = args else {
59- throw_ub_format ! (
60- "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT_BITSET`: got {}, expected at least 6" ,
61- args. len( )
62- ) ;
63- } ;
53+ let ( timeout, bitset) = if wait_bitset {
54+ let [ _, _, _, _, timeout, uaddr2, bitset] =
55+ check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`" , args) ?;
6456 let _timeout = this. read_pointer ( timeout) ?;
6557 let _uaddr2 = this. read_pointer ( uaddr2) ?;
66- this. read_scalar ( bitset) ?. to_u32 ( ) ?
58+ ( timeout , this. read_scalar ( bitset) ?. to_u32 ( ) ?)
6759 } else {
68- if args. len ( ) < 4 {
69- throw_ub_format ! (
70- "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT`: got {}, expected at least 4" ,
71- args. len( )
72- ) ;
73- }
74- u32:: MAX
60+ let [ _, _, _, _, timeout] =
61+ check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAIT, ...)`" , args) ?;
62+ ( timeout, u32:: MAX )
7563 } ;
7664
7765 if bitset == 0 {
@@ -80,7 +68,7 @@ pub fn futex<'tcx>(
8068 return interp_ok ( ( ) ) ;
8169 }
8270
83- let timeout = this. deref_pointer_as ( & args [ 3 ] , this. libc_ty_layout ( "timespec" ) ) ?;
71+ let timeout = this. deref_pointer_as ( timeout , this. libc_ty_layout ( "timespec" ) ) ?;
8472 let timeout = if this. ptr_is_null ( timeout. ptr ( ) ) ? {
8573 None
8674 } else {
@@ -183,12 +171,8 @@ pub fn futex<'tcx>(
183171 // Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up.
184172 op if op == futex_wake || op == futex_wake_bitset => {
185173 let bitset = if op == futex_wake_bitset {
186- let [ _, _, _, timeout, uaddr2, bitset, ..] = args else {
187- throw_ub_format ! (
188- "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAKE_BITSET`: got {}, expected at least 6" ,
189- args. len( )
190- ) ;
191- } ;
174+ let [ _, _, _, _, timeout, uaddr2, bitset] =
175+ check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`" , args) ?;
192176 let _timeout = this. read_pointer ( timeout) ?;
193177 let _uaddr2 = this. read_pointer ( uaddr2) ?;
194178 this. read_scalar ( bitset) ?. to_u32 ( ) ?
0 commit comments