@@ -290,7 +290,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
290
290
Ok ( val) => val,
291
291
Err ( err) => match err. kind {
292
292
EvalErrorKind :: PointerOutOfBounds { .. } |
293
- EvalErrorKind :: ReadUndefBytes =>
293
+ EvalErrorKind :: ReadUndefBytes ( _ ) =>
294
294
return validation_failure ! (
295
295
"uninitialized or out-of-bounds memory" , path
296
296
) ,
@@ -333,16 +333,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
333
333
// The fields don't need to correspond to any bit pattern of the union's fields.
334
334
// See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
335
335
} ,
336
- layout:: FieldPlacement :: Array { .. } if !dest. layout . is_zst ( ) => {
336
+ layout:: FieldPlacement :: Array { stride , .. } if !dest. layout . is_zst ( ) => {
337
337
let dest = dest. to_mem_place ( ) ; // non-ZST array/slice/str cannot be immediate
338
- // Special handling for strings to verify UTF-8
339
338
match dest. layout . ty . sty {
339
+ // Special handling for strings to verify UTF-8
340
340
ty:: Str => {
341
341
match self . read_str ( dest) {
342
342
Ok ( _) => { } ,
343
343
Err ( err) => match err. kind {
344
344
EvalErrorKind :: PointerOutOfBounds { .. } |
345
- EvalErrorKind :: ReadUndefBytes =>
345
+ EvalErrorKind :: ReadUndefBytes ( _ ) =>
346
346
// The error here looks slightly different than it does
347
347
// for slices, because we do not report the index into the
348
348
// str at which we are OOB.
@@ -356,6 +356,55 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
356
356
}
357
357
}
358
358
}
359
+ // Special handling for arrays/slices of builtin integer types
360
+ ty:: Array ( tys, ..) | ty:: Slice ( tys) if {
361
+ // This optimization applies only for integer types
362
+ match tys. sty {
363
+ ty:: Int ( ..) | ty:: Uint ( ..) => true ,
364
+ _ => false ,
365
+ }
366
+ } => {
367
+ // This is the length of the array/slice.
368
+ let len = dest. len ( self ) ?;
369
+ // Since primitive types are naturally aligned and tightly packed in arrays,
370
+ // we can use the stride to get the size of the integral type.
371
+ let ty_size = stride. bytes ( ) ;
372
+ // This is the size in bytes of the whole array.
373
+ let size = Size :: from_bytes ( ty_size * len) ;
374
+
375
+ match self . memory . read_bytes ( dest. ptr , size) {
376
+ // In the happy case, we needn't check anything else.
377
+ Ok ( _) => { } ,
378
+ // Some error happened, try to provide a more detailed description.
379
+ Err ( err) => {
380
+ // For some errors we might be able to provide extra information
381
+ match err. kind {
382
+ EvalErrorKind :: ReadUndefBytes ( offset) => {
383
+ // Some byte was undefined, determine which
384
+ // element that byte belongs to so we can
385
+ // provide an index.
386
+ let i = ( offset. bytes ( ) / ty_size) as usize ;
387
+ path. push ( PathElem :: ArrayElem ( i) ) ;
388
+
389
+ return validation_failure ! (
390
+ "undefined bytes" , path
391
+ )
392
+ } ,
393
+ EvalErrorKind :: PointerOutOfBounds { allocation_size, .. } => {
394
+ // If the array access is out-of-bounds, the first
395
+ // undefined access is the after the end of the array.
396
+ let i = ( allocation_size. bytes ( ) * ty_size) as usize ;
397
+ path. push ( PathElem :: ArrayElem ( i) ) ;
398
+ } ,
399
+ _ => ( ) ,
400
+ }
401
+
402
+ return validation_failure ! (
403
+ "uninitialized or out-of-bounds memory" , path
404
+ )
405
+ }
406
+ }
407
+ } ,
359
408
_ => {
360
409
// This handles the unsized case correctly as well, as well as
361
410
// SIMD an all sorts of other array-like types.
0 commit comments