-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
not_unsafe_ptr_arg_deref false positives #3045
Comments
Hit the same just passing-through a pointer to an FFI extern function: use std::os::raw::{c_int, c_void};
extern "C" {
pub fn libfoo_set_item(h: c_int, t: c_int, item: *const c_void) -> c_int;
}
pub fn set_item(_h: (), _t: (), item: *const c_void) {
unsafe { libfoo_set_item(0, 0, item) };
}
fn main() {} |
I don't get this lint. As I understand it, you mark a function as |
Bear in mind that safe code can synthesize raw pointers at will. A function accepting a raw pointer that it uses can almost never be safe. How do you check pointer validity? It could be a pointer to anything. It's not just null checks you have to do. You're right that it is the responsibility of safe functions to check invariants -- but that's basically almost impossible to do in this case. There is one exception: if you actually maintain a list of valid pointers and validate against that. I've only seen this pattern used once, it's not common enough to attempt to catch. Not using the pointer is definitely a false positive (albeit a bit weird) The FFI example is not a false positive. This is a pretty important lint -- this kind of mistake (misjudging boundaries) is not uncommon in unsafe code |
In the FFI example, the Rust code as well does not dereference the pointer in Which is why, unless I badly misunderstood something, I think I'm hitting a variation of this false positive. |
The only thing that the FFI function can do is :
With (a) ... why do you need the argument? (b) is rare, and (c) should have a usize API. You're right that C is outside the scope of Rust, but this is Clippy, not rustc, and Clippy knows that it is almost impossible for this to be safe and is in its rights to complain. It is definitely actionable in the lint -- make the function unsafe, or make it accept a pointer abstraction that is unsafe to synthesize. |
Neither While I can hide pointers in some newtype or mark all the Rust functions unsafe, we still didn't move from the initial fact that the snippet above does not do any pointer dereference in the Rust code (and the native code function doing that is already extern/unsafe). |
In that case it is definitely wrong to have a safe API that takes a raw pointer and blindly hand it over to C code. My API design argument was not my main argument here, you're missing the point. If a C API is accepting a pointer it is very likely that it intends to eventually dereference it, at most with a null check. There isn't more checking it can do. You cannot give safe rust code the ability to pass down arbitrary pointer values to it. This is enough to justify the lint. The API design point was dealing with the edge cases -- when the C API accepts a pointer without intent to dereference it. These are reasonably rare, I just gave a counterargument for completeness' sake. The fact that the rust code is not doing the pointer dereference isn't relevant, it's very likely that someone is, and it's still the Rust code's responsibility to maintain the safety invariants, but we know can't. This is a very fundamental thing about writing unsafe code, you have to make sure you take responsibility for the invariants when you mark an unsafety-containung function as safe. Simply put, in safe code, I can call, |
@Manishearth thanks for the followup. I definitely see your point (and in the previous comment too, I was trying to bring this down to a concrete real-word scenario). |
If this is the expected behaviour, I think the message should be changed. Maybe something like "this public function might dereference a raw pointer but is not marked `unsafe`"? The current message is confusing and not always correct. |
Sure, I'd accept that change |
Improve message for `not_unsafe_ptr_arg_deref` lint changelog: Improved message for the ['not_unsafe_ptr_arg_deref'] lint Doesn't close any issue, but implements a suggestion from #3045 (comment).
Hey, I just wanted to add another example of a false positive that I just ran into that does not involve FFI. I was in the process of fixing some old Rust code which looked something like this when I encountered #[repr(transparent)]
pub struct Foo(usize);
impl Foo {
pub fn from_ptr<T>(ptr: *const T) -> Self {
unsafe { mem::transmute(ptr) }
}
} Now there are a lot of things wrong with this code (Personally I don't think
My initial reaction upon seeing this error was that Clippy was broken since there is no way That being said, it seems likely that |
I'm providing another false positive, in #![feature(const_ptr_is_null)]
#[repr(transparent)]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
impl<T: ?Sized> NonNull<T> {
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
// SAFETY: the caller must guarantee that `ptr` is non-null.
unsafe { NonNull { pointer: ptr as _ } }
}
#[inline]
pub const fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
// SAFETY: The pointer is already checked and is not null
Some(unsafe { Self::new_unchecked(ptr) })
} else {
None
}
}
}
fn main() { } cargo clippy produces
|
@Manishearth Regarding your arguments: With the false positive above even in |
Yes, and "pointer wrapper types" are rather rare. I would consider such types as a valid reason to disable the lint for the module implementing these types. Clippy lints are by-design not supposed to be perfect, they will need to be disabled based on user preferences or specific edge cases1, this is a case where you acknowledge the lint and disable it. We could potentially allowlist a bunch of APIs and actually check the body of such functions, it's tricky but doable and would cut down on false positives. Footnotes
|
Playground:
produces
which is incorrect since no raw pointer is ever dereferenced anywhere.
The text was updated successfully, but these errors were encountered: