From aced30064a00916064387fc63d046dcff8031521 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 25 Oct 2025 21:30:46 -0400 Subject: [PATCH 1/3] Make deref_nullptr deny by default instead of warn --- compiler/rustc_lint/src/builtin.rs | 2 +- tests/ui/lint/lint-forbid-internal-unsafe.rs | 2 +- tests/ui/lint/lint-forbid-internal-unsafe.stderr | 6 +++--- tests/ui/unreachable-code/unreachable-bool-read-7246.rs | 2 +- tests/ui/unreachable-code/unreachable-bool-read-7246.stderr | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d3468499b4b3a..045155569bf94 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2716,7 +2716,7 @@ declare_lint! { /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html pub DEREF_NULLPTR, - Warn, + Deny, "detects when an null pointer is dereferenced" } diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.rs b/tests/ui/lint/lint-forbid-internal-unsafe.rs index 3ee55ba96b137..ab3769b06cbe3 100644 --- a/tests/ui/lint/lint-forbid-internal-unsafe.rs +++ b/tests/ui/lint/lint-forbid-internal-unsafe.rs @@ -13,5 +13,5 @@ macro_rules! evil { fn main() { println!("{}", evil!(*(0 as *const u8))); - //~^ WARNING dereferencing a null pointer + //~^ ERROR dereferencing a null pointer } diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.stderr b/tests/ui/lint/lint-forbid-internal-unsafe.stderr index 52d9c8471e56e..a58bd467f6757 100644 --- a/tests/ui/lint/lint-forbid-internal-unsafe.stderr +++ b/tests/ui/lint/lint-forbid-internal-unsafe.stderr @@ -10,13 +10,13 @@ note: the lint level is defined here LL | #![forbid(unsafe_code)] | ^^^^^^^^^^^ -warning: dereferencing a null pointer +error: dereferencing a null pointer --> $DIR/lint-forbid-internal-unsafe.rs:15:26 | LL | println!("{}", evil!(*(0 as *const u8))); | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | - = note: `#[warn(deref_nullptr)]` on by default + = note: `#[deny(deref_nullptr)]` on by default -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/unreachable-code/unreachable-bool-read-7246.rs b/tests/ui/unreachable-code/unreachable-bool-read-7246.rs index 8bbaa1025493f..212828679800b 100644 --- a/tests/ui/unreachable-code/unreachable-bool-read-7246.rs +++ b/tests/ui/unreachable-code/unreachable-bool-read-7246.rs @@ -5,7 +5,7 @@ use std::ptr; pub unsafe fn g() { return; if *ptr::null() {}; //~ ERROR unreachable - //~| WARNING dereferencing a null pointer + //~| ERROR dereferencing a null pointer } pub fn main() {} diff --git a/tests/ui/unreachable-code/unreachable-bool-read-7246.stderr b/tests/ui/unreachable-code/unreachable-bool-read-7246.stderr index 6072160cb5f13..6e4123760a791 100644 --- a/tests/ui/unreachable-code/unreachable-bool-read-7246.stderr +++ b/tests/ui/unreachable-code/unreachable-bool-read-7246.stderr @@ -12,13 +12,13 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -warning: dereferencing a null pointer +error: dereferencing a null pointer --> $DIR/unreachable-bool-read-7246.rs:7:8 | LL | if *ptr::null() {}; | ^^^^^^^^^^^^ this code causes undefined behavior when executed | - = note: `#[warn(deref_nullptr)]` on by default + = note: `#[deny(deref_nullptr)]` on by default -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors From 3b9de6f7c990cc29304911b5453a584ae7662398 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 26 Oct 2025 13:37:48 -0400 Subject: [PATCH 2/3] Expect compilation failure --- compiler/rustc_lint/src/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 045155569bf94..9631530a48869 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2697,7 +2697,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,no_run + /// ```rust,compile_fail /// # #![allow(unused)] /// use std::ptr; /// unsafe { From ab634f5c9a3c54f3ee97b7b10ef818e8610f3b9f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 6 Nov 2025 18:50:04 -0500 Subject: [PATCH 3/3] Don't lint on derefs of null pointers to ZSTs --- compiler/rustc_lint/src/builtin.rs | 10 ++++++++++ tests/ui/lint/lint-deref-nullptr.rs | 10 ++++++++-- tests/ui/lint/lint-deref-nullptr.stderr | 22 +++++++++------------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9631530a48869..47283a1738585 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2726,6 +2726,16 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { /// test if expression is a null ptr fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let pointer_ty = cx.typeck_results().expr_ty(expr); + let ty::RawPtr(pointee, _) = pointer_ty.kind() else { + return false; + }; + if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*pointee)) { + if layout.layout.size() == rustc_abi::Size::ZERO { + return false; + } + } + match &expr.kind { hir::ExprKind::Cast(expr, ty) => { if let hir::TyKind::Ptr(_) = ty.kind { diff --git a/tests/ui/lint/lint-deref-nullptr.rs b/tests/ui/lint/lint-deref-nullptr.rs index f83d88309b9a7..ed0cc7fa3ee95 100644 --- a/tests/ui/lint/lint-deref-nullptr.rs +++ b/tests/ui/lint/lint-deref-nullptr.rs @@ -1,13 +1,14 @@ // test the deref_nullptr lint -#![deny(deref_nullptr)] - use std::ptr; struct Struct { field: u8, } +#[derive(Clone, Copy)] +struct Zst; + fn f() { unsafe { let a = 1; @@ -32,6 +33,11 @@ fn f() { // ^^ OKAY let offset = ptr::addr_of!((*ptr::null::()).field); //~^ ERROR dereferencing a null pointer + + // Make sure the lint permits derefs of null pointers to ZSTs + let ok: Zst = *ptr::null(); + let ok: Zst = *ptr::null_mut(); + let ok: Zst = *(0 as *const Zst); } } diff --git a/tests/ui/lint/lint-deref-nullptr.stderr b/tests/ui/lint/lint-deref-nullptr.stderr index 175431b2994bd..1216e455485a0 100644 --- a/tests/ui/lint/lint-deref-nullptr.stderr +++ b/tests/ui/lint/lint-deref-nullptr.stderr @@ -1,53 +1,49 @@ error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:15:18 + --> $DIR/lint-deref-nullptr.rs:16:18 | LL | let ub = *(0 as *const i32); | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | -note: the lint level is defined here - --> $DIR/lint-deref-nullptr.rs:3:9 - | -LL | #![deny(deref_nullptr)] - | ^^^^^^^^^^^^^ + = note: `#[deny(deref_nullptr)]` on by default error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:17:18 + --> $DIR/lint-deref-nullptr.rs:18:18 | LL | let ub = *ptr::null::(); | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:19:18 + --> $DIR/lint-deref-nullptr.rs:20:18 | LL | let ub = *ptr::null_mut::(); | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:21:18 + --> $DIR/lint-deref-nullptr.rs:22:18 | LL | let ub = *(ptr::null::() as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:23:18 + --> $DIR/lint-deref-nullptr.rs:24:18 | LL | let ub = *(ptr::null::() as *mut i32 as *mut usize as *const u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:25:19 + --> $DIR/lint-deref-nullptr.rs:26:19 | LL | let ub = &*ptr::null::(); | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:27:19 + --> $DIR/lint-deref-nullptr.rs:28:19 | LL | let ub = &*ptr::null_mut::(); | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:33:36 + --> $DIR/lint-deref-nullptr.rs:34:36 | LL | let offset = ptr::addr_of!((*ptr::null::()).field); | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed