Skip to content

add lint deref_nullptr detecting when a null ptr is dereferenced #83948

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

Merged
merged 7 commits into from
Apr 14, 2021

Conversation

ABouttefeux
Copy link
Contributor

@ABouttefeux ABouttefeux commented Apr 6, 2021

fixes #83856
changelog: add lint that detect code like

unsafe {
      &*core::ptr::null::<i32>()
 };
unsafe {
     addr_of!(*std::ptr::null::<i32>())
};
let x: i32 = unsafe {*core::ptr::null()};
let x: i32 = unsafe {*core::ptr::null_mut()};
unsafe {*(0 as *const i32)};
unsafe {*(core::ptr::null() as *const i32)};
warning: Dereferencing a null pointer causes undefined behavior
 --> src\main.rs:5:26
  |
5 |     let x: i32 = unsafe {*core::ptr::null()};
  |                          ^^^^^^^^^^^^^^^^^^
  |                          |
  |                          a null pointer is dereferenced
  |                          this code causes undefined behavior when executed
  |
  = note: `#[warn(deref_nullptr)]` on by default

Limitation:
It does not detect code like

const ZERO: usize = 0;
unsafe {*(ZERO as *const i32)};

or code where 0 is not directly a literal

@rust-highfive
Copy link
Contributor

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @lcnr (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 6, 2021
@ABouttefeux ABouttefeux changed the title add lint deref_nullptr detecting when a null ptr is dereference add lint deref_nullptr detecting when a null ptr is dereferenced Apr 6, 2021
@rust-log-analyzer

This comment has been minimized.

@jyn514
Copy link
Member

jyn514 commented Apr 6, 2021

I thought the plan was to uplift the existing clippy lint?

@jyn514
Copy link
Member

jyn514 commented Apr 6, 2021

r? @RalfJung

@rust-highfive rust-highfive assigned RalfJung and unassigned lcnr Apr 6, 2021
@RalfJung
Copy link
Member

RalfJung commented Apr 6, 2021

Thanks a lot. :)
It might take until the weekend that I have time to review this. However, one thing already: please add a test file in src/test/ui. See the docs for how to write a test.

The CI failure is caused by that file crossing the threshold of 3000 lines... I am not sure what to do about that though, so adding // ignore-tidy-filelength to the file seems okay to me. 🤷

@RalfJung
Copy link
Member

RalfJung commented Apr 6, 2021

I thought the plan was to uplift the existing clippy lint?

Yeah it is at least the easiest option I think... @ABouttefeux did you use the clippy lint as a basis or write this from scratch? It would be good to at least ensure that we catch all the same cases. Clippy will likely have tests that you can also use as inspiration.

@ABouttefeux
Copy link
Contributor Author

I wrote it from scratch. I will look at the clippy lint.

@ABouttefeux
Copy link
Contributor Author

Also from what I see the lint clippy::zero_ptr is different from what is described in #83856.
From clippy's documentation

What it does

Catch casts from 0 to some pointer type

Example

// Bad
let a = 0 as *const u32;

// Good
let a = std::ptr::null::<u32>();

@RalfJung
Copy link
Member

RalfJung commented Apr 7, 2021

@ABouttefeux good point, that lint is not what we are looking for. Thanks for checking. :)

@RalfJung
Copy link
Member

RalfJung commented Apr 7, 2021

changelog: add lint that detect code like

Would be good to also mention &*core::ptr::null() and addr_of!(core::ptr::null()) in your examples (and have them in the test), just to drive home the point that the lint fires even in place expression context.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@RalfJung
Copy link
Member

RalfJung commented Apr 9, 2021

This looks good to me. :)
I'll inquire if any further approval is needed to add a new lint.

@ABouttefeux
Copy link
Contributor Author

Thank you for your help 🎉

@RalfJung
Copy link
Member

Thanks for working on this. ❤️

@RalfJung
Copy link
Member

RalfJung commented Apr 10, 2021

Btw, does this also detect addr_of!((*ptr::null::<Struct>()).field)?

if not, that could be an interesting future extension of this lint. :) If yes, please add a test. :D

@ABouttefeux
Copy link
Contributor Author

ABouttefeux commented Apr 10, 2021

I think it should detect that. I will add a test

@apiraino
Copy link
Contributor

@scottmcm which team the I-nominated is relevant to? Perhaps the T-compiler? (asking because in case, this issue can be mentioned tomorrow during the compiler team meeting). Specifically, what should be discussed? Whether this should be a clippy lint?

(thanks for the additional context)

@RalfJung RalfJung added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Apr 14, 2021
@RalfJung
Copy link
Member

I was told lints are lang team territory so setting the flag accordingly.

@RalfJung
Copy link
Member

@scottmcm wrote on Zulip

Personally, I think it should just go in because it's not a one-way door -- we can always tweak it (behaviour, severity, or even remove it entirely) later if needed, so I don't see a strict need for an FCP. I'll motion that you can r+ it on my lang member "seems reasonable", the same way unstable library items can go in on a libs member "seems reasonable".

So, let's go with this then. :) @bors r+

@bors
Copy link
Collaborator

bors commented Apr 14, 2021

📌 Commit 7f0f83a has been approved by RalfJung

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 14, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 14, 2021
…alfJung

add lint deref_nullptr detecting when a null ptr is dereferenced

fixes rust-lang#83856
changelog: add lint that detect code like
```rust
unsafe {
      &*core::ptr::null::<i32>()
 };
unsafe {
     addr_of!(std::ptr::null::<i32>())
};
let x: i32 = unsafe {*core::ptr::null()};
let x: i32 = unsafe {*core::ptr::null_mut()};
unsafe {*(0 as *const i32)};
unsafe {*(core::ptr::null() as *const i32)};
```
```
warning: Dereferencing a null pointer causes undefined behavior
 --> src\main.rs:5:26
  |
5 |     let x: i32 = unsafe {*core::ptr::null()};
  |                          ^^^^^^^^^^^^^^^^^^
  |                          |
  |                          a null pointer is dereferenced
  |                          this code causes undefined behavior when executed
  |
  = note: `#[warn(deref_nullptr)]` on by default
```

Limitation:
It does not detect code like
```rust
const ZERO: usize = 0;
unsafe {*(ZERO as *const i32)};
```
or code where `0` is not directly a literal
@bors
Copy link
Collaborator

bors commented Apr 14, 2021

⌛ Testing commit 7f0f83a with merge 7537b20...

@bors
Copy link
Collaborator

bors commented Apr 14, 2021

☀️ Test successful - checks-actions
Approved by: RalfJung
Pushing 7537b20 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 14, 2021
@bors bors merged commit 7537b20 into rust-lang:master Apr 14, 2021
@rustbot rustbot added this to the 1.53.0 milestone Apr 14, 2021
@rust-highfive
Copy link
Contributor

📣 Toolstate changed by #83948!

Tested on commit 7537b20.
Direct link to PR: #83948

💔 miri on windows: test-pass → test-fail (cc @oli-obk @RalfJung @eddyb).
💔 miri on linux: test-pass → test-fail (cc @oli-obk @RalfJung @eddyb).

rust-highfive added a commit to rust-lang-nursery/rust-toolstate that referenced this pull request Apr 14, 2021
Tested on commit rust-lang/rust@7537b20.
Direct link to PR: <rust-lang/rust#83948>

💔 miri on windows: test-pass → test-fail (cc @oli-obk @RalfJung @eddyb).
💔 miri on linux: test-pass → test-fail (cc @oli-obk @RalfJung @eddyb).
@WaffleLapkin
Copy link
Member

PR description is a bit missleading:

unsafe {
     addr_of!(std::ptr::null::<i32>())
};

Doesn't trigger the lint (there is no dereference), moreover this doesn't compile (cannot take address of a temporary).

What does trigger the lint is

unsafe {
     addr_of!(*std::ptr::null::<i32>())
     //       ^ deref
};

@RalfJung
Copy link
Member

@WaffleLapkin thanks for pointing that out, I fixed the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add lint to detect dereferencing of NULL pointers