about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-04-14 23:29:52 +0200
committerGitHub <noreply@github.com>2020-04-14 23:29:52 +0200
commitb5dc6e620b68665a1d0aa79ee2e2ed2dd2b4d130 (patch)
tree1a46683721bce285b2bbcb49c7f60066483e6cfb
parent15ab586b495376bd8e1a591e8a80e6f976251eb5 (diff)
parenta1f7e9a7250aea6f415fd62e88bbcb848baf73ff (diff)
downloadrust-b5dc6e620b68665a1d0aa79ee2e2ed2dd2b4d130.tar.gz
rust-b5dc6e620b68665a1d0aa79ee2e2ed2dd2b4d130.zip
Rollup merge of #70947 - RalfJung:ctfe-no-read-mut-global, r=oli-obk
tighten CTFE safety net for accesses to globals

Previously, we only rejected reading from all statics. Now we also reject reading from any mutable global. Mutable globals are the true culprit here as their run-time value might be different from their compile-time values. Statics are just the approximation we use for that so far.

Also refactor the code a bit to make it clearer what is being checked and allowed.

r? @oli-obk
-rw-r--r--src/librustc_mir/const_eval/machine.rs31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 3f9aa9ed02d..a1ab9a1c342 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -353,15 +353,30 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
         static_def_id: Option<DefId>,
         is_write: bool,
     ) -> InterpResult<'tcx> {
-        if is_write && allocation.mutability == Mutability::Not {
-            Err(err_ub!(WriteToReadOnly(alloc_id)).into())
-        } else if is_write {
-            Err(ConstEvalErrKind::ModifiedGlobal.into())
-        } else if memory_extra.can_access_statics || static_def_id.is_none() {
-            // `static_def_id.is_none()` indicates this is not a static, but a const or so.
-            Ok(())
+        if is_write {
+            // Write access. These are never allowed, but we give a targeted error message.
+            if allocation.mutability == Mutability::Not {
+                Err(err_ub!(WriteToReadOnly(alloc_id)).into())
+            } else {
+                Err(ConstEvalErrKind::ModifiedGlobal.into())
+            }
         } else {
-            Err(ConstEvalErrKind::ConstAccessesStatic.into())
+            // Read access. These are usually allowed, with some exceptions.
+            if memory_extra.can_access_statics {
+                // Machine configuration allows us read from anything (e.g., `static` initializer).
+                Ok(())
+            } else if static_def_id.is_some() {
+                // Machine configuration does not allow us to read statics
+                // (e.g., `const` initializer).
+                Err(ConstEvalErrKind::ConstAccessesStatic.into())
+            } else {
+                // Immutable global, this read is fine.
+                // But make sure we never accept a read from something mutable, that would be
+                // unsound. The reason is that as the content of this allocation may be different
+                // now and at run-time, so if we permit reading now we might return the wrong value.
+                assert_eq!(allocation.mutability, Mutability::Not);
+                Ok(())
+            }
         }
     }
 }