Skip to content

Commit

Permalink
new lint ptr_to_temporary
Browse files Browse the repository at this point in the history
Update mod.rs

Update mod.rs
  • Loading branch information
Centri3 committed Jun 15, 2023
1 parent cda13a8 commit 0c88f66
Show file tree
Hide file tree
Showing 16 changed files with 155 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5088,6 +5088,7 @@ Released 2018-09-13
[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness
[`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
[`ptr_to_temporary`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_to_temporary
[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
[`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
Expand Down
28 changes: 28 additions & 0 deletions clippy_lints/src/casts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod fn_to_numeric_cast_any;
mod fn_to_numeric_cast_with_truncation;
mod ptr_as_ptr;
mod ptr_cast_constness;
mod ptr_to_temporary;
mod unnecessary_cast;
mod utils;

Expand Down Expand Up @@ -657,6 +658,31 @@ declare_clippy_lint! {
"casting a known floating-point NaN into an integer"
}

declare_clippy_lint! {
/// ### What it does
/// Checks for raw pointers that point to temporary values.
///
/// ### Why is this bad?
/// It will result in Undefined Behavior, as the pointer will stop pointing to valid stack
/// memory once the temporary is dropped.
///
/// ### Example
/// ```rust,ignore
/// let p = &0u32 as *const u32;
/// unsafe { p.read() }; // ⚠️
/// ```
/// Use instead:
/// ```rust,ignore
/// let x = 0u32;
/// let px = &x as *const u32;
/// unsafe { px.read() };
/// ```
#[clippy::version = "1.72.0"]
pub PTR_TO_TEMPORARY,
correctness,
"disallows obtaining a raw pointer to a temporary value"
}

pub struct Casts {
msrv: Msrv,
}
Expand Down Expand Up @@ -691,6 +717,7 @@ impl_lint_pass!(Casts => [
CAST_SLICE_FROM_RAW_PARTS,
AS_PTR_CAST_MUT,
CAST_NAN_TO_INT,
PTR_TO_TEMPORARY,
]);

impl<'tcx> LateLintPass<'tcx> for Casts {
Expand Down Expand Up @@ -736,6 +763,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
}

as_underscore::check(cx, expr, cast_to_hir);
ptr_to_temporary::check(cx, expr, cast_expr, cast_to_hir);

if self.msrv.meets(msrvs::BORROW_AS_PTR) {
borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
Expand Down
34 changes: 34 additions & 0 deletions clippy_lints/src/casts/ptr_to_temporary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::{BorrowKind, Expr, ExprKind, Ty, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;

use super::PTR_TO_TEMPORARY;

pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
cast_expr: &'tcx Expr<'_>,
cast_to: &'tcx Ty<'_>,
) {
if matches!(cast_to.kind, TyKind::Ptr(_))
&& let ExprKind::AddrOf(BorrowKind::Ref, _, e) = cast_expr.kind
{
// rustc's criteria of a "temporary value", so this should be 100% accurate
if !e.is_place_expr(|base| {
cx.typeck_results()
.adjustments()
.get(base.hir_id)
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
}) {
span_lint_and_help(
cx,
PTR_TO_TEMPORARY,
expr.span,
"raw pointer to a temporary value",
None,
"this causes Undefined Behavior; create a local binding to make it longer lived",
);
}
}
}
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
crate::casts::PTR_AS_PTR_INFO,
crate::casts::PTR_CAST_CONSTNESS_INFO,
crate::casts::PTR_TO_TEMPORARY_INFO,
crate::casts::UNNECESSARY_CAST_INFO,
crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/borrow_deref_ref.fixed
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@run-rustfix
//@aux-build: proc_macros.rs

#![allow(dead_code, unused_variables)]
#![allow(clippy::ptr_to_temporary, dead_code, unused_variables)]

extern crate proc_macros;
use proc_macros::with_span;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/borrow_deref_ref.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@run-rustfix
//@aux-build: proc_macros.rs

#![allow(dead_code, unused_variables)]
#![allow(clippy::ptr_to_temporary, dead_code, unused_variables)]

extern crate proc_macros;
use proc_macros::with_span;
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/cast_alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ extern crate libc;
clippy::no_effect,
clippy::unnecessary_operation,
clippy::cast_lossless,
clippy::borrow_as_ptr
clippy::borrow_as_ptr,
clippy::ptr_to_temporary
)]

fn main() {
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/cast_alignment.stderr
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:19:5
--> $DIR/cast_alignment.rs:20:5
|
LL | (&1u8 as *const u8) as *const u16;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::cast-ptr-alignment` implied by `-D warnings`

error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:20:5
--> $DIR/cast_alignment.rs:21:5
|
LL | (&mut 1u8 as *mut u8) as *mut u16;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:23:5
--> $DIR/cast_alignment.rs:24:5
|
LL | (&1u8 as *const u8).cast::<u16>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:24:5
--> $DIR/cast_alignment.rs:25:5
|
LL | (&mut 1u8 as *mut u8).cast::<u16>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/ptr_to_temporary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#![allow(clippy::explicit_auto_deref, clippy::unnecessary_cast, clippy::useless_vec)]

use std::ptr::addr_of;

fn a() -> i32 {
0
}

struct Vec3 {
x: f32,
y: f32,
z: f32,
}

fn main() {
let _p = &0 as *const i32;
let _p = &a() as *const i32;
let vec = vec![1];
let _p = &vec.len() as *const usize;
let x = &(1 + 2) as *const i32;
let x = &(x as *const i32) as *const *const i32;

// Do not lint...
let ptr = &Vec3 { x: 1.0, y: 2.0, z: 3.0 };
let some_variable = 1i32;
let x = &(*ptr).x as *const f32;
let x = &(some_variable) as *const i32;

// ...As `addr_of!` does not report anything out of the ordinary
let ptr = &Vec3 { x: 1.0, y: 2.0, z: 3.0 };
let some_variable = 1i32;
let x = addr_of!((*ptr).x) as *const f32;
let x = addr_of!(some_variable);
}
43 changes: 43 additions & 0 deletions tests/ui/ptr_to_temporary.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
error: raw pointer to a temporary value
--> $DIR/ptr_to_temporary.rs:16:14
|
LL | let _p = &0 as *const i32;
| ^^^^^^^^^^^^^^^^
|
= help: this causes Undefined Behavior; create a local binding to make it longer lived
= note: `#[deny(clippy::ptr_to_temporary)]` on by default

error: raw pointer to a temporary value
--> $DIR/ptr_to_temporary.rs:17:14
|
LL | let _p = &a() as *const i32;
| ^^^^^^^^^^^^^^^^^^
|
= help: this causes Undefined Behavior; create a local binding to make it longer lived

error: raw pointer to a temporary value
--> $DIR/ptr_to_temporary.rs:19:14
|
LL | let _p = &vec.len() as *const usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: this causes Undefined Behavior; create a local binding to make it longer lived

error: raw pointer to a temporary value
--> $DIR/ptr_to_temporary.rs:20:13
|
LL | let x = &(1 + 2) as *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: this causes Undefined Behavior; create a local binding to make it longer lived

error: raw pointer to a temporary value
--> $DIR/ptr_to_temporary.rs:21:13
|
LL | let x = &(x as *const i32) as *const *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: this causes Undefined Behavior; create a local binding to make it longer lived

error: aborting due to 5 previous errors

2 changes: 1 addition & 1 deletion tests/ui/transmute_ptr_to_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::borrow_as_ptr)]
#![allow(clippy::borrow_as_ptr, clippy::ptr_to_temporary)]

// Make sure we can modify lifetimes, which is one of the recommended uses
// of transmute
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/transmutes_expressible_as_ptr_casts.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// would otherwise be responsible for
#![warn(clippy::useless_transmute)]
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(unused, clippy::borrow_as_ptr)]
#![allow(unused, clippy::borrow_as_ptr, clippy::ptr_to_temporary)]

use std::mem::{size_of, transmute};

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/transmutes_expressible_as_ptr_casts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// would otherwise be responsible for
#![warn(clippy::useless_transmute)]
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(unused, clippy::borrow_as_ptr)]
#![allow(unused, clippy::borrow_as_ptr, clippy::ptr_to_temporary)]

use std::mem::{size_of, transmute};

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/unnecessary_struct_initialization.fixed
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@run-rustfix

#![allow(unused)]
#![allow(clippy::ptr_to_temporary, unused)]
#![warn(clippy::unnecessary_struct_initialization)]

struct S {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/unnecessary_struct_initialization.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@run-rustfix

#![allow(unused)]
#![allow(clippy::ptr_to_temporary, unused)]
#![warn(clippy::unnecessary_struct_initialization)]

struct S {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/zero_offset.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[allow(clippy::borrow_as_ptr)]
#[allow(clippy::borrow_as_ptr, clippy::ptr_to_temporary)]
fn main() {
unsafe {
let m = &mut () as *mut ();
Expand Down

0 comments on commit 0c88f66

Please sign in to comment.