about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2020-04-23 12:53:05 +0200
committerOliver Scherer <github35764891676564198441@oli-obk.de>2020-04-23 15:55:08 +0200
commitaf44cdf04fddf4d18efee49c0c683cb4bbce71fa (patch)
treed3e967dd0229bb51003535bb05aba1ecf135e312
parent2b25c0cd815f032b2c0b34d7d2316fbb20eda8de (diff)
downloadrust-af44cdf04fddf4d18efee49c0c683cb4bbce71fa.tar.gz
rust-af44cdf04fddf4d18efee49c0c683cb4bbce71fa.zip
Disallow statics initializing themselves
-rw-r--r--src/librustc_mir/interpret/memory.rs11
-rw-r--r--src/test/ui/consts/recursive-zst-static.rs8
-rw-r--r--src/test/ui/consts/recursive-zst-static.stderr21
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`.