Skip to content

Commit

Permalink
Validate nested static items
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Apr 17, 2024
1 parent 6c6b302 commit 8c9cba2
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 85 deletions.
26 changes: 19 additions & 7 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// Special handling for pointers to statics (irrespective of their type).
assert!(!self.ecx.tcx.is_thread_local_static(did));
assert!(self.ecx.tcx.is_static(did));
let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did)
else {
bug!()
};
// Mode-specific checks
match self.ctfe_mode {
Some(
Expand All @@ -471,7 +475,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// trigger cycle errors if we try to compute the value of the other static
// and that static refers back to us (potentially through a promoted).
// This could miss some UB, but that's fine.
skip_recursive_check = true;
// We still walk nested allocations, as they are fundamentally part of this validation run.
// This means we will also recurse into nested statics of *other*
// statics, even though we do not recurse into other statics directly.
// That's somewhat inconsistent but harmless.
skip_recursive_check = !nested;
}
Some(CtfeValidationMode::Const { .. }) => {
// We can't recursively validate `extern static`, so we better reject them.
Expand All @@ -483,10 +491,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
}
// Return alloc mutability. For "root" statics we look at the type to account for interior
// mutability; for nested statics we have no type and directly use the annotated mutability.
let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did)
else {
bug!()
};
match (mutability, nested) {
(Mutability::Mut, _) => Mutability::Mut,
(Mutability::Not, true) => Mutability::Not,
Expand Down Expand Up @@ -709,8 +713,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
if let Some(mplace) = op.as_mplace_or_imm().left() {
if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
let mutability = match self.ecx.tcx.global_alloc(alloc_id) {
GlobalAlloc::Static(_) => {
self.ecx.memory.alloc_map.get(alloc_id).unwrap().1.mutability
GlobalAlloc::Static(did) => {
let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did)
else {
bug!()
};
if nested {
mutability
} else {
self.ecx.memory.alloc_map.get(alloc_id).unwrap().1.mutability
}
}
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
_ => span_bug!(self.ecx.tcx.span, "not a memory allocation"),
Expand Down
17 changes: 0 additions & 17 deletions tests/crashes/122548.rs

This file was deleted.

2 changes: 2 additions & 0 deletions tests/ui/consts/miri_unleashed/mutable_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::cell::UnsafeCell;
static FOO: &&mut u32 = &&mut 42;
//~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler
//~| ERROR it is undefined behavior to use this value

static BAR: &mut () = &mut ();
//~^ ERROR encountered mutable pointer in final value of static
Expand All @@ -28,6 +29,7 @@ unsafe impl Sync for Meh {}
static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
//~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler
//~| ERROR it is undefined behavior to use this value

static OH_YES: &mut i32 = &mut 42;
//~^ ERROR encountered mutable pointer in final value of static
Expand Down
52 changes: 37 additions & 15 deletions tests/ui/consts/miri_unleashed/mutable_references.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,19 @@ note: the lint level is defined here
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:10:1
|
LL | static FOO: &&mut u32 = &&mut 42;
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered mutable reference or box pointing to read-only memory
|
= 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: $SIZE, align: $ALIGN) {
HEX_DUMP
}

error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:14:1
--> $DIR/mutable_references.rs:15:1
|
LL | static BAR: &mut () = &mut ();
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -22,7 +33,7 @@ LL | static BAR: &mut () = &mut ();
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>

error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:20:1
--> $DIR/mutable_references.rs:21:1
|
LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -31,16 +42,27 @@ LL | static BOO: &mut Foo<()> = &mut Foo(());
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>

error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:28:1
--> $DIR/mutable_references.rs:29:1
|
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>

error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:29:1
|
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
|
= 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: $SIZE, align: $ALIGN) {
HEX_DUMP
}

error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:32:1
--> $DIR/mutable_references.rs:34:1
|
LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -49,7 +71,7 @@ LL | static OH_YES: &mut i32 = &mut 42;
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>

error[E0080]: it is undefined behavior to use this value
--> $DIR/mutable_references.rs:32:1
--> $DIR/mutable_references.rs:34:1
|
LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
Expand All @@ -60,7 +82,7 @@ LL | static OH_YES: &mut i32 = &mut 42;
}

error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
--> $DIR/mutable_references.rs:41:5
--> $DIR/mutable_references.rs:43:5
|
LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign
Expand All @@ -73,27 +95,27 @@ help: skipping check that does not even have a feature gate
LL | static FOO: &&mut u32 = &&mut 42;
| ^^^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:14:23
--> $DIR/mutable_references.rs:15:23
|
LL | static BAR: &mut () = &mut ();
| ^^^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:20:28
--> $DIR/mutable_references.rs:21:28
|
LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:28:28
--> $DIR/mutable_references.rs:29:28
|
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/mutable_references.rs:32:27
--> $DIR/mutable_references.rs:34:27
|
LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^

error: aborting due to 7 previous errors; 1 warning emitted
error: aborting due to 9 previous errors; 1 warning emitted

Some errors have detailed explanations: E0080, E0594.
For more information about an error, try `rustc --explain E0080`.
Expand All @@ -114,7 +136,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)]

Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:14:1
--> $DIR/mutable_references.rs:15:1
|
LL | static BAR: &mut () = &mut ();
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -129,7 +151,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)]

Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:20:1
--> $DIR/mutable_references.rs:21:1
|
LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -144,7 +166,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)]

Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:28:1
--> $DIR/mutable_references.rs:29:1
|
LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^
Expand All @@ -159,7 +181,7 @@ LL | #![deny(const_eval_mutable_ptr_in_final_value)]

Future breakage diagnostic:
error: encountered mutable pointer in final value of static
--> $DIR/mutable_references.rs:32:1
--> $DIR/mutable_references.rs:34:1
|
LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
Loading

0 comments on commit 8c9cba2

Please sign in to comment.