From 59eff14120a067d04832142c8198f0132db2acb0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 13:49:07 +0100 Subject: [PATCH] Also catch static mutation at evaluation time --- src/librustc/ich/impls_ty.rs | 1 + src/librustc/mir/interpret/error.rs | 3 ++ src/librustc_mir/interpret/memory.rs | 8 ++--- src/librustc_mir/transform/const_prop.rs | 1 + src/librustc_mir/transform/qualify_consts.rs | 7 ++++- .../assign-to-static-within-other-static-2.rs | 30 +++++++++++++++++++ ...ign-to-static-within-other-static-2.stderr | 9 ++++++ .../assign-to-static-within-other-static.rs | 17 ++--------- ...ssign-to-static-within-other-static.stderr | 6 ++-- src/test/ui/error-codes/E0017.rs | 1 + src/test/ui/error-codes/E0017.stderr | 10 +++++-- src/test/ui/error-codes/E0388.rs | 1 + src/test/ui/error-codes/E0388.stderr | 10 +++++-- src/test/ui/write-to-static-mut-in-static.rs | 4 +-- .../ui/write-to-static-mut-in-static.stderr | 9 ++---- 15 files changed, 82 insertions(+), 35 deletions(-) create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f3a62975dd9f..fc970400f6cc 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -423,6 +423,7 @@ impl_stable_hash_for!( CalledClosureAsFunction, VtableForArgumentlessMethod, ModifiedConstantMemory, + ModifiedStatic, AssumptionNotHeld, InlineAsm, ReallocateNonBasePtr, diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f28aa41ed422..5895b6cab9ab 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -276,6 +276,7 @@ pub enum EvalErrorKind<'tcx, O> { CalledClosureAsFunction, VtableForArgumentlessMethod, ModifiedConstantMemory, + ModifiedStatic, AssumptionNotHeld, InlineAsm, TypeNotPrimitive(Ty<'tcx>), @@ -380,6 +381,8 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { "tried to call a vtable function without arguments", ModifiedConstantMemory => "tried to modify constant memory", + ModifiedStatic => + "tried to modify a static's initial value from another static's initializer", AssumptionNotHeld => "`assume` argument was false", InlineAsm => diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index e125927e7d27..68a91b0a3bd2 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -423,10 +423,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if alloc.mutability == Mutability::Immutable { return err!(ModifiedConstantMemory); } - let kind = M::STATIC_KIND.expect( - "An allocation is being mutated but the machine does not expect that to happen" - ); - Ok((MemoryKind::Machine(kind), alloc.into_owned())) + match M::STATIC_KIND { + Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())), + None => err!(ModifiedStatic), + } }); // Unpack the error type manually because type inference doesn't // work otherwise (and we cannot help it because `impl Trait`) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 885d70dc4304..51327464266d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -197,6 +197,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { | CalledClosureAsFunction | VtableForArgumentlessMethod | ModifiedConstantMemory + | ModifiedStatic | AssumptionNotHeld // FIXME: should probably be removed and turned into a bug! call | TypeNotPrimitive(_) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 31a0dc1494ce..1371b9a99770 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -249,7 +249,8 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { match dest { Place::Local(index) => break *index, Place::Projection(proj) => dest = &proj.base, - Place::Promoted(..) | Place::Static(..) => { + Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"), + Place::Static(..) => { // Catch more errors in the destination. self.visit_place( dest, @@ -495,6 +496,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { if context.is_mutating_use() { + // this is not strictly necessary as miri will also bail out + // For interior mutability we can't really catch this statically as that + // goes through raw pointers and intermediate temporaries, so miri has + // to catch this anyway self.tcx.sess.span_err( self.span, "cannot mutate statics in the initializer of another static", diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs new file mode 100644 index 000000000000..ef0de61d219a --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs @@ -0,0 +1,30 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never compile successfully + +#![feature(const_raw_ptr_deref)] +#![feature(const_let)] + +use std::cell::UnsafeCell; + +struct Foo(UnsafeCell); + +unsafe impl Send for Foo {} +unsafe impl Sync for Foo {} + +static FOO: Foo = Foo(UnsafeCell::new(42)); + +static BAR: () = unsafe { + *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr new file mode 100644 index 000000000000..0892b05a69df --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/assign-to-static-within-other-static-2.rs:27:5 + | +LL | *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer + | ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs index 5113d73b3841..6f16f644eec6 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -16,20 +16,9 @@ use std::cell::UnsafeCell; -struct Foo(UnsafeCell); - -unsafe impl Send for Foo {} -unsafe impl Sync for Foo {} - -static FOO: Foo = Foo(UnsafeCell::new(42)); - -static BAR: () = unsafe { - *FOO.0.get() = 5; -}; - -static mut FOO2: u32 = 42; -static BOO2: () = unsafe { - FOO2 = 5; +static mut FOO: u32 = 42; +static BOO: () = unsafe { + FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static }; fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr index 87f02e8e4cf7..ca652c9df32a 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -1,8 +1,8 @@ error: cannot mutate statics in the initializer of another static - --> $DIR/assign-to-static-within-other-static.rs:32:5 + --> $DIR/assign-to-static-within-other-static.rs:21:5 | -LL | FOO2 = 5; - | ^^^^^^^^ +LL | FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs index c98c35a1442a..bf400fde365b 100644 --- a/src/test/ui/error-codes/E0017.rs +++ b/src/test/ui/error-codes/E0017.rs @@ -14,5 +14,6 @@ const C: i32 = 2; const CR: &'static mut i32 = &mut C; //~ ERROR E0017 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| ERROR cannot borrow + //~| ERROR cannot mutate statics static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 fn main() {} diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index 411b9f313978..94a90d92d3e7 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0017.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0017.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^ error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0017.rs:17:38 + --> $DIR/E0017.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs index c002badfef64..3203798c7095 100644 --- a/src/test/ui/error-codes/E0388.rs +++ b/src/test/ui/error-codes/E0388.rs @@ -14,6 +14,7 @@ const C: i32 = 2; const CR: &'static mut i32 = &mut C; //~ ERROR E0017 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| ERROR cannot borrow + //~| ERROR cannot mutate statics static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 fn main() {} diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index d2263cd4034b..46efda9147b6 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0388.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0388.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^ error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0388.rs:17:38 + --> $DIR/E0388.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 1ea74f73723b..191f09b54ee7 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR statements in statics are unstable +//~^ ERROR cannot mutate statics in the initializer of another static pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR statements in statics are unstable +//~^ ERROR cannot mutate statics in the initializer of another static pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index f07d240746fd..673a71b4642f 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,19 +1,14 @@ -error[E0658]: statements in statics are unstable (see issue #48821) +error: cannot mutate statics in the initializer of another static --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable -error[E0658]: statements in statics are unstable (see issue #48821) +error: cannot mutate statics in the initializer of another static --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`.