diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2020-04-23 12:53:05 +0200 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2020-04-23 15:55:08 +0200 |
| commit | af44cdf04fddf4d18efee49c0c683cb4bbce71fa (patch) | |
| tree | d3e967dd0229bb51003535bb05aba1ecf135e312 | |
| parent | 2b25c0cd815f032b2c0b34d7d2316fbb20eda8de (diff) | |
| download | rust-af44cdf04fddf4d18efee49c0c683cb4bbce71fa.tar.gz rust-af44cdf04fddf4d18efee49c0c683cb4bbce71fa.zip | |
Disallow statics initializing themselves
| -rw-r--r-- | src/librustc_mir/interpret/memory.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/consts/recursive-zst-static.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/consts/recursive-zst-static.stderr | 21 |
3 files changed, 37 insertions, 3 deletions
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index bcad7855c37..43b2f0e9110 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -400,7 +400,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // We can still be zero-sized in this branch, in which case we have to // return `None`. - if size.bytes() == 0 { None } else { Some(ptr) } + if size.bytes() == 0 { + // We may be reading from a static. + // In order to ensure that `static FOO: Type = FOO;` causes a cycle error + // instead of magically pulling *any* ZST value from the ether, we need to + // trigger a read here. + self.get_raw(ptr.alloc_id)?; + None + } else { + Some(ptr) + } } }) } diff --git a/src/test/ui/consts/recursive-zst-static.rs b/src/test/ui/consts/recursive-zst-static.rs index df7562bd9f5..768df58e1e3 100644 --- a/src/test/ui/consts/recursive-zst-static.rs +++ b/src/test/ui/consts/recursive-zst-static.rs @@ -1,6 +1,10 @@ -// build-pass +// This test ensures that we do not allow ZST statics to initialize themselves without ever +// actually creating a value of that type. This is important, as the ZST may have private fields +// that users can reasonably expect to only get initialized by their own code. Thus unsafe code +// can depend on this fact and will thus do unsound things when it is violated. +// See https://github.com/rust-lang/rust/issues/71078 for more details. -static FOO: () = FOO; +static FOO: () = FOO; //~ cycle detected when const-evaluating `FOO` fn main() { FOO diff --git a/src/test/ui/consts/recursive-zst-static.stderr b/src/test/ui/consts/recursive-zst-static.stderr new file mode 100644 index 00000000000..e21dcf691ab --- /dev/null +++ b/src/test/ui/consts/recursive-zst-static.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating `FOO` + --> $DIR/recursive-zst-static.rs:7:18 + | +LL | static FOO: () = FOO; + | ^^^ + | +note: ...which requires const-evaluating `FOO`... + --> $DIR/recursive-zst-static.rs:7:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `FOO`, completing the cycle +note: cycle used when const-evaluating + checking `FOO` + --> $DIR/recursive-zst-static.rs:7:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. |
