about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJ-ZhengLi <lizheng135@huawei.com>2023-09-15 12:24:45 +0800
committerJ-ZhengLi <lizheng135@huawei.com>2023-09-15 12:24:45 +0800
commit1d76eede99126dc6534a0d89dbf04121cd990042 (patch)
treeb0dbb2ae47a663d8e4366945c0f721c4fa8e0d3e
parent6734e96ba4f0872e1245665d8c7c85e56c61fd1f (diff)
downloadrust-1d76eede99126dc6534a0d89dbf04121cd990042.tar.gz
rust-1d76eede99126dc6534a0d89dbf04121cd990042.zip
trigger [`transmute_null_to_fn`] on chain of casts
-rw-r--r--clippy_lints/src/transmute/transmute_null_to_fn.rs30
-rw-r--r--tests/ui/transmute_null_to_fn.rs11
-rw-r--r--tests/ui/transmute_null_to_fn.stderr26
3 files changed, 55 insertions, 12 deletions
diff --git a/clippy_lints/src/transmute/transmute_null_to_fn.rs b/clippy_lints/src/transmute/transmute_null_to_fn.rs
index 4944381da24..b26365e34ab 100644
--- a/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -28,35 +28,43 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
         return false;
     }
 
-    match arg.kind {
+    let casts_peeled = peel_casts(arg);
+    match casts_peeled.kind {
         // Catching:
         // transmute over constants that resolve to `null`.
-        ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => {
+        ExprKind::Path(ref _qpath)
+            if matches!(
+                constant(cx, cx.typeck_results(), casts_peeled),
+                Some(Constant::RawPtr(0))
+            ) =>
+        {
             lint_expr(cx, expr);
             true
         },
-
-        // Catching:
-        // `std::mem::transmute(0 as *const i32)`
-        ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => {
-            lint_expr(cx, expr);
-            true
-        },
-
         // Catching:
         // `std::mem::transmute(std::ptr::null::<i32>())`
         ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => {
             lint_expr(cx, expr);
             true
         },
-
         _ => {
             // FIXME:
             // Also catch transmutations of variables which are known nulls.
             // To do this, MIR const propagation seems to be the better tool.
             // Whenever MIR const prop routines are more developed, this will
             // become available. As of this writing (25/03/19) it is not yet.
+            if is_integer_literal(casts_peeled, 0) {
+                lint_expr(cx, expr);
+                return true;
+            }
             false
         },
     }
 }
+
+fn peel_casts<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
+    match &expr.kind {
+        ExprKind::Cast(inner_expr, _) => peel_casts(inner_expr),
+        _ => expr,
+    }
+}
diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs
index 7d780c803ff..b07851e864f 100644
--- a/tests/ui/transmute_null_to_fn.rs
+++ b/tests/ui/transmute_null_to_fn.rs
@@ -25,6 +25,17 @@ fn transmute_const() {
     }
 }
 
+fn issue_11485() {
+    unsafe {
+        let _: fn() = std::mem::transmute(0 as *const u8 as *const ());
+        //~^ ERROR: transmuting a known null pointer into a function pointer
+        let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8);
+        //~^ ERROR: transmuting a known null pointer into a function pointer
+        let _: fn() = std::mem::transmute(ZPTR as *const u8);
+        //~^ ERROR: transmuting a known null pointer into a function pointer
+    }
+}
+
 fn main() {
     one_liners();
     transmute_const();
diff --git a/tests/ui/transmute_null_to_fn.stderr b/tests/ui/transmute_null_to_fn.stderr
index ab0ac0dd480..9073080cbf3 100644
--- a/tests/ui/transmute_null_to_fn.stderr
+++ b/tests/ui/transmute_null_to_fn.stderr
@@ -24,5 +24,29 @@ LL |         let _: fn() = std::mem::transmute(ZPTR);
    |
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
 
-error: aborting due to 3 previous errors
+error: transmuting a known null pointer into a function pointer
+  --> $DIR/transmute_null_to_fn.rs:30:23
+   |
+LL |         let _: fn() = std::mem::transmute(0 as *const u8 as *const ());
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+   |
+   = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+
+error: transmuting a known null pointer into a function pointer
+  --> $DIR/transmute_null_to_fn.rs:32:23
+   |
+LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+   |
+   = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+
+error: transmuting a known null pointer into a function pointer
+  --> $DIR/transmute_null_to_fn.rs:34:23
+   |
+LL |         let _: fn() = std::mem::transmute(ZPTR as *const u8);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+   |
+   = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+
+error: aborting due to 6 previous errors