Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2697,7 +2697,7 @@ declare_lint! {
///
/// ### Example
///
/// ```rust,no_run
/// ```rust,compile_fail
/// # #![allow(unused)]
/// use std::ptr;
/// unsafe {
Expand All @@ -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"
}

Expand All @@ -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 {
Expand Down
10 changes: 8 additions & 2 deletions tests/ui/lint/lint-deref-nullptr.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -32,6 +33,11 @@ fn f() {
// ^^ OKAY
let offset = ptr::addr_of!((*ptr::null::<Struct>()).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);
}
}

Expand Down
22 changes: 9 additions & 13 deletions tests/ui/lint/lint-deref-nullptr.stderr
Original file line number Diff line number Diff line change
@@ -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::<i32>();
| ^^^^^^^^^^^^^^^^^^^ 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::<i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^ 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::<i16>() 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::<i16>() 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::<i32>();
| ^^^^^^^^^^^^^^^^^^^ 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::<i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^ 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::<Struct>()).field);
| ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lint/lint-forbid-internal-unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
6 changes: 3 additions & 3 deletions tests/ui/lint/lint-forbid-internal-unsafe.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

2 changes: 1 addition & 1 deletion tests/ui/unreachable-code/unreachable-bool-read-7246.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/unreachable-code/unreachable-bool-read-7246.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Loading