From 352f3841b3376ee43bdcc050e0deb4e9d9f778c0 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Thu, 30 Jan 2025 17:40:13 +0000 Subject: [PATCH] Extend lint to also lint for pointers of pointers --- compiler/rustc_lint/src/builtin.rs | 105 ++++++++---------- ...t-returning-pointers-to-local-variables.rs | 27 +++-- ...turning-pointers-to-local-variables.stderr | 24 ++-- 3 files changed, 76 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index abe6046e3ac68..4257607ad5db0 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3062,68 +3062,59 @@ impl<'tcx> LateLintPass<'tcx> for ReturningPointersToLocalVariables { impl ReturningPointersToLocalVariables { /// Evaluates the return expression of a function and emits a lint if it /// returns a pointer to a local variable. - fn maybe_lint_return_expr<'tcx>(cx: &LateContext<'tcx>, return_expr: &hir::Expr<'tcx>, params: &'tcx [hir::Ty<'tcx>]) { - // dbg!(return_expr); - if let hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. } - | hir::Expr { - kind: - hir::ExprKind::Cast(hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. }, _), - .. - } = return_expr - { - if let hir::ExprKind::Path( - hir::QPath::Resolved(_, hir::Path { res: hir::def::Res::Local(_), .. }), - .., - ) = addr_expr.kind - { - cx.emit_span_lint( - RETURNING_POINTERS_TO_LOCAL_VARIABLES, - return_expr.span, - BuiltinReturningPointersToLocalVariables, - ); - } + fn maybe_lint_return_expr<'tcx>( + cx: &LateContext<'tcx>, + return_expr: &hir::Expr<'tcx>, + params: &'tcx [hir::Ty<'tcx>], + ) { + // Early exit if we see that this is a pointer to an input parameter. + if Self::expr_is_param(cx.typeck_results(), return_expr, params) { + return; } - if let hir::Expr { - kind: - hir::ExprKind::Cast( - hir::Expr { - hir_id, - kind: - hir::ExprKind::Path(hir::QPath::Resolved( - _, - hir::Path { res: hir::def::Res::Local(_), .. }, - )), - .. - }, - _, - ), - .. - } = return_expr - { - - if let hir::Node::Pat(hir::Pat { - hir_id: pat_id, - .. - }) = cx.tcx.hir_node(*hir_id) { - if !params.iter().map(|param| param.hir_id).collect::>().contains(pat_id) { - println!("No param ty"); - cx.emit_span_lint( - RETURNING_POINTERS_TO_LOCAL_VARIABLES, - return_expr.span, - BuiltinReturningPointersToLocalVariables, - ); - } else { - println!("Found param ty"); - } - - } - if let hir::Node::Expr(expr) = cx.tcx.hir_node(*hir_id) { - Self::maybe_lint_return_expr(cx, expr, params); - } + match return_expr { + hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. } => { + Self::maybe_lint_return_expr(cx, addr_expr, params) + } + hir::Expr { + kind: + hir::ExprKind::Cast( + hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. }, + _, + ), + .. + } => Self::maybe_lint_return_expr(cx, addr_expr, params), + hir::Expr { kind: hir::ExprKind::Cast(expr, _), .. } => { + Self::maybe_lint_return_expr(cx, expr, params) + } + hir::Expr { + kind: + hir::ExprKind::Path( + hir::QPath::Resolved(_, hir::Path { res: hir::def::Res::Local(_), .. }), + .., + ), + .. + } => cx.emit_span_lint( + RETURNING_POINTERS_TO_LOCAL_VARIABLES, + return_expr.span, + BuiltinReturningPointersToLocalVariables, + ), + _ => (), } } + fn expr_is_param<'tcx>( + typeck_results: &ty::TypeckResults<'tcx>, + expr: &hir::Expr<'tcx>, + params: &'tcx [hir::Ty<'tcx>], + ) -> bool { + params + .iter() + .map(|param| typeck_results.type_dependent_def_id(param.hir_id)) + .collect::>() + .contains(&typeck_results.type_dependent_def_id(expr.hir_id)) + } + /// Returns the enclosing block for a [hir::HirId], if available. fn get_enclosing_block<'tcx>( cx: &LateContext<'tcx>, diff --git a/tests/ui/lint/lint-returning-pointers-to-local-variables.rs b/tests/ui/lint/lint-returning-pointers-to-local-variables.rs index 19c021876a42d..d9b7a524f865b 100644 --- a/tests/ui/lint/lint-returning-pointers-to-local-variables.rs +++ b/tests/ui/lint/lint-returning-pointers-to-local-variables.rs @@ -26,23 +26,22 @@ fn faa() -> *const u32 { //~^ WARN returning a pointer to stack memory associated with a local variable } -const ALGORITHM_NAMES: &[&str] = &[ - "danish", - "dutch", - "english", -]; - -#[no_mangle] -pub extern "C" fn sb_stemmer_list() -> *mut *const std::ffi::c_char { - let c_strings: Vec<_> = ALGORITHM_NAMES.iter().map(|&alg| std::ffi::CString::new(alg).unwrap()).collect(); +fn pointer_to_pointer() -> *const *mut u32 { + let mut empty = 42u32; + &(&mut empty as *mut u32) as *const _ + //~^ WARN returning a pointer to stack memory associated with a local variable +} - let mut ptrs: Vec<_> = c_strings.iter().map(|cs| cs.as_ptr()).collect(); - ptrs.push(std::ptr::null()); // Now safe to push +fn dont_lint_param(val: u32) -> *const u32 { + &val +} - let boxed_ptrs = ptrs.into_boxed_slice(); - let raw_ptr = Box::into_raw(boxed_ptrs); +struct Foo {} - raw_ptr as *mut *const std::ffi::c_char +impl Foo { + fn dont_lint_self_param(&self) -> *const Foo { + self + } } fn main() {} diff --git a/tests/ui/lint/lint-returning-pointers-to-local-variables.stderr b/tests/ui/lint/lint-returning-pointers-to-local-variables.stderr index 14d65c5018611..3394ae94d8a23 100644 --- a/tests/ui/lint/lint-returning-pointers-to-local-variables.stderr +++ b/tests/ui/lint/lint-returning-pointers-to-local-variables.stderr @@ -1,8 +1,8 @@ warning: returning a pointer to stack memory associated with a local variable - --> $DIR/lint-returning-pointers-to-local-variables.rs:7:12 + --> $DIR/lint-returning-pointers-to-local-variables.rs:7:13 | LL | return &empty as *const _; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^ | note: the lint level is defined here --> $DIR/lint-returning-pointers-to-local-variables.rs:3:9 @@ -11,22 +11,28 @@ LL | #![warn(returning_pointers_to_local_variables)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: returning a pointer to stack memory associated with a local variable - --> $DIR/lint-returning-pointers-to-local-variables.rs:13:5 + --> $DIR/lint-returning-pointers-to-local-variables.rs:13:6 | LL | &empty as *const _ - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^ warning: returning a pointer to stack memory associated with a local variable - --> $DIR/lint-returning-pointers-to-local-variables.rs:19:12 + --> $DIR/lint-returning-pointers-to-local-variables.rs:19:13 | LL | return ∅ - | ^^^^^^ + | ^^^^^ warning: returning a pointer to stack memory associated with a local variable - --> $DIR/lint-returning-pointers-to-local-variables.rs:25:5 + --> $DIR/lint-returning-pointers-to-local-variables.rs:25:6 | LL | &empty - | ^^^^^^ + | ^^^^^ -warning: 4 warnings emitted +warning: returning a pointer to stack memory associated with a local variable + --> $DIR/lint-returning-pointers-to-local-variables.rs:31:12 + | +LL | &(&mut empty as *mut u32) as *const _ + | ^^^^^ + +warning: 5 warnings emitted