Skip to content

Commit 352f384

Browse files
committed
Extend lint to also lint for pointers of pointers
1 parent 6ddbf7c commit 352f384

File tree

3 files changed

+76
-80
lines changed

3 files changed

+76
-80
lines changed

compiler/rustc_lint/src/builtin.rs

+48-57
Original file line numberDiff line numberDiff line change
@@ -3062,68 +3062,59 @@ impl<'tcx> LateLintPass<'tcx> for ReturningPointersToLocalVariables {
30623062
impl ReturningPointersToLocalVariables {
30633063
/// Evaluates the return expression of a function and emits a lint if it
30643064
/// returns a pointer to a local variable.
3065-
fn maybe_lint_return_expr<'tcx>(cx: &LateContext<'tcx>, return_expr: &hir::Expr<'tcx>, params: &'tcx [hir::Ty<'tcx>]) {
3066-
// dbg!(return_expr);
3067-
if let hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. }
3068-
| hir::Expr {
3069-
kind:
3070-
hir::ExprKind::Cast(hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. }, _),
3071-
..
3072-
} = return_expr
3073-
{
3074-
if let hir::ExprKind::Path(
3075-
hir::QPath::Resolved(_, hir::Path { res: hir::def::Res::Local(_), .. }),
3076-
..,
3077-
) = addr_expr.kind
3078-
{
3079-
cx.emit_span_lint(
3080-
RETURNING_POINTERS_TO_LOCAL_VARIABLES,
3081-
return_expr.span,
3082-
BuiltinReturningPointersToLocalVariables,
3083-
);
3084-
}
3065+
fn maybe_lint_return_expr<'tcx>(
3066+
cx: &LateContext<'tcx>,
3067+
return_expr: &hir::Expr<'tcx>,
3068+
params: &'tcx [hir::Ty<'tcx>],
3069+
) {
3070+
// Early exit if we see that this is a pointer to an input parameter.
3071+
if Self::expr_is_param(cx.typeck_results(), return_expr, params) {
3072+
return;
30853073
}
3086-
if let hir::Expr {
3087-
kind:
3088-
hir::ExprKind::Cast(
3089-
hir::Expr {
3090-
hir_id,
3091-
kind:
3092-
hir::ExprKind::Path(hir::QPath::Resolved(
3093-
_,
3094-
hir::Path { res: hir::def::Res::Local(_), .. },
3095-
)),
3096-
..
3097-
},
3098-
_,
3099-
),
3100-
..
3101-
} = return_expr
3102-
{
3103-
3104-
if let hir::Node::Pat(hir::Pat {
3105-
hir_id: pat_id,
3106-
..
3107-
}) = cx.tcx.hir_node(*hir_id) {
3108-
if !params.iter().map(|param| param.hir_id).collect::<Vec<_>>().contains(pat_id) {
3109-
println!("No param ty");
3110-
cx.emit_span_lint(
3111-
RETURNING_POINTERS_TO_LOCAL_VARIABLES,
3112-
return_expr.span,
3113-
BuiltinReturningPointersToLocalVariables,
3114-
);
3115-
} else {
3116-
println!("Found param ty");
3117-
}
3118-
3119-
}
31203074

3121-
if let hir::Node::Expr(expr) = cx.tcx.hir_node(*hir_id) {
3122-
Self::maybe_lint_return_expr(cx, expr, params);
3123-
}
3075+
match return_expr {
3076+
hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. } => {
3077+
Self::maybe_lint_return_expr(cx, addr_expr, params)
3078+
}
3079+
hir::Expr {
3080+
kind:
3081+
hir::ExprKind::Cast(
3082+
hir::Expr { kind: hir::ExprKind::AddrOf(_, _, addr_expr), .. },
3083+
_,
3084+
),
3085+
..
3086+
} => Self::maybe_lint_return_expr(cx, addr_expr, params),
3087+
hir::Expr { kind: hir::ExprKind::Cast(expr, _), .. } => {
3088+
Self::maybe_lint_return_expr(cx, expr, params)
3089+
}
3090+
hir::Expr {
3091+
kind:
3092+
hir::ExprKind::Path(
3093+
hir::QPath::Resolved(_, hir::Path { res: hir::def::Res::Local(_), .. }),
3094+
..,
3095+
),
3096+
..
3097+
} => cx.emit_span_lint(
3098+
RETURNING_POINTERS_TO_LOCAL_VARIABLES,
3099+
return_expr.span,
3100+
BuiltinReturningPointersToLocalVariables,
3101+
),
3102+
_ => (),
31243103
}
31253104
}
31263105

3106+
fn expr_is_param<'tcx>(
3107+
typeck_results: &ty::TypeckResults<'tcx>,
3108+
expr: &hir::Expr<'tcx>,
3109+
params: &'tcx [hir::Ty<'tcx>],
3110+
) -> bool {
3111+
params
3112+
.iter()
3113+
.map(|param| typeck_results.type_dependent_def_id(param.hir_id))
3114+
.collect::<Vec<_>>()
3115+
.contains(&typeck_results.type_dependent_def_id(expr.hir_id))
3116+
}
3117+
31273118
/// Returns the enclosing block for a [hir::HirId], if available.
31283119
fn get_enclosing_block<'tcx>(
31293120
cx: &LateContext<'tcx>,

tests/ui/lint/lint-returning-pointers-to-local-variables.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,22 @@ fn faa() -> *const u32 {
2626
//~^ WARN returning a pointer to stack memory associated with a local variable
2727
}
2828

29-
const ALGORITHM_NAMES: &[&str] = &[
30-
"danish",
31-
"dutch",
32-
"english",
33-
];
34-
35-
#[no_mangle]
36-
pub extern "C" fn sb_stemmer_list() -> *mut *const std::ffi::c_char {
37-
let c_strings: Vec<_> = ALGORITHM_NAMES.iter().map(|&alg| std::ffi::CString::new(alg).unwrap()).collect();
29+
fn pointer_to_pointer() -> *const *mut u32 {
30+
let mut empty = 42u32;
31+
&(&mut empty as *mut u32) as *const _
32+
//~^ WARN returning a pointer to stack memory associated with a local variable
33+
}
3834

39-
let mut ptrs: Vec<_> = c_strings.iter().map(|cs| cs.as_ptr()).collect();
40-
ptrs.push(std::ptr::null()); // Now safe to push
35+
fn dont_lint_param(val: u32) -> *const u32 {
36+
&val
37+
}
4138

42-
let boxed_ptrs = ptrs.into_boxed_slice();
43-
let raw_ptr = Box::into_raw(boxed_ptrs);
39+
struct Foo {}
4440

45-
raw_ptr as *mut *const std::ffi::c_char
41+
impl Foo {
42+
fn dont_lint_self_param(&self) -> *const Foo {
43+
self
44+
}
4645
}
4746

4847
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
warning: returning a pointer to stack memory associated with a local variable
2-
--> $DIR/lint-returning-pointers-to-local-variables.rs:7:12
2+
--> $DIR/lint-returning-pointers-to-local-variables.rs:7:13
33
|
44
LL | return &empty as *const _;
5-
| ^^^^^^^^^^^^^^^^^^
5+
| ^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/lint-returning-pointers-to-local-variables.rs:3:9
@@ -11,22 +11,28 @@ LL | #![warn(returning_pointers_to_local_variables)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
warning: returning a pointer to stack memory associated with a local variable
14-
--> $DIR/lint-returning-pointers-to-local-variables.rs:13:5
14+
--> $DIR/lint-returning-pointers-to-local-variables.rs:13:6
1515
|
1616
LL | &empty as *const _
17-
| ^^^^^^^^^^^^^^^^^^
17+
| ^^^^^
1818

1919
warning: returning a pointer to stack memory associated with a local variable
20-
--> $DIR/lint-returning-pointers-to-local-variables.rs:19:12
20+
--> $DIR/lint-returning-pointers-to-local-variables.rs:19:13
2121
|
2222
LL | return &empty;
23-
| ^^^^^^
23+
| ^^^^^
2424

2525
warning: returning a pointer to stack memory associated with a local variable
26-
--> $DIR/lint-returning-pointers-to-local-variables.rs:25:5
26+
--> $DIR/lint-returning-pointers-to-local-variables.rs:25:6
2727
|
2828
LL | &empty
29-
| ^^^^^^
29+
| ^^^^^
3030

31-
warning: 4 warnings emitted
31+
warning: returning a pointer to stack memory associated with a local variable
32+
--> $DIR/lint-returning-pointers-to-local-variables.rs:31:12
33+
|
34+
LL | &(&mut empty as *mut u32) as *const _
35+
| ^^^^^
36+
37+
warning: 5 warnings emitted
3238

0 commit comments

Comments
 (0)