Skip to content

Commit 1b0588b

Browse files
authored
Rollup merge of rust-lang#100897 - RalfJung:const-not-to-mutable, r=lcnr
extra sanity check against consts pointing to mutable memory This should be both unreachable and redundant (since we already ensure that validation only reads from read-only memory, when validating consts), but I feel like we cannot be paranoid enough here, and also if this ever fails it'll be a nicer error than the "cannot read from mutable memory" error.
2 parents 36f372e + cb4cd73 commit 1b0588b

7 files changed

+55
-37
lines changed

compiler/rustc_const_eval/src/interpret/validity.rs

+45-27
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::convert::TryFrom;
88
use std::fmt::Write;
99
use std::num::NonZeroUsize;
1010

11+
use rustc_ast::Mutability;
1112
use rustc_data_structures::fx::FxHashSet;
1213
use rustc_hir as hir;
1314
use rustc_middle::mir::interpret::InterpError;
@@ -423,34 +424,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
423424
// Proceed recursively even for ZST, no reason to skip them!
424425
// `!` is a ZST and we want to validate it.
425426
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.
427428
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(());
442457
}
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(..)) => {}
454472
}
455473
}
456474
let path = &self.path;
@@ -528,7 +546,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
528546
}
529547
ty::Ref(_, ty, mutbl) => {
530548
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
531-
&& *mutbl == hir::Mutability::Mut
549+
&& *mutbl == Mutability::Mut
532550
{
533551
// A mutable reference inside a const? That does not seem right (except if it is
534552
// a ZST).

src/test/ui/consts/const-points-to-static.32bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const-points-to-static.rs:6:1
33
|
44
LL | const TEST: &u8 = &MY_STATIC;
5-
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 4, align: 4) {

src/test/ui/consts/const-points-to-static.64bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const-points-to-static.rs:6:1
33
|
44
LL | const TEST: &u8 = &MY_STATIC;
5-
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 8, align: 8) {

src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const_refers_to_static2.rs:11:1
33
|
44
LL | const REF_INTERIOR_MUT: &usize = {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 4, align: 4) {
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
1313
--> $DIR/const_refers_to_static2.rs:18:1
1414
|
1515
LL | const READ_IMMUT: &usize = {
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
1717
|
1818
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1919
= note: the raw bytes of the constant (size: 4, align: 4) {

src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const_refers_to_static2.rs:11:1
33
|
44
LL | const REF_INTERIOR_MUT: &usize = {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 8, align: 8) {
@@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value
1313
--> $DIR/const_refers_to_static2.rs:18:1
1414
|
1515
LL | const READ_IMMUT: &usize = {
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
1717
|
1818
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1919
= note: the raw bytes of the constant (size: 8, align: 8) {

src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const_refers_to_static_cross_crate.rs:12:1
33
|
44
LL | const SLICE_MUT: &[u8; 1] = {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 4, align: 4) {
@@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value
1919
--> $DIR/const_refers_to_static_cross_crate.rs:17:1
2020
|
2121
LL | const U8_MUT: &u8 = {
22-
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
22+
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
2323
|
2424
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
2525
= note: the raw bytes of the constant (size: 4, align: 4) {

src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/const_refers_to_static_cross_crate.rs:12:1
33
|
44
LL | const SLICE_MUT: &[u8; 1] = {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
88
= note: the raw bytes of the constant (size: 8, align: 8) {
@@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value
1919
--> $DIR/const_refers_to_static_cross_crate.rs:17:1
2020
|
2121
LL | const U8_MUT: &u8 = {
22-
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable
22+
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
2323
|
2424
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
2525
= note: the raw bytes of the constant (size: 8, align: 8) {

0 commit comments

Comments
 (0)