@@ -11,6 +11,7 @@ use rustc_span::symbol::sym;
1111use rustc_ast:: attr;
1212
1313use crate :: * ;
14+ use helpers:: check_arg_count;
1415
1516impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
1617pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
@@ -139,8 +140,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
139140 | "exit"
140141 | "ExitProcess"
141142 => {
143+ let & [ code] = check_arg_count ( args) ?;
142144 // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
143- let code = this. read_scalar ( args [ 0 ] ) ?. to_i32 ( ) ?;
145+ let code = this. read_scalar ( code ) ?. to_i32 ( ) ?;
144146 throw_machine_stop ! ( TerminationInfo :: Exit ( code. into( ) ) ) ;
145147 }
146148 _ => throw_unsup_format ! ( "can't call (diverging) foreign function: {}" , link_name) ,
@@ -197,25 +199,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
197199 match link_name {
198200 // Standard C allocation
199201 "malloc" => {
200- let size = this. read_scalar ( args[ 0 ] ) ?. to_machine_usize ( this) ?;
202+ let & [ size] = check_arg_count ( args) ?;
203+ let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
201204 let res = this. malloc ( size, /*zero_init:*/ false , MiriMemoryKind :: C ) ;
202205 this. write_scalar ( res, dest) ?;
203206 }
204207 "calloc" => {
205- let items = this. read_scalar ( args[ 0 ] ) ?. to_machine_usize ( this) ?;
206- let len = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
208+ let & [ items, len] = check_arg_count ( args) ?;
209+ let items = this. read_scalar ( items) ?. to_machine_usize ( this) ?;
210+ let len = this. read_scalar ( len) ?. to_machine_usize ( this) ?;
207211 let size =
208212 items. checked_mul ( len) . ok_or_else ( || err_ub_format ! ( "overflow during calloc size computation" ) ) ?;
209213 let res = this. malloc ( size, /*zero_init:*/ true , MiriMemoryKind :: C ) ;
210214 this. write_scalar ( res, dest) ?;
211215 }
212216 "free" => {
213- let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
217+ let & [ ptr] = check_arg_count ( args) ?;
218+ let ptr = this. read_scalar ( ptr) ?. not_undef ( ) ?;
214219 this. free ( ptr, MiriMemoryKind :: C ) ?;
215220 }
216221 "realloc" => {
217- let old_ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
218- let new_size = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
222+ let & [ old_ptr, new_size] = check_arg_count ( args) ?;
223+ let old_ptr = this. read_scalar ( old_ptr) ?. not_undef ( ) ?;
224+ let new_size = this. read_scalar ( new_size) ?. to_machine_usize ( this) ?;
219225 let res = this. realloc ( old_ptr, new_size, MiriMemoryKind :: C ) ?;
220226 this. write_scalar ( res, dest) ?;
221227 }
@@ -224,8 +230,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
224230 // (Usually these would be forwarded to to `#[global_allocator]`; we instead implement a generic
225231 // allocation that also checks that all conditions are met, such as not permitting zero-sized allocations.)
226232 "__rust_alloc" => {
227- let size = this. read_scalar ( args[ 0 ] ) ?. to_machine_usize ( this) ?;
228- let align = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
233+ let & [ size, align] = check_arg_count ( args) ?;
234+ let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
235+ let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
229236 Self :: check_alloc_request ( size, align) ?;
230237 let ptr = this. memory . allocate (
231238 Size :: from_bytes ( size) ,
@@ -235,8 +242,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
235242 this. write_scalar ( ptr, dest) ?;
236243 }
237244 "__rust_alloc_zeroed" => {
238- let size = this. read_scalar ( args[ 0 ] ) ?. to_machine_usize ( this) ?;
239- let align = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
245+ let & [ size, align] = check_arg_count ( args) ?;
246+ let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
247+ let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
240248 Self :: check_alloc_request ( size, align) ?;
241249 let ptr = this. memory . allocate (
242250 Size :: from_bytes ( size) ,
@@ -248,9 +256,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
248256 this. write_scalar ( ptr, dest) ?;
249257 }
250258 "__rust_dealloc" => {
251- let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
252- let old_size = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
253- let align = this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( this) ?;
259+ let & [ ptr, old_size, align] = check_arg_count ( args) ?;
260+ let ptr = this. read_scalar ( ptr) ?. not_undef ( ) ?;
261+ let old_size = this. read_scalar ( old_size) ?. to_machine_usize ( this) ?;
262+ let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
254263 // No need to check old_size/align; we anyway check that they match the allocation.
255264 let ptr = this. force_ptr ( ptr) ?;
256265 this. memory . deallocate (
@@ -260,12 +269,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
260269 ) ?;
261270 }
262271 "__rust_realloc" => {
263- let old_size = this. read_scalar ( args[ 1 ] ) ?. to_machine_usize ( this) ?;
264- let align = this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( this) ?;
265- let new_size = this. read_scalar ( args[ 3 ] ) ?. to_machine_usize ( this) ?;
272+ let & [ ptr, old_size, align, new_size] = check_arg_count ( args) ?;
273+ let ptr = this. force_ptr ( this. read_scalar ( ptr) ?. not_undef ( ) ?) ?;
274+ let old_size = this. read_scalar ( old_size) ?. to_machine_usize ( this) ?;
275+ let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
276+ let new_size = this. read_scalar ( new_size) ?. to_machine_usize ( this) ?;
266277 Self :: check_alloc_request ( new_size, align) ?;
267278 // No need to check old_size; we anyway check that they match the allocation.
268- let ptr = this. force_ptr ( this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?) ?;
269279 let align = Align :: from_bytes ( align) . unwrap ( ) ;
270280 let new_ptr = this. memory . reallocate (
271281 ptr,
@@ -279,9 +289,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
279289
280290 // C memory handling functions
281291 "memcmp" => {
282- let left = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
283- let right = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
284- let n = Size :: from_bytes ( this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( this) ?) ;
292+ let & [ left, right, n] = check_arg_count ( args) ?;
293+ let left = this. read_scalar ( left) ?. not_undef ( ) ?;
294+ let right = this. read_scalar ( right) ?. not_undef ( ) ?;
295+ let n = Size :: from_bytes ( this. read_scalar ( n) ?. to_machine_usize ( this) ?) ;
285296
286297 let result = {
287298 let left_bytes = this. memory . read_bytes ( left, n) ?;
@@ -298,9 +309,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
298309 this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
299310 }
300311 "memrchr" => {
301- let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
302- let val = this. read_scalar ( args[ 1 ] ) ?. to_i32 ( ) ? as u8 ;
303- let num = this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( this) ?;
312+ let & [ ptr, val, num] = check_arg_count ( args) ?;
313+ let ptr = this. read_scalar ( ptr) ?. not_undef ( ) ?;
314+ let val = this. read_scalar ( val) ?. to_i32 ( ) ? as u8 ;
315+ let num = this. read_scalar ( num) ?. to_machine_usize ( this) ?;
304316 if let Some ( idx) = this
305317 . memory
306318 . read_bytes ( ptr, Size :: from_bytes ( num) ) ?
@@ -315,9 +327,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
315327 }
316328 }
317329 "memchr" => {
318- let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
319- let val = this. read_scalar ( args[ 1 ] ) ?. to_i32 ( ) ? as u8 ;
320- let num = this. read_scalar ( args[ 2 ] ) ?. to_machine_usize ( this) ?;
330+ let & [ ptr, val, num] = check_arg_count ( args) ?;
331+ let ptr = this. read_scalar ( ptr) ?. not_undef ( ) ?;
332+ let val = this. read_scalar ( val) ?. to_i32 ( ) ? as u8 ;
333+ let num = this. read_scalar ( num) ?. to_machine_usize ( this) ?;
321334 let idx = this
322335 . memory
323336 . read_bytes ( ptr, Size :: from_bytes ( num) ) ?
@@ -331,7 +344,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
331344 }
332345 }
333346 "strlen" => {
334- let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
347+ let & [ ptr] = check_arg_count ( args) ?;
348+ let ptr = this. read_scalar ( ptr) ?. not_undef ( ) ?;
335349 let n = this. memory . read_c_str ( ptr) ?. len ( ) ;
336350 this. write_scalar ( Scalar :: from_machine_usize ( u64:: try_from ( n) . unwrap ( ) , this) , dest) ?;
337351 }
@@ -345,8 +359,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
345359 | "asinf"
346360 | "atanf"
347361 => {
362+ let & [ f] = check_arg_count ( args) ?;
348363 // FIXME: Using host floats.
349- let f = f32:: from_bits ( this. read_scalar ( args [ 0 ] ) ?. to_u32 ( ) ?) ;
364+ let f = f32:: from_bits ( this. read_scalar ( f ) ?. to_u32 ( ) ?) ;
350365 let f = match link_name {
351366 "cbrtf" => f. cbrt ( ) ,
352367 "coshf" => f. cosh ( ) ,
@@ -363,11 +378,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
363378 | "hypotf"
364379 | "atan2f"
365380 => {
381+ let & [ f1, f2] = check_arg_count ( args) ?;
366382 // underscore case for windows, here and below
367383 // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
368384 // FIXME: Using host floats.
369- let f1 = f32:: from_bits ( this. read_scalar ( args [ 0 ] ) ?. to_u32 ( ) ?) ;
370- let f2 = f32:: from_bits ( this. read_scalar ( args [ 1 ] ) ?. to_u32 ( ) ?) ;
385+ let f1 = f32:: from_bits ( this. read_scalar ( f1 ) ?. to_u32 ( ) ?) ;
386+ let f2 = f32:: from_bits ( this. read_scalar ( f2 ) ?. to_u32 ( ) ?) ;
371387 let n = match link_name {
372388 "_hypotf" | "hypotf" => f1. hypot ( f2) ,
373389 "atan2f" => f1. atan2 ( f2) ,
@@ -383,8 +399,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
383399 | "asin"
384400 | "atan"
385401 => {
402+ let & [ f] = check_arg_count ( args) ?;
386403 // FIXME: Using host floats.
387- let f = f64:: from_bits ( this. read_scalar ( args [ 0 ] ) ?. to_u64 ( ) ?) ;
404+ let f = f64:: from_bits ( this. read_scalar ( f ) ?. to_u64 ( ) ?) ;
388405 let f = match link_name {
389406 "cbrt" => f. cbrt ( ) ,
390407 "cosh" => f. cosh ( ) ,
@@ -401,9 +418,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
401418 | "hypot"
402419 | "atan2"
403420 => {
421+ let & [ f1, f2] = check_arg_count ( args) ?;
404422 // FIXME: Using host floats.
405- let f1 = f64:: from_bits ( this. read_scalar ( args [ 0 ] ) ?. to_u64 ( ) ?) ;
406- let f2 = f64:: from_bits ( this. read_scalar ( args [ 1 ] ) ?. to_u64 ( ) ?) ;
423+ let f1 = f64:: from_bits ( this. read_scalar ( f1 ) ?. to_u64 ( ) ?) ;
424+ let f2 = f64:: from_bits ( this. read_scalar ( f2 ) ?. to_u64 ( ) ?) ;
407425 let n = match link_name {
408426 "_hypot" | "hypot" => f1. hypot ( f2) ,
409427 "atan2" => f1. atan2 ( f2) ,
@@ -415,9 +433,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
415433 | "ldexp"
416434 | "scalbn"
417435 => {
436+ let & [ x, exp] = check_arg_count ( args) ?;
418437 // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
419- let x = this. read_scalar ( args [ 0 ] ) ?. to_f64 ( ) ?;
420- let exp = this. read_scalar ( args [ 1 ] ) ?. to_i32 ( ) ?;
438+ let x = this. read_scalar ( x ) ?. to_f64 ( ) ?;
439+ let exp = this. read_scalar ( exp ) ?. to_i32 ( ) ?;
421440
422441 // Saturating cast to i16. Even those are outside the valid exponent range to
423442 // `scalbn` below will do its over/underflow handling.
@@ -435,6 +454,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
435454
436455 // Architecture-specific shims
437456 "llvm.x86.sse2.pause" if this. tcx . sess . target . target . arch == "x86" || this. tcx . sess . target . target . arch == "x86_64" => {
457+ let & [ ] = check_arg_count ( args) ?;
438458 this. sched_yield ( ) ?;
439459 }
440460
0 commit comments