@@ -8,6 +8,7 @@ use std::convert::TryFrom;
8
8
use std:: fmt:: Write ;
9
9
use std:: num:: NonZeroUsize ;
10
10
11
+ use rustc_ast:: Mutability ;
11
12
use rustc_data_structures:: fx:: FxHashSet ;
12
13
use rustc_hir as hir;
13
14
use rustc_middle:: mir:: interpret:: InterpError ;
@@ -423,34 +424,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
423
424
// Proceed recursively even for ZST, no reason to skip them!
424
425
// `!` is a ZST and we want to validate it.
425
426
if let Ok ( ( alloc_id, _offset, _prov) ) = self . ecx . ptr_try_get_alloc_id ( place. ptr ) {
426
- // Special handling for pointers to statics (irrespective of their type) .
427
+ // Let's see what kind of memory this points to .
427
428
let alloc_kind = self . ecx . tcx . try_get_global_alloc ( alloc_id) ;
428
- if let Some ( GlobalAlloc :: Static ( did) ) = alloc_kind {
429
- assert ! ( !self . ecx. tcx. is_thread_local_static( did) ) ;
430
- assert ! ( self . ecx. tcx. is_static( did) ) ;
431
- if matches ! (
432
- self . ctfe_mode,
433
- Some ( CtfeValidationMode :: Const { allow_static_ptrs: false , .. } )
434
- ) {
435
- // See const_eval::machine::MemoryExtra::can_access_statics for why
436
- // this check is so important.
437
- // This check is reachable when the const just referenced the static,
438
- // but never read it (so we never entered `before_access_global`).
439
- throw_validation_failure ! ( self . path,
440
- { "a {} pointing to a static variable" , kind }
441
- ) ;
429
+ match alloc_kind {
430
+ Some ( GlobalAlloc :: Static ( did) ) => {
431
+ // Special handling for pointers to statics (irrespective of their type).
432
+ assert ! ( !self . ecx. tcx. is_thread_local_static( did) ) ;
433
+ assert ! ( self . ecx. tcx. is_static( did) ) ;
434
+ if matches ! (
435
+ self . ctfe_mode,
436
+ Some ( CtfeValidationMode :: Const { allow_static_ptrs: false , .. } )
437
+ ) {
438
+ // See const_eval::machine::MemoryExtra::can_access_statics for why
439
+ // this check is so important.
440
+ // This check is reachable when the const just referenced the static,
441
+ // but never read it (so we never entered `before_access_global`).
442
+ throw_validation_failure ! ( self . path,
443
+ { "a {} pointing to a static variable in a constant" , kind }
444
+ ) ;
445
+ }
446
+ // We skip recursively checking other statics. These statics must be sound by
447
+ // themselves, and the only way to get broken statics here is by using
448
+ // unsafe code.
449
+ // The reasons we don't check other statics is twofold. For one, in all
450
+ // sound cases, the static was already validated on its own, and second, we
451
+ // trigger cycle errors if we try to compute the value of the other static
452
+ // and that static refers back to us.
453
+ // We might miss const-invalid data,
454
+ // but things are still sound otherwise (in particular re: consts
455
+ // referring to statics).
456
+ return Ok ( ( ) ) ;
442
457
}
443
- // We skip checking other statics. These statics must be sound by
444
- // themselves, and the only way to get broken statics here is by using
445
- // unsafe code.
446
- // The reasons we don't check other statics is twofold. For one, in all
447
- // sound cases, the static was already validated on its own, and second, we
448
- // trigger cycle errors if we try to compute the value of the other static
449
- // and that static refers back to us.
450
- // We might miss const-invalid data,
451
- // but things are still sound otherwise (in particular re: consts
452
- // referring to statics).
453
- return Ok ( ( ) ) ;
458
+ Some ( GlobalAlloc :: Memory ( alloc) ) => {
459
+ if alloc. inner ( ) . mutability == Mutability :: Mut
460
+ && matches ! ( self . ctfe_mode, Some ( CtfeValidationMode :: Const { .. } ) )
461
+ {
462
+ // This should be unreachable, but if someone manages to copy a pointer
463
+ // out of a `static`, then that pointer might point to mutable memory,
464
+ // and we would catch that here.
465
+ throw_validation_failure ! ( self . path,
466
+ { "a {} pointing to mutable memory in a constant" , kind }
467
+ ) ;
468
+ }
469
+ }
470
+ // Nothing to check for these.
471
+ None | Some ( GlobalAlloc :: Function ( ..) | GlobalAlloc :: VTable ( ..) ) => { }
454
472
}
455
473
}
456
474
let path = & self . path ;
@@ -528,7 +546,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
528
546
}
529
547
ty:: Ref ( _, ty, mutbl) => {
530
548
if matches ! ( self . ctfe_mode, Some ( CtfeValidationMode :: Const { .. } ) )
531
- && * mutbl == hir :: Mutability :: Mut
549
+ && * mutbl == Mutability :: Mut
532
550
{
533
551
// A mutable reference inside a const? That does not seem right (except if it is
534
552
// a ZST).
0 commit comments