@@ -11,6 +11,7 @@ use rustc_span::symbol::sym;
11
11
use rustc_ast:: attr;
12
12
13
13
use crate :: * ;
14
+ use helpers:: check_arg_count;
14
15
15
16
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
16
17
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
@@ -139,8 +140,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
139
140
| "exit"
140
141
| "ExitProcess"
141
142
=> {
143
+ let & [ code] = check_arg_count ( args) ?;
142
144
// 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 ( ) ?;
144
146
throw_machine_stop ! ( TerminationInfo :: Exit ( code. into( ) ) ) ;
145
147
}
146
148
_ => 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
197
199
match link_name {
198
200
// Standard C allocation
199
201
"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) ?;
201
204
let res = this. malloc ( size, /*zero_init:*/ false , MiriMemoryKind :: C ) ;
202
205
this. write_scalar ( res, dest) ?;
203
206
}
204
207
"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) ?;
207
211
let size =
208
212
items. checked_mul ( len) . ok_or_else ( || err_ub_format ! ( "overflow during calloc size computation" ) ) ?;
209
213
let res = this. malloc ( size, /*zero_init:*/ true , MiriMemoryKind :: C ) ;
210
214
this. write_scalar ( res, dest) ?;
211
215
}
212
216
"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 ( ) ?;
214
219
this. free ( ptr, MiriMemoryKind :: C ) ?;
215
220
}
216
221
"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) ?;
219
225
let res = this. realloc ( old_ptr, new_size, MiriMemoryKind :: C ) ?;
220
226
this. write_scalar ( res, dest) ?;
221
227
}
@@ -224,8 +230,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
224
230
// (Usually these would be forwarded to to `#[global_allocator]`; we instead implement a generic
225
231
// allocation that also checks that all conditions are met, such as not permitting zero-sized allocations.)
226
232
"__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) ?;
229
236
Self :: check_alloc_request ( size, align) ?;
230
237
let ptr = this. memory . allocate (
231
238
Size :: from_bytes ( size) ,
@@ -235,8 +242,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
235
242
this. write_scalar ( ptr, dest) ?;
236
243
}
237
244
"__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) ?;
240
248
Self :: check_alloc_request ( size, align) ?;
241
249
let ptr = this. memory . allocate (
242
250
Size :: from_bytes ( size) ,
@@ -248,9 +256,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
248
256
this. write_scalar ( ptr, dest) ?;
249
257
}
250
258
"__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) ?;
254
263
// No need to check old_size/align; we anyway check that they match the allocation.
255
264
let ptr = this. force_ptr ( ptr) ?;
256
265
this. memory . deallocate (
@@ -260,12 +269,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
260
269
) ?;
261
270
}
262
271
"__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) ?;
266
277
Self :: check_alloc_request ( new_size, align) ?;
267
278
// 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 ( ) ?) ?;
269
279
let align = Align :: from_bytes ( align) . unwrap ( ) ;
270
280
let new_ptr = this. memory . reallocate (
271
281
ptr,
@@ -279,9 +289,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
279
289
280
290
// C memory handling functions
281
291
"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) ?) ;
285
296
286
297
let result = {
287
298
let left_bytes = this. memory . read_bytes ( left, n) ?;
@@ -298,9 +309,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
298
309
this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
299
310
}
300
311
"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) ?;
304
316
if let Some ( idx) = this
305
317
. memory
306
318
. read_bytes ( ptr, Size :: from_bytes ( num) ) ?
@@ -315,9 +327,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
315
327
}
316
328
}
317
329
"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) ?;
321
334
let idx = this
322
335
. memory
323
336
. read_bytes ( ptr, Size :: from_bytes ( num) ) ?
@@ -331,7 +344,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
331
344
}
332
345
}
333
346
"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 ( ) ?;
335
349
let n = this. memory . read_c_str ( ptr) ?. len ( ) ;
336
350
this. write_scalar ( Scalar :: from_machine_usize ( u64:: try_from ( n) . unwrap ( ) , this) , dest) ?;
337
351
}
@@ -345,8 +359,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
345
359
| "asinf"
346
360
| "atanf"
347
361
=> {
362
+ let & [ f] = check_arg_count ( args) ?;
348
363
// 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 ( ) ?) ;
350
365
let f = match link_name {
351
366
"cbrtf" => f. cbrt ( ) ,
352
367
"coshf" => f. cosh ( ) ,
@@ -363,11 +378,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
363
378
| "hypotf"
364
379
| "atan2f"
365
380
=> {
381
+ let & [ f1, f2] = check_arg_count ( args) ?;
366
382
// underscore case for windows, here and below
367
383
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
368
384
// 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 ( ) ?) ;
371
387
let n = match link_name {
372
388
"_hypotf" | "hypotf" => f1. hypot ( f2) ,
373
389
"atan2f" => f1. atan2 ( f2) ,
@@ -383,8 +399,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
383
399
| "asin"
384
400
| "atan"
385
401
=> {
402
+ let & [ f] = check_arg_count ( args) ?;
386
403
// 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 ( ) ?) ;
388
405
let f = match link_name {
389
406
"cbrt" => f. cbrt ( ) ,
390
407
"cosh" => f. cosh ( ) ,
@@ -401,9 +418,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
401
418
| "hypot"
402
419
| "atan2"
403
420
=> {
421
+ let & [ f1, f2] = check_arg_count ( args) ?;
404
422
// 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 ( ) ?) ;
407
425
let n = match link_name {
408
426
"_hypot" | "hypot" => f1. hypot ( f2) ,
409
427
"atan2" => f1. atan2 ( f2) ,
@@ -415,9 +433,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
415
433
| "ldexp"
416
434
| "scalbn"
417
435
=> {
436
+ let & [ x, exp] = check_arg_count ( args) ?;
418
437
// 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 ( ) ?;
421
440
422
441
// Saturating cast to i16. Even those are outside the valid exponent range to
423
442
// `scalbn` below will do its over/underflow handling.
0 commit comments