Skip to content

Commit 2cd8af2

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 55cfe1f + cb4cd73 commit 2cd8af2

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;
@@ -411,34 +412,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
411412
// Proceed recursively even for ZST, no reason to skip them!
412413
// `!` is a ZST and we want to validate it.
413414
if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
414-
// Special handling for pointers to statics (irrespective of their type).
415+
// Let's see what kind of memory this points to.
415416
let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id);
416-
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
417-
assert!(!self.ecx.tcx.is_thread_local_static(did));
418-
assert!(self.ecx.tcx.is_static(did));
419-
if matches!(
420-
self.ctfe_mode,
421-
Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. })
422-
) {
423-
// See const_eval::machine::MemoryExtra::can_access_statics for why
424-
// this check is so important.
425-
// This check is reachable when the const just referenced the static,
426-
// but never read it (so we never entered `before_access_global`).
427-
throw_validation_failure!(self.path,
428-
{ "a {} pointing to a static variable", kind }
429-
);
417+
match alloc_kind {
418+
Some(GlobalAlloc::Static(did)) => {
419+
// Special handling for pointers to statics (irrespective of their type).
420+
assert!(!self.ecx.tcx.is_thread_local_static(did));
421+
assert!(self.ecx.tcx.is_static(did));
422+
if matches!(
423+
self.ctfe_mode,
424+
Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. })
425+
) {
426+
// See const_eval::machine::MemoryExtra::can_access_statics for why
427+
// this check is so important.
428+
// This check is reachable when the const just referenced the static,
429+
// but never read it (so we never entered `before_access_global`).
430+
throw_validation_failure!(self.path,
431+
{ "a {} pointing to a static variable in a constant", kind }
432+
);
433+
}
434+
// We skip recursively checking other statics. These statics must be sound by
435+
// themselves, and the only way to get broken statics here is by using
436+
// unsafe code.
437+
// The reasons we don't check other statics is twofold. For one, in all
438+
// sound cases, the static was already validated on its own, and second, we
439+
// trigger cycle errors if we try to compute the value of the other static
440+
// and that static refers back to us.
441+
// We might miss const-invalid data,
442+
// but things are still sound otherwise (in particular re: consts
443+
// referring to statics).
444+
return Ok(());
430445
}
431-
// We skip checking other statics. These statics must be sound by
432-
// themselves, and the only way to get broken statics here is by using
433-
// unsafe code.
434-
// The reasons we don't check other statics is twofold. For one, in all
435-
// sound cases, the static was already validated on its own, and second, we
436-
// trigger cycle errors if we try to compute the value of the other static
437-
// and that static refers back to us.
438-
// We might miss const-invalid data,
439-
// but things are still sound otherwise (in particular re: consts
440-
// referring to statics).
441-
return Ok(());
446+
Some(GlobalAlloc::Memory(alloc)) => {
447+
if alloc.inner().mutability == Mutability::Mut
448+
&& matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
449+
{
450+
// This should be unreachable, but if someone manages to copy a pointer
451+
// out of a `static`, then that pointer might point to mutable memory,
452+
// and we would catch that here.
453+
throw_validation_failure!(self.path,
454+
{ "a {} pointing to mutable memory in a constant", kind }
455+
);
456+
}
457+
}
458+
// Nothing to check for these.
459+
None | Some(GlobalAlloc::Function(..) | GlobalAlloc::VTable(..)) => {}
442460
}
443461
}
444462
let path = &self.path;
@@ -544,7 +562,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
544562
}
545563
ty::Ref(_, ty, mutbl) => {
546564
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
547-
&& *mutbl == hir::Mutability::Mut
565+
&& *mutbl == Mutability::Mut
548566
{
549567
// A mutable reference inside a const? That does not seem right (except if it is
550568
// 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)