From e8ffa2182bc41f3511a214a8ae6dad85d9d60e79 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 Apr 2020 23:48:22 +0200 Subject: [PATCH 1/6] better document const-pattern dynamic soundness checks, and fix a soundness hole --- src/librustc_mir/const_eval/eval_queries.rs | 2 +- src/librustc_mir/const_eval/machine.rs | 9 ++++++++- src/librustc_mir/interpret/validity.rs | 22 ++++++++++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 95c5d0f0b1059..d97546e4391b5 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -193,7 +193,7 @@ fn validate_and_turn_into_const<'tcx>( mplace.into(), path, &mut ref_tracking, - /*may_ref_to_static*/ is_static, + /*may_ref_to_static*/ ecx.memory.extra.can_access_statics, )?; } } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 84031ec0f1764..ce9d25599ff9a 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -99,7 +99,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { #[derive(Copy, Clone, Debug)] pub struct MemoryExtra { - /// Whether this machine may read from statics + /// We need to make sure consts never point to anything mutable, even recursively. That is + /// relied on for pattern matching on consts with references. + /// To achieve this, two pieces have to work together: + /// * Interning makes everything outside of statics immutable. + /// * Pointers to allocations inside of statics can never leak outside, to a non-static global. + /// This boolean here controls the second part. pub(super) can_access_statics: bool, } @@ -337,6 +342,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } else if static_def_id.is_some() { // Machine configuration does not allow us to read statics // (e.g., `const` initializer). + // See const_eval::machine::MemoryExtra::can_access_statics for why + // this check is so important. Err(ConstEvalErrKind::ConstAccessesStatic.into()) } else { // Immutable global, this read is fine. diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 838a5b32fc80b..df3c353220318 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -404,19 +404,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Skip validation entirely for some external statics let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { - // `extern static` cannot be validated as they have no body. - // FIXME: Statics from other crates are also skipped. - // They might be checked at a different type, but for now we - // want to avoid recursing too deeply. This is not sound! - if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { - return Ok(()); - } + // See const_eval::machine::MemoryExtra::can_access_statics for why + // this check is so important. + // This check is reachable when the const just referenced the static, + // but never read it (so we never entered `before_access_global`). + // We also need to do it here instead of going on to avoid running + // into the `before_access_global` check during validation. if !self.may_ref_to_static && self.ecx.tcx.is_static(did) { throw_validation_failure!( format_args!("a {} pointing to a static variable", kind), self.path ); } + // `extern static` cannot be validated as they have no body. + // FIXME: Statics from other crates are also skipped. + // They might be checked at a different type, but for now we + // want to avoid recursing too deeply. We might miss const-invalid data, + // but things are still sound otherwise (in particular re: consts + // referring to statics). + if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { + return Ok(()); + } } } // Proceed recursively even for ZST, no reason to skip them! From a84e2a0c91613e92ebf946d650b315aa2cd111a1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 Apr 2020 23:49:36 +0200 Subject: [PATCH 2/6] add test for const-ref-to-cross-crate-mutable-static --- .../auxiliary/static_cross_crate.rs | 1 + .../miri_unleashed/const_refers_to_static.rs | 3 +- .../const_refers_to_static.stderr | 16 ++++---- .../miri_unleashed/const_refers_to_static2.rs | 7 +++- .../const_refers_to_static2.stderr | 12 ++++-- .../const_refers_to_static_cross_crate.rs | 35 ++++++++++++++++ .../const_refers_to_static_cross_crate.stderr | 41 +++++++++++++++++++ 7 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr diff --git a/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs new file mode 100644 index 0000000000000..c86b724ac9438 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs @@ -0,0 +1 @@ +pub static mut ZERO: [u8; 1] = [0]; diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs index 11f4a30d1779b..6b205a2f66d9b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -7,7 +7,8 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; -// These tests only cause an error when *using* the const. +// These fail during CTFE (as they read a static), so they only cause an error +// when *using* the const. const MUTATE_INTERIOR_MUT: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 788762808f13b..acc3b637f58bc 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -1,47 +1,47 @@ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:14:5 + --> $DIR/const_refers_to_static.rs:15:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:14:5 + --> $DIR/const_refers_to_static.rs:15:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:21:17 + --> $DIR/const_refers_to_static.rs:22:17 | LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:26:32 + --> $DIR/const_refers_to_static.rs:27:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:26:32 + --> $DIR/const_refers_to_static.rs:27:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ error[E0080]: erroneous constant used - --> $DIR/const_refers_to_static.rs:31:5 + --> $DIR/const_refers_to_static.rs:32:5 | LL | MUTATE_INTERIOR_MUT; | ^^^^^^^^^^^^^^^^^^^ referenced constant has errors error[E0080]: erroneous constant used - --> $DIR/const_refers_to_static.rs:33:5 + --> $DIR/const_refers_to_static.rs:34:5 | LL | READ_INTERIOR_MUT; | ^^^^^^^^^^^^^^^^^ referenced constant has errors error[E0080]: erroneous constant used - --> $DIR/const_refers_to_static.rs:35:5 + --> $DIR/const_refers_to_static.rs:36:5 | LL | READ_MUT; | ^^^^^^^^ referenced constant has errors diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs index 2704f2a7d73c1..553d90f1891cc 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs @@ -6,9 +6,12 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; -// These tests cause immediate error when *defining* the const. +// These only fail during validation (they do not use but just create a reference to a static), +// so they cause an immediate error when *defining* the const. const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value +//~| NOTE encountered a reference pointing to a static variable +//~| NOTE static FOO: AtomicUsize = AtomicUsize::new(0); unsafe { &*(&FOO as *const _ as *const usize) } //~^ WARN skipping const checks @@ -16,6 +19,8 @@ const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this valu // ok some day perhaps const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value +//~| NOTE encountered a reference pointing to a static variable +//~| NOTE static FOO: usize = 0; &FOO //~^ WARN skipping const checks diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr index 2a233d63efef8..33f4a42605cce 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr @@ -1,19 +1,21 @@ warning: skipping const checks - --> $DIR/const_refers_to_static2.rs:13:18 + --> $DIR/const_refers_to_static2.rs:16:18 | LL | unsafe { &*(&FOO as *const _ as *const usize) } | ^^^ warning: skipping const checks - --> $DIR/const_refers_to_static2.rs:20:6 + --> $DIR/const_refers_to_static2.rs:25:6 | LL | &FOO | ^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static2.rs:11:1 + --> $DIR/const_refers_to_static2.rs:12:1 | LL | / const REF_INTERIOR_MUT: &usize = { +LL | | +LL | | LL | | static FOO: AtomicUsize = AtomicUsize::new(0); LL | | unsafe { &*(&FOO as *const _ as *const usize) } LL | | @@ -23,9 +25,11 @@ LL | | }; = 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. error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static2.rs:18:1 + --> $DIR/const_refers_to_static2.rs:21:1 | LL | / const READ_IMMUT: &usize = { +LL | | +LL | | LL | | static FOO: usize = 0; LL | | &FOO LL | | diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs new file mode 100644 index 0000000000000..cf277308c0895 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -0,0 +1,35 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// aux-build:static_cross_crate.rs +#![allow(const_err)] + +#![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] + +extern crate static_cross_crate; + +// Sneaky: reference to a mutable static. +// Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking! +const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value +//~| NOTE encountered a reference pointing to a static variable +//~| NOTE + unsafe { &static_cross_crate::ZERO } + //~^ WARN skipping const checks + //~| WARN skipping const checks +}; + +pub fn test(x: &[u8; 1]) -> bool { + match x { + SLICE_MUT => true, + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + &[1..] => false, + } +} + +fn main() { + unsafe { + static_cross_crate::ZERO[0] = 1; + } + // Now the pattern is not exhaustive any more! + test(&[0]); +} diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr new file mode 100644 index 0000000000000..dfee007c74049 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -0,0 +1,41 @@ +warning: skipping const checks + --> $DIR/const_refers_to_static_cross_crate.rs:15:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static_cross_crate.rs:15:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:12:1 + | +LL | / const SLICE_MUT: &[u8; 1] = { +LL | | +LL | | +LL | | unsafe { &static_cross_crate::ZERO } +LL | | +LL | | +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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. + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:22:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:22:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error: aborting due to 3 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. From a0898019485fd0920957444b7b387eec5f2b112d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 Apr 2020 23:54:47 +0200 Subject: [PATCH 3/6] clarify comment --- src/librustc_mir/const_eval/machine.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index ce9d25599ff9a..7c1ab261eb9c4 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -343,7 +343,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // Machine configuration does not allow us to read statics // (e.g., `const` initializer). // See const_eval::machine::MemoryExtra::can_access_statics for why - // this check is so important. + // this check is so important: if we could read statics, we could read pointers + // to mutable allocations *inside* statics. These allocations are not themselves + // statics, so pointers to them can get around the check in `validity.rs`. Err(ConstEvalErrKind::ConstAccessesStatic.into()) } else { // Immutable global, this read is fine. From 979bbf2ce1568f305fb52c2e10dc9db2375ce5bd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 10:47:16 +0200 Subject: [PATCH 4/6] also test reference into static field --- .../const_refers_to_static_cross_crate.rs | 19 ++++++++-- .../const_refers_to_static_cross_crate.stderr | 36 ++++++++++++------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index cf277308c0895..dd4982539174b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you +// compile-flags: -Zunleash-the-miri-inside-of-you -Zdeduplicate-diagnostics // aux-build:static_cross_crate.rs #![allow(const_err)] @@ -14,18 +14,31 @@ const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value //~| NOTE unsafe { &static_cross_crate::ZERO } //~^ WARN skipping const checks - //~| WARN skipping const checks +}; + +const SLICE_MUT2: &u8 = { //~ ERROR undefined behavior to use this value +//~| NOTE encountered a reference pointing to a static variable +//~| NOTE + unsafe { &static_cross_crate::ZERO[0] } + //~^ WARN skipping const checks }; pub fn test(x: &[u8; 1]) -> bool { match x { SLICE_MUT => true, //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern &[1..] => false, } } +pub fn test2(x: &u8) -> bool { + match x { + SLICE_MUT2 => true, + //~^ ERROR could not evaluate constant pattern + &(1..) => false, + } +} + fn main() { unsafe { static_cross_crate::ZERO[0] = 1; diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index dfee007c74049..b176dbd2e4d4c 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -4,12 +4,6 @@ warning: skipping const checks LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: skipping const checks - --> $DIR/const_refers_to_static_cross_crate.rs:15:15 - | -LL | unsafe { &static_cross_crate::ZERO } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | @@ -18,24 +12,42 @@ LL | | LL | | LL | | unsafe { &static_cross_crate::ZERO } LL | | -LL | | LL | | }; | |__^ type validation failed: encountered a reference pointing to a static variable | = 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. error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:22:9 + --> $DIR/const_refers_to_static_cross_crate.rs:28:9 | LL | SLICE_MUT => true, | ^^^^^^^^^ +warning: skipping const checks + --> $DIR/const_refers_to_static_cross_crate.rs:22:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:19:1 + | +LL | / const SLICE_MUT2: &u8 = { +LL | | +LL | | +LL | | unsafe { &static_cross_crate::ZERO[0] } +LL | | +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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. + error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:22:9 + --> $DIR/const_refers_to_static_cross_crate.rs:36:9 | -LL | SLICE_MUT => true, - | ^^^^^^^^^ +LL | SLICE_MUT2 => true, + | ^^^^^^^^^^ -error: aborting due to 3 previous errors; 2 warnings emitted +error: aborting due to 4 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0080`. From a03355dea0b7d042b8b4e01d75bba6c7489e3a14 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:55:05 +0200 Subject: [PATCH 5/6] some more test cases --- .../auxiliary/static_cross_crate.rs | 2 + .../const_refers_to_static_cross_crate.rs | 41 +++++++++- .../const_refers_to_static_cross_crate.stderr | 80 ++++++++++++++++--- 3 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs index c86b724ac9438..4fc6ae66a1242 100644 --- a/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs +++ b/src/test/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs @@ -1 +1,3 @@ pub static mut ZERO: [u8; 1] = [0]; +pub static ZERO_REF: &[u8; 1] = unsafe { &ZERO }; +pub static mut OPT_ZERO: Option = Some(0); diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index dd4982539174b..8bdb48e6f122f 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -2,8 +2,7 @@ // aux-build:static_cross_crate.rs #![allow(const_err)] -#![feature(exclusive_range_pattern)] -#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern, half_open_range_patterns, const_if_match, const_panic)] extern crate static_cross_crate; @@ -16,13 +15,29 @@ const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value //~^ WARN skipping const checks }; -const SLICE_MUT2: &u8 = { //~ ERROR undefined behavior to use this value +const U8_MUT: &u8 = { //~ ERROR undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable //~| NOTE unsafe { &static_cross_crate::ZERO[0] } //~^ WARN skipping const checks }; +// Also test indirection that reads from other static. This causes a const_err. +#[warn(const_err)] //~ NOTE +const U8_MUT2: &u8 = { //~ NOTE + unsafe { &(*static_cross_crate::ZERO_REF)[0] } + //~^ WARN skipping const checks + //~| WARN [const_err] + //~| NOTE constant accesses static +}; +#[warn(const_err)] //~ NOTE +const U8_MUT3: &u8 = { //~ NOTE + unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + //~^ WARN skipping const checks + //~| WARN [const_err] + //~| NOTE constant accesses static +}; + pub fn test(x: &[u8; 1]) -> bool { match x { SLICE_MUT => true, @@ -33,7 +48,24 @@ pub fn test(x: &[u8; 1]) -> bool { pub fn test2(x: &u8) -> bool { match x { - SLICE_MUT2 => true, + U8_MUT => true, + //~^ ERROR could not evaluate constant pattern + &(1..) => false, + } +} + +// We need to use these *in a pattern* to trigger the failure... likely because +// the errors above otherwise stop compilation too early? +pub fn test3(x: &u8) -> bool { + match x { + U8_MUT2 => true, + //~^ ERROR could not evaluate constant pattern + &(1..) => false, + } +} +pub fn test4(x: &u8) -> bool { + match x { + U8_MUT3 => true, //~^ ERROR could not evaluate constant pattern &(1..) => false, } @@ -45,4 +77,5 @@ fn main() { } // Now the pattern is not exhaustive any more! test(&[0]); + test2(&0); } diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index b176dbd2e4d4c..bc6375f3d5e0b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -1,11 +1,11 @@ warning: skipping const checks - --> $DIR/const_refers_to_static_cross_crate.rs:15:15 + --> $DIR/const_refers_to_static_cross_crate.rs:14:15 | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ 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:11:1 | LL | / const SLICE_MUT: &[u8; 1] = { LL | | @@ -18,21 +18,21 @@ LL | | }; = 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. error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:28:9 + --> $DIR/const_refers_to_static_cross_crate.rs:43:9 | LL | SLICE_MUT => true, | ^^^^^^^^^ warning: skipping const checks - --> $DIR/const_refers_to_static_cross_crate.rs:22:15 + --> $DIR/const_refers_to_static_cross_crate.rs:21:15 | LL | unsafe { &static_cross_crate::ZERO[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:19:1 + --> $DIR/const_refers_to_static_cross_crate.rs:18:1 | -LL | / const SLICE_MUT2: &u8 = { +LL | / const U8_MUT: &u8 = { LL | | LL | | LL | | unsafe { &static_cross_crate::ZERO[0] } @@ -43,11 +43,71 @@ LL | | }; = 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. error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:36:9 + --> $DIR/const_refers_to_static_cross_crate.rs:51:9 | -LL | SLICE_MUT2 => true, - | ^^^^^^^^^^ +LL | U8_MUT => true, + | ^^^^^^ -error: aborting due to 4 previous errors; 2 warnings emitted +warning: skipping const checks + --> $DIR/const_refers_to_static_cross_crate.rs:28:17 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static_cross_crate.rs:28:14 + | +LL | / const U8_MUT2: &u8 = { +LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static +LL | | +LL | | +LL | | +LL | | }; + | |__- + | +note: the lint level is defined here + --> $DIR/const_refers_to_static_cross_crate.rs:26:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:61:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static_cross_crate.rs:35:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static_cross_crate.rs:35:51 + | +LL | / const U8_MUT3: &u8 = { +LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | | ^^^^^^^^^^^ constant accesses static +LL | | +LL | | +LL | | +LL | | }; + | |__- + | +note: the lint level is defined here + --> $DIR/const_refers_to_static_cross_crate.rs:33:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:68:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +error: aborting due to 6 previous errors; 6 warnings emitted For more information about this error, try `rustc --explain E0080`. From 07772fcf6fca44217439154aa37e4854dd5aef34 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:56:40 +0200 Subject: [PATCH 6/6] expand comment in memory.rs with extra soundness concerns --- src/librustc_mir/interpret/memory.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0d0ed465c1cc6..8560594b583d4 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -453,7 +453,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID, // and the other one is maps to `GlobalAlloc::Memory`, this is returned by // `const_eval_raw` and it is the "resolved" ID. - // The resolved ID is never used by the interpreted progrma, it is hidden. + // The resolved ID is never used by the interpreted program, it is hidden. + // This is relied upon for soundness of const-patterns; a pointer to the resolved + // ID would "sidestep" the checks that make sure consts do not point to statics! // The `GlobalAlloc::Memory` branch here is still reachable though; when a static // contains a reference to memory that was created during its evaluation (i.e., not // to another static), those inner references only exist in "resolved" form.