-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Strict provenance lints #95599
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
Strict provenance lints #95599
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -807,11 +807,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { | |||||
|
||||||
// ptr -> * | ||||||
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast | ||||||
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast | ||||||
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), | ||||||
|
||||||
// * -> ptr | ||||||
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast | ||||||
// ptr-addr-cast | ||||||
(Ptr(m_expr), Int(t_c)) => { | ||||||
self.lossy_provenance_ptr2int_lint(fcx, t_c); | ||||||
self.check_ptr_addr_cast(fcx, m_expr) | ||||||
} | ||||||
(FnPtr, Int(_)) => { | ||||||
// FIXME(#95489): there should eventually be a lint for these casts | ||||||
Ok(CastKind::FnPtrAddrCast) | ||||||
niluxv marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
} | ||||||
// addr-ptr-cast | ||||||
(Int(_), Ptr(mt)) => { | ||||||
self.fuzzy_provenance_int2ptr_lint(fcx); | ||||||
self.check_addr_ptr_cast(fcx, mt) | ||||||
} | ||||||
// fn-ptr-cast | ||||||
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), | ||||||
|
||||||
// prim -> prim | ||||||
|
@@ -973,6 +984,74 @@ impl<'a, 'tcx> CastCheck<'tcx> { | |||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { | ||||||
fcx.tcx.struct_span_lint_hir( | ||||||
lint::builtin::LOSSY_PROVENANCE_CASTS, | ||||||
self.expr.hir_id, | ||||||
self.span, | ||||||
|err| { | ||||||
let mut err = err.build(&format!( | ||||||
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`", | ||||||
self.expr_ty, self.cast_ty | ||||||
)); | ||||||
|
||||||
let msg = "use `.addr()` to obtain the address of a pointer"; | ||||||
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { | ||||||
let scalar_cast = match t_c { | ||||||
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(), | ||||||
_ => format!(" as {}", self.cast_ty), | ||||||
}; | ||||||
err.span_suggestion( | ||||||
self.span, | ||||||
msg, | ||||||
format!("({}).addr(){}", snippet, scalar_cast), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This suggestion can contain unnecessary parenthesis but I have no idea how to reliably check whether There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we have access to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for the hints. Opened #96112. |
||||||
Applicability::MaybeIncorrect | ||||||
); | ||||||
} else { | ||||||
err.help(msg); | ||||||
} | ||||||
err.help( | ||||||
"if you can't comply with strict provenance and need to expose the pointer\ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Currently it is printed without a space, I doubt that is intentional. (Test output also needs to be adjusted then.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I'm too late to modify this PR. Should I open a new one? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that'd be good. :) |
||||||
provenance you can use `.expose_addr()` instead" | ||||||
); | ||||||
|
||||||
err.emit(); | ||||||
}, | ||||||
); | ||||||
} | ||||||
|
||||||
fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { | ||||||
fcx.tcx.struct_span_lint_hir( | ||||||
lint::builtin::FUZZY_PROVENANCE_CASTS, | ||||||
self.expr.hir_id, | ||||||
self.span, | ||||||
|err| { | ||||||
|
||||||
let mut err = err.build(&format!( | ||||||
"strict provenance disallows casting integer `{}` to pointer `{}`", | ||||||
self.expr_ty, self.cast_ty | ||||||
)); | ||||||
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address"; | ||||||
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { | ||||||
err.span_suggestion( | ||||||
self.span, | ||||||
msg, | ||||||
format!("(...).with_addr({})", snippet), | ||||||
Applicability::HasPlaceholders, | ||||||
); | ||||||
} else { | ||||||
err.help(msg); | ||||||
} | ||||||
err.help( | ||||||
"if you can't comply with strict provenance and don't have a pointer with \ | ||||||
the correct provenance you can use `std::ptr::from_exposed_addr()` instead" | ||||||
); | ||||||
|
||||||
err.emit(); | ||||||
}, | ||||||
); | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# `strict_provenance` | ||
|
||
The tracking issue for this feature is: [#95228] | ||
|
||
[#95228]: https://github.com/rust-lang/rust/issues/95228 | ||
----- | ||
|
||
The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. | ||
These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. | ||
The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). | ||
|
||
## Example | ||
|
||
```rust | ||
#![feature(strict_provenance)] | ||
#![warn(fuzzy_provenance_casts)] | ||
|
||
fn main() { | ||
let _dangling = 16_usize as *const u8; | ||
//~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// check-pass | ||
|
||
#![deny(fuzzy_provenance_casts)] | ||
//~^ WARNING unknown lint: `fuzzy_provenance_casts` | ||
//~| WARNING unknown lint: `fuzzy_provenance_casts` | ||
//~| WARNING unknown lint: `fuzzy_provenance_casts` | ||
#![deny(lossy_provenance_casts)] | ||
//~^ WARNING unknown lint: `lossy_provenance_casts` | ||
//~| WARNING unknown lint: `lossy_provenance_casts` | ||
//~| WARNING unknown lint: `lossy_provenance_casts` | ||
|
||
fn main() { | ||
// no warnings emitted since the lints are not activated | ||
|
||
let _dangling = 16_usize as *const u8; | ||
|
||
let x: u8 = 37; | ||
let _addr: usize = &x as *const u8 as usize; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
warning: unknown lint: `fuzzy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:3:1 | ||
| | ||
LL | #![deny(fuzzy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: `#[warn(unknown_lints)]` on by default | ||
= note: the `fuzzy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: unknown lint: `lossy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:7:1 | ||
| | ||
LL | #![deny(lossy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the `lossy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: unknown lint: `fuzzy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:3:1 | ||
| | ||
LL | #![deny(fuzzy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the `fuzzy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: unknown lint: `lossy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:7:1 | ||
| | ||
LL | #![deny(lossy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the `lossy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: unknown lint: `fuzzy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:3:1 | ||
| | ||
LL | #![deny(fuzzy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the `fuzzy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: unknown lint: `lossy_provenance_casts` | ||
--> $DIR/feature-gate-strict_provenance.rs:7:1 | ||
| | ||
LL | #![deny(lossy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: the `lossy_provenance_casts` lint is unstable | ||
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information | ||
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable | ||
|
||
warning: 6 warnings emitted | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#![feature(strict_provenance)] | ||
#![deny(fuzzy_provenance_casts)] | ||
|
||
fn main() { | ||
let dangling = 16_usize as *const u8; | ||
//~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error: strict provenance disallows casting integer `usize` to pointer `*const u8` | ||
--> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20 | ||
| | ||
LL | let dangling = 16_usize as *const u8; | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: the lint level is defined here | ||
--> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9 | ||
| | ||
LL | #![deny(fuzzy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||
= help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead | ||
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address | ||
| | ||
LL | let dangling = (...).with_addr(16_usize); | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![feature(strict_provenance)] | ||
#![deny(lossy_provenance_casts)] | ||
|
||
fn main() { | ||
let x: u8 = 37; | ||
let addr: usize = &x as *const u8 as usize; | ||
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` | ||
|
||
let addr_32bit = &x as *const u8 as u32; | ||
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` | ||
--> $DIR/lint-strict-provenance-lossy-casts.rs:6:23 | ||
| | ||
LL | let addr: usize = &x as *const u8 as usize; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()` | ||
| | ||
note: the lint level is defined here | ||
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 | ||
| | ||
LL | #![deny(lossy_provenance_casts)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||
= help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead | ||
|
||
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` | ||
--> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 | ||
| | ||
LL | let addr_32bit = &x as *const u8 as u32; | ||
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As seen in this example the suggestion lines tend to get really long. Feels suboptimal, but I don't know how to change the way the suggestion is shown. |
||
| | ||
= help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead | ||
|
||
error: aborting due to 2 previous errors | ||
|
Uh oh!
There was an error while loading. Please reload this page.