about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAria Beingessner <a.beingessner@gmail.com>2022-03-21 19:25:44 -0400
committerniluxv <niluxv.opensource.C-h2ty6xl@yandex.com>2022-04-08 17:40:33 +0200
commit1040cab53b95aa47c2ea8e1a6de73eddadc57aa7 (patch)
treeaecc5ec60b9f6cb10be5e00b100eec7cea3c8158
parente4f5b15b8832334eca2c0bd3929eb3969f1d166d (diff)
downloadrust-1040cab53b95aa47c2ea8e1a6de73eddadc57aa7.tar.gz
rust-1040cab53b95aa47c2ea8e1a6de73eddadc57aa7.zip
WIP PROOF-OF-CONCEPT: Make the compiler complain about all int<->ptr casts.
ALL

OF

THEM
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs36
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs64
2 files changed, 96 insertions, 4 deletions
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 5704c6ed3b2..f9ac0a54a2f 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2649,6 +2649,41 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
+    /// and a pointer.
+    ///
+    /// ### Example
+    ///
+    /// fn main() {
+    ///     let my_ref = &0;
+    ///     let my_addr = my_ref as usize;
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Casting a pointer to an integer or an integer to a pointer is a lossy operation,
+    /// because beyond just an *address* a pointer may be associated with a particular
+    /// *provenance* and *segment*. This information is required by both the compiler
+    /// and the hardware to correctly execute your code. If you need to do this kind
+    /// of operation, use ptr::addr and ptr::with_addr.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a hard error
+    /// in the future. See [issue #9999999] for more details.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    /// [issue #9999999]: https://github.com/rust-lang/rust/issues/9999999
+    pub FUZZY_PROVENANCE_CASTS,
+    Warn,
+    "A lossy pointer-integer integer cast is used",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #9999999 <https://github.com/rust-lang/rust/issues/9999999>",
+    };
+}
+
+declare_lint! {
     /// The `const_evaluatable_unchecked` lint detects a generic constant used
     /// in a type.
     ///
@@ -3101,6 +3136,7 @@ declare_lint_pass! {
         UNSAFE_OP_IN_UNSAFE_FN,
         INCOMPLETE_INCLUDE,
         CENUM_IMPL_DROP_CAST,
+        FUZZY_PROVENANCE_CASTS,
         CONST_EVALUATABLE_UNCHECKED,
         INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
         MUST_NOT_SUSPEND,
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 7ce428ea124..9b67fd54bd6 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -807,11 +807,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
             // ptr -> *
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
-            (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
-            (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
 
-            // * -> ptr
-            (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
+            // ptr-addr-cast
+            (Ptr(m_expr), Int(_)) => {
+                self.fuzzy_provenance_ptr2int_lint(fcx, t_from);
+                self.check_ptr_addr_cast(fcx, m_expr)
+            }
+            (FnPtr, Int(_)) => {
+                self.fuzzy_provenance_ptr2int_lint(fcx, t_from);
+                Ok(CastKind::FnPtrAddrCast)
+            }
+            // addr-ptr-cast
+            (Int(_), Ptr(mt)) => {
+                self.fuzzy_provenance_int2ptr_lint(fcx);
+                self.check_addr_ptr_cast(fcx, mt)
+            }
+            // fn-ptr-cast
             (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
 
             // prim -> prim
@@ -934,6 +945,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         fcx: &FnCtxt<'a, 'tcx>,
         m_cast: TypeAndMut<'tcx>,
     ) -> Result<CastKind, CastError> {
+        self.fuzzy_provenance_int2ptr_lint(fcx);
         // ptr-addr cast. pointer must be thin.
         match fcx.pointer_kind(m_cast.ty, self.span)? {
             None => Err(CastError::UnknownCastPtrKind),
@@ -973,6 +985,50 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             }
         }
     }
+
+    fn fuzzy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_from: CastTy<'tcx>) {
+        fcx.tcx.struct_span_lint_hir(
+            lint::builtin::FUZZY_PROVENANCE_CASTS,
+            self.expr.hir_id,
+            self.span,
+            |err| {
+                let mut err = err.build(&format!(
+                    "strict provenance disallows casting pointer `{}` to integer `{}`",
+                    self.expr_ty, self.cast_ty
+                ));
+
+                if let CastTy::FnPtr = t_from {
+                    err.help(
+                        "use `(... as *const u8).addr()` to obtain \
+                         the address of a function pointer",
+                    );
+                } else {
+                    err.help("use `.addr()` to obtain the address of a pointer");
+                }
+
+                err.emit();
+            },
+        );
+    }
+
+    fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
+        fcx.tcx.struct_span_lint_hir(
+            lint::builtin::FUZZY_PROVENANCE_CASTS,
+            self.expr.hir_id,
+            self.span,
+            |err| {
+                err.build(&format!(
+                    "strict provenance disallows casting integer `{}` to pointer `{}`",
+                    self.expr_ty, self.cast_ty
+                ))
+                .help(
+                    "use `.with_addr(...)` to adjust a valid pointer \
+                     in the same allocation, to this address",
+                )
+                .emit();
+            },
+        );
+    }
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {