-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add a new lint that warns for pointers to stack memory #134218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
rustbot has assigned @compiler-errors. Use |
I am aware that this may warn on existing code. I wonder what is a good strategy here? Should it be an |
Is there a reason why this was implemented as a rust lint rather than a clippy suspicious lint or something? I guess let's find the fallout of this lint @bors try |
Add a new lint that warns for pointers to stack memory This adds a new lint with level `Warn` to check for code like: ```rust fn foo() -> *const i32 { let x = 42; &x } ``` and produce a warning like: ```text error: returning a pointer to stack memory associated with a local variable --> <source>:12:5 | LL| &x | ^^ ``` This fixes rust-lang#134215.
This was completely my judgment, I am happy to change this if requested. My reasoning was that this is a pretty fundamental lint, since the code it lints should probably never exist? And looking at the list of rustc lints I thought it might be a good fit. |
This comment has been minimized.
This comment has been minimized.
40eb5d7
to
e162e89
Compare
Oops - I don't fully understand that error. The failure looks like in the .stderr file, but it still has unexpected errors that it doesn't match on... This even happens when passing |
This comment has been minimized.
This comment has been minimized.
@craterbot check |
🚨 Error: missing start toolchain 🆘 If you have any trouble with Crater please ping |
@craterbot run mode=check-only start=master#8e37e151835d96d6a7415e93e6876561485a3354 end=try#6db1a6a7ebb2ad243051f3ff949f987dd70cde2b |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
bless will generate a .stderr file for you, but it will not update the original .rs file. compiletest is complaining because it expects each warning to be annotated with |
This comment has been minimized.
This comment has been minimized.
3c39f0f
to
f56a313
Compare
The Miri subtree was changed cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
f56a313
to
80a2f21
Compare
This comment has been minimized.
This comment has been minimized.
80a2f21
to
4e7732c
Compare
@craterbot end=try#6db1a6a7ebb2ad243051f3ff949f987dd70cde2b+rustflags=-Dreturn-local-variable-ptr |
📝 Configuration of the ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Friendly ping on this again :) It would be great to get some feedback! |
Friendly ping again! |
☔ The latest upstream changes (presumably #138058) made this pull request unmergeable. Please resolve the merge conflicts. |
Pinging once again, it'd be really great to get some feedback! |
Can this detect the "out-param" case yet? e.g. assigning to |
It should, I can add a test for it. Would be great to get feedback if this is something that is considered for Rust or better lives in Clippy. |
Actually it cannot, but before I invest more work, it would be great to get the fundamental bit of feedback about the lint, before I put it in the wrong place / it is not wanted in general. |
Friendly ping! :) |
@1c3t3a it is not necessary to send weekly reminders for a review. Reviewers are pretty busy and will be back when they have capacity to look at this. Thank you for your patience. |
r? rust-lang/compiler |
r? compiler (busy on compiletest atm) |
@@ -9,6 +9,7 @@ | |||
// Regression test for #114484: This used to ICE during monomorphization, because we treated | |||
// `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion | |||
// limit when finding the struct tail. | |||
#![allow(returning_pointers_to_local_variables)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which part of the test was triggering the lint? All the returned poiunters in this test look legit to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right! The problem was the gen_vtable_ptr
which returns *const ()
, which should be fine. I'll add an exclude for the unit type :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think excluding the unit type is correct: it's not particularly special. Where in that test did your lint think there was a pointer to stack memory? The vtable
in gen_vtable_ptr
was transmuted from pointer metadata which is not pointing to stack memory, and the ptr
in virtualize_my_trait
is obtained by transmuting an existing pointer.
Shouldn't your lint be operating on MIR actually? Because right now operating on HIR you have to think about implicit coercions and reborrows and things.
e38f2c8
to
a599cfa
Compare
```rust fn foo() -> *const i32 { let x = 42; &x } ``` and produce a warning like: ```text error: returning a pointer to stack memory associated with a local variable --> <source>:12:5 | LL| &x | ^^ ``` Disable the lint for another test
a599cfa
to
4d9b3ad
Compare
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, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hum, doesn't this also catch
fn foo() -> *const Something {
let x: *const Something = ...;
...
x
}
?
if matches!(ptr_ty.ty.kind, hir::TyKind::Tup([])) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no good reason to exclude the unit type from this analysis.
I'm overall mixed about this lint: it feels extremely targeted; do we have such targeted lints in rustc usually? I'd also prefer a MIR-based lint honestly, it could then catch the difference between @rustbot author |
Reminder, once the PR becomes ready for a review, use |
Could you explain with what you mean by extremely targeted? This lint generally just catches a pattern of code that is never going to be correct, similar to
That's a very good point. Especially the const promotion was sth I didn't think about. I will try to reimplement the lint on MIR. |
I say targeted because it seems to be exclusively about a syntactic |
Mhm I think with enough control flow that adds indirection this can get complicated enough. This PR was motivated by clang having this warning and two weeks after I opened the PR my team found a piece of code that survived for half a year in our codebase and was the perfect motivation for this lint: // Import actual list from source and use this temporarily for now
const GLOBAL: &[&str] = &[
"abcd",
...
];
#[no_mangle]
pub extern "C" fn foo() -> *mut *const c_char {
let c_strings: Vec<_> = GLOBAL.iter().map(|&val| CString::new(val).unwrap()).collect();
let mut ptrs: Vec<_> = c_strings.iter().map(|cs| cs.as_ptr()).collect();
ptrs.push(std::ptr::null()); // Now safe to push
let boxed_ptrs = ptrs.into_boxed_slice();
let raw_ptr = Box::into_raw(boxed_ptrs);
return raw_ptr as *mut *const c_char;
} I think this is reasonably indirect to not make it entirely clear what is going on. Especially if you are new to Rust or write FFI code that frequently makes use of raw pointers. But maybe the fact that we are discussing this is already a sign that it should be a clippy lint? Idk. |
This adds a new lint with level
Warn
to check for code like:and produce a warning like:
This fixes #134215.