1
+ use crate :: helpers:: check_min_arg_count;
1
2
use crate :: * ;
2
3
3
4
/// Implementation of the SYS_futex syscall.
4
- /// `args` is the arguments *after * the syscall number.
5
+ /// `args` is the arguments *including * the syscall number.
5
6
pub fn futex < ' tcx > (
6
7
this : & mut MiriInterpCx < ' tcx > ,
7
8
args : & [ OpTy < ' tcx > ] ,
@@ -15,12 +16,7 @@ pub fn futex<'tcx>(
15
16
// may or may not be left out from the `syscall()` call.
16
17
// Therefore we don't use `check_arg_count` here, but only check for the
17
18
// 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) ?;
24
20
25
21
// The first three arguments (after the syscall number itself) are the same to all futex operations:
26
22
// (int *addr, int op, int val).
@@ -54,24 +50,16 @@ pub fn futex<'tcx>(
54
50
op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => {
55
51
let wait_bitset = op & !futex_realtime == futex_wait_bitset;
56
52
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) ?;
64
56
let _timeout = this. read_pointer ( timeout) ?;
65
57
let _uaddr2 = this. read_pointer ( uaddr2) ?;
66
- this. read_scalar ( bitset) ?. to_u32 ( ) ?
58
+ ( timeout , this. read_scalar ( bitset) ?. to_u32 ( ) ?)
67
59
} 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 )
75
63
} ;
76
64
77
65
if bitset == 0 {
@@ -80,7 +68,7 @@ pub fn futex<'tcx>(
80
68
return interp_ok ( ( ) ) ;
81
69
}
82
70
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" ) ) ?;
84
72
let timeout = if this. ptr_is_null ( timeout. ptr ( ) ) ? {
85
73
None
86
74
} else {
@@ -183,12 +171,8 @@ pub fn futex<'tcx>(
183
171
// Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up.
184
172
op if op == futex_wake || op == futex_wake_bitset => {
185
173
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) ?;
192
176
let _timeout = this. read_pointer ( timeout) ?;
193
177
let _uaddr2 = this. read_pointer ( uaddr2) ?;
194
178
this. read_scalar ( bitset) ?. to_u32 ( ) ?
0 commit comments