Skip to content

Commit

Permalink
Extend lint to also lint for pointers of pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
1c3t3a committed Jan 30, 2025
1 parent 6ddbf7c commit 352f384
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 80 deletions.
105 changes: 48 additions & 57 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>().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::<Vec<_>>()
.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>,
Expand Down
27 changes: 13 additions & 14 deletions tests/ui/lint/lint-returning-pointers-to-local-variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
24 changes: 15 additions & 9 deletions tests/ui/lint/lint-returning-pointers-to-local-variables.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 &empty;
| ^^^^^^
| ^^^^^

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

0 comments on commit 352f384

Please sign in to comment.