extra sanity check against consts pointing to mutable memory

This commit is contained in:
Ralf Jung 2022-08-22 21:25:03 -04:00
parent 015a824f2d
commit cb4cd73664
7 changed files with 55 additions and 37 deletions

View File

@ -8,6 +8,7 @@ use std::convert::TryFrom;
use std::fmt::Write; use std::fmt::Write;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::mir::interpret::InterpError; use rustc_middle::mir::interpret::InterpError;
@ -411,34 +412,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// Proceed recursively even for ZST, no reason to skip them! // Proceed recursively even for ZST, no reason to skip them!
// `!` is a ZST and we want to validate it. // `!` is a ZST and we want to validate it.
if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
// Special handling for pointers to statics (irrespective of their type). // Let's see what kind of memory this points to.
let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id); let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id);
if let Some(GlobalAlloc::Static(did)) = alloc_kind { match alloc_kind {
assert!(!self.ecx.tcx.is_thread_local_static(did)); Some(GlobalAlloc::Static(did)) => {
assert!(self.ecx.tcx.is_static(did)); // Special handling for pointers to statics (irrespective of their type).
if matches!( assert!(!self.ecx.tcx.is_thread_local_static(did));
self.ctfe_mode, assert!(self.ecx.tcx.is_static(did));
Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. }) if matches!(
) { self.ctfe_mode,
// See const_eval::machine::MemoryExtra::can_access_statics for why Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. })
// this check is so important. ) {
// This check is reachable when the const just referenced the static, // See const_eval::machine::MemoryExtra::can_access_statics for why
// but never read it (so we never entered `before_access_global`). // this check is so important.
throw_validation_failure!(self.path, // This check is reachable when the const just referenced the static,
{ "a {} pointing to a static variable", kind } // but never read it (so we never entered `before_access_global`).
); throw_validation_failure!(self.path,
{ "a {} pointing to a static variable in a constant", kind }
);
}
// We skip recursively checking other statics. These statics must be sound by
// themselves, and the only way to get broken statics here is by using
// unsafe code.
// The reasons we don't check other statics is twofold. For one, in all
// sound cases, the static was already validated on its own, and second, we
// trigger cycle errors if we try to compute the value of the other static
// and that static refers back to us.
// We might miss const-invalid data,
// but things are still sound otherwise (in particular re: consts
// referring to statics).
return Ok(());
} }
// We skip checking other statics. These statics must be sound by Some(GlobalAlloc::Memory(alloc)) => {
// themselves, and the only way to get broken statics here is by using if alloc.inner().mutability == Mutability::Mut
// unsafe code. && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
// The reasons we don't check other statics is twofold. For one, in all {
// sound cases, the static was already validated on its own, and second, we // This should be unreachable, but if someone manages to copy a pointer
// trigger cycle errors if we try to compute the value of the other static // out of a `static`, then that pointer might point to mutable memory,
// and that static refers back to us. // and we would catch that here.
// We might miss const-invalid data, throw_validation_failure!(self.path,
// but things are still sound otherwise (in particular re: consts { "a {} pointing to mutable memory in a constant", kind }
// referring to statics). );
return Ok(()); }
}
// Nothing to check for these.
None | Some(GlobalAlloc::Function(..) | GlobalAlloc::VTable(..)) => {}
} }
} }
let path = &self.path; let path = &self.path;
@ -544,7 +562,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
} }
ty::Ref(_, ty, mutbl) => { ty::Ref(_, ty, mutbl) => {
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
&& *mutbl == hir::Mutability::Mut && *mutbl == Mutability::Mut
{ {
// A mutable reference inside a const? That does not seem right (except if it is // A mutable reference inside a const? That does not seem right (except if it is
// a ZST). // a ZST).

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const-points-to-static.rs:6:1 --> $DIR/const-points-to-static.rs:6:1
| |
LL | const TEST: &u8 = &MY_STATIC; LL | const TEST: &u8 = &MY_STATIC;
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 4, align: 4) { = note: the raw bytes of the constant (size: 4, align: 4) {

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const-points-to-static.rs:6:1 --> $DIR/const-points-to-static.rs:6:1
| |
LL | const TEST: &u8 = &MY_STATIC; LL | const TEST: &u8 = &MY_STATIC;
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 8, align: 8) { = note: the raw bytes of the constant (size: 8, align: 8) {

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static2.rs:11:1 --> $DIR/const_refers_to_static2.rs:11:1
| |
LL | const REF_INTERIOR_MUT: &usize = { LL | const REF_INTERIOR_MUT: &usize = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 4, align: 4) { = 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
--> $DIR/const_refers_to_static2.rs:18:1 --> $DIR/const_refers_to_static2.rs:18:1
| |
LL | const READ_IMMUT: &usize = { LL | const READ_IMMUT: &usize = {
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 4, align: 4) { = note: the raw bytes of the constant (size: 4, align: 4) {

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static2.rs:11:1 --> $DIR/const_refers_to_static2.rs:11:1
| |
LL | const REF_INTERIOR_MUT: &usize = { LL | const REF_INTERIOR_MUT: &usize = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 8, align: 8) { = 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
--> $DIR/const_refers_to_static2.rs:18:1 --> $DIR/const_refers_to_static2.rs:18:1
| |
LL | const READ_IMMUT: &usize = { LL | const READ_IMMUT: &usize = {
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 8, align: 8) { = note: the raw bytes of the constant (size: 8, align: 8) {

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static_cross_crate.rs:12:1 --> $DIR/const_refers_to_static_cross_crate.rs:12:1
| |
LL | const SLICE_MUT: &[u8; 1] = { LL | const SLICE_MUT: &[u8; 1] = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 4, align: 4) { = 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
--> $DIR/const_refers_to_static_cross_crate.rs:17:1 --> $DIR/const_refers_to_static_cross_crate.rs:17:1
| |
LL | const U8_MUT: &u8 = { LL | const U8_MUT: &u8 = {
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 4, align: 4) { = note: the raw bytes of the constant (size: 4, align: 4) {

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/const_refers_to_static_cross_crate.rs:12:1 --> $DIR/const_refers_to_static_cross_crate.rs:12:1
| |
LL | const SLICE_MUT: &[u8; 1] = { LL | const SLICE_MUT: &[u8; 1] = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 8, align: 8) { = 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
--> $DIR/const_refers_to_static_cross_crate.rs:17:1 --> $DIR/const_refers_to_static_cross_crate.rs:17:1
| |
LL | const U8_MUT: &u8 = { LL | const U8_MUT: &u8 = {
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
| |
= 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. = 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.
= note: the raw bytes of the constant (size: 8, align: 8) { = note: the raw bytes of the constant (size: 8, align: 8) {