-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Warn on references casting to bigger memory layout #118983
Warn on references casting to bigger memory layout #118983
Conversation
This comment has been minimized.
This comment has been minimized.
Whether this is actually always UB is subject to debate, also called the " |
7e737d4
to
dbf8ac9
Compare
Hum, this is surprising. This may not be as obviously UB (or not) as I though and expected. If this happens to not be (for now) undecided, I can probably change the implementation to find the backing allocation, if possible of course. cc @RalfJung, to have an opsem expert opinion on this. |
This comment has been minimized.
This comment has been minimized.
@Nilstrieb rust-lang/unsafe-code-guidelines#256 seems to be about the size component (read layout size) only? What about the alignment? Casting to reference to reference that requires more alignment, is this UB? |
Creating an unaligned reference is always UB, but you only know at runtime whether the source reference will be aligned or not. |
@Nilstrieb is right. Such a cast is certainly highly suspect, but may or may not always be UB. Tree Borrows allows such casts under certain conditions. |
@RalfJung I suspect that none of those cases can be trivial determined? And that in it's current form this PR cannot make progress until we have an approved/official aliasing model? |
These cases can indeed not be determined trivially, knowing whether the allocation is bigger than the referent is very non-local. |
dbf8ac9
to
e113cbb
Compare
This comment has been minimized.
This comment has been minimized.
e113cbb
to
e8d7b9d
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
af355bf
to
f5e5e9f
Compare
This comment has been minimized.
This comment has been minimized.
b3b4571
to
3b0b09e
Compare
The Miri subtree was changed cc @rust-lang/miri Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
I've updated the implementation to only lint when we can find the allocation, that means that it only works locally. The implementation tries to follow the reference at the start of the casting chain to find those patterns, This should resolve the concern from @est31 this is ready for review |
Is rustc the right place for such a specific lint or should this go to clippy? |
Tests that make sure the lint is conservative with regards to certain patterns that may be accepted in the future would be nice to have. |
I think so. We should warn/deny code that is UB as soon as possible, not wait for people to write their code, clean it up and then run clippy to find out that it is actually not OK. (Not to mention that many people don't use clippy). EDIT: Note that this PR does not add any new lint, it just extends the
Do you have such pattern in mind? I've already restricted the scope to exclude the |
In general, I think there is a place for lints that find instances of code that is obvious true undefined behaviour. The emphasis here lies on obvious: there have to be zero false positives. That's a much higher bar than what many clippy lints need to pass. If the compiler tells the user that some pattern is UB, then the user will believe that much more likely than if clippy said it. That doesn't mean that this particular PR is automatically a good idea. There need to be thorough tests to ensure that there is no false positives. Also, there is many ways that code can be UB, and we cannot write and maintain heuristics for all possible ways: we need to pick the instances which we think are easiest to maintain and that catch the most UB "in the wild". |
3b0b09e
to
e08c9d1
Compare
@bors r+ |
…ayout, r=oli-obk Warn on references casting to bigger memory layout This PR extends the [`invalid_reference_casting`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#invalid-reference-casting) lint (*deny-by-default*) which currently lint on `&T -> &mut T` casting to also lint on `&(mut) A -> &(mut) B` where `size_of::<B>() > size_of::<A>()` (bigger memory layout requirement). The goal is to detect such cases: ```rust let u8_ref: &u8 = &0u8; let u64_ref: &u64 = unsafe { &*(u8_ref as *const u8 as *const u64) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior let mat3 = Mat3 { a: Vec3(0i32, 0, 0), b: Vec3(0, 0, 0), c: Vec3(0, 0, 0) }; let mat3 = unsafe { &*(&mat3 as *const _ as *const [[i64; 3]; 3]) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior ``` This is added to help people who write unsafe code, especially when people have matrix struct that they cast to simple array of arrays. EDIT: One caveat, due to the [`&Header`](rust-lang/unsafe-code-guidelines#256) uncertainty the lint only fires when it can find the underline allocation. ~~I have manually tested all the new expressions that warn against Miri, and they all report immediate UB.~~ r? `@est31`
…iaskrgr Rollup of 10 pull requests Successful merges: - rust-lang#118983 (Warn on references casting to bigger memory layout) - rust-lang#119451 (Gate PR CI on clippy correctness lints) - rust-lang#120273 (compiletest: few naive improvements) - rust-lang#120889 (Implement Instant for UEFI) - rust-lang#120938 (Implement sys/thread for UEFI) - rust-lang#120950 (Fix async closures in CTFE) - rust-lang#120958 (Dejargonize `subst`) - rust-lang#120965 (Add lahfsahf and prfchw target feature) - rust-lang#120970 (add another test for promoteds-in-static) - rust-lang#120979 (Update books) Failed merges: - rust-lang#120973 (allow static_mut_ref in some tests that specifically test mutable statics) r? `@ghost` `@rustbot` modify labels: rollup
…iaskrgr Rollup of 8 pull requests Successful merges: - rust-lang#118983 (Warn on references casting to bigger memory layout) - rust-lang#119451 (Gate PR CI on clippy correctness lints) - rust-lang#120273 (compiletest: few naive improvements) - rust-lang#120950 (Fix async closures in CTFE) - rust-lang#120958 (Dejargonize `subst`) - rust-lang#120965 (Add lahfsahf and prfchw target feature) - rust-lang#120970 (add another test for promoteds-in-static) - rust-lang#120979 (Update books) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#118983 - Urgau:invalid_ref_casting-bigger-layout, r=oli-obk Warn on references casting to bigger memory layout This PR extends the [`invalid_reference_casting`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#invalid-reference-casting) lint (*deny-by-default*) which currently lint on `&T -> &mut T` casting to also lint on `&(mut) A -> &(mut) B` where `size_of::<B>() > size_of::<A>()` (bigger memory layout requirement). The goal is to detect such cases: ```rust let u8_ref: &u8 = &0u8; let u64_ref: &u64 = unsafe { &*(u8_ref as *const u8 as *const u64) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior let mat3 = Mat3 { a: Vec3(0i32, 0, 0), b: Vec3(0, 0, 0), c: Vec3(0, 0, 0) }; let mat3 = unsafe { &*(&mat3 as *const _ as *const [[i64; 3]; 3]) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior ``` This is added to help people who write unsafe code, especially when people have matrix struct that they cast to simple array of arrays. EDIT: One caveat, due to the [`&Header`](rust-lang/unsafe-code-guidelines#256) uncertainty the lint only fires when it can find the underline allocation. ~~I have manually tested all the new expressions that warn against Miri, and they all report immediate UB.~~ r? ``@est31``
…iler-errors Ignore unsized types when trying to determine the size of the original type Fixes rust-lang#121074 a regression from rust-lang#118983
Rollup merge of rust-lang#121104 - Urgau:bigger_layout-fix-fp, r=compiler-errors Ignore unsized types when trying to determine the size of the original type Fixes rust-lang#121074 a regression from rust-lang#118983
…ayout, r=oli-obk Warn on references casting to bigger memory layout This PR extends the [`invalid_reference_casting`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#invalid-reference-casting) lint (*deny-by-default*) which currently lint on `&T -> &mut T` casting to also lint on `&(mut) A -> &(mut) B` where `size_of::<B>() > size_of::<A>()` (bigger memory layout requirement). The goal is to detect such cases: ```rust let u8_ref: &u8 = &0u8; let u64_ref: &u64 = unsafe { &*(u8_ref as *const u8 as *const u64) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior let mat3 = Mat3 { a: Vec3(0i32, 0, 0), b: Vec3(0, 0, 0), c: Vec3(0, 0, 0) }; let mat3 = unsafe { &*(&mat3 as *const _ as *const [[i64; 3]; 3]) }; //~^ ERROR casting references to a bigger memory layout is undefined behavior ``` This is added to help people who write unsafe code, especially when people have matrix struct that they cast to simple array of arrays. EDIT: One caveat, due to the [`&Header`](rust-lang/unsafe-code-guidelines#256) uncertainty the lint only fires when it can find the underline allocation. ~~I have manually tested all the new expressions that warn against Miri, and they all report immediate UB.~~ r? ``@est31``
Why was this FCP approved? The wording in the lint as reported in #124685 is misleading at best. @traviscross are there any notes from the meeting that I can review? I can't really figure out what lang approved or discussed for this change. |
@saethlin It was discussed on 2024-01-03: https://hackmd.io/@rust-lang-team/Hk4z917da#Warn-on-references-casting-to-bigger-memory-layout-rust118983 |
Pkgsrc changes: * Adapt checksums and patches, some have beene intregrated upstream. Upstream chnages: Version 1.78.0 (2024-05-02) =========================== Language -------- - [Stabilize `#[cfg(target_abi = ...)]`] (rust-lang/rust#119590) - [Stabilize the `#[diagnostic]` namespace and `#[diagnostic::on_unimplemented]` attribute] (rust-lang/rust#119888) - [Make async-fn-in-trait implementable with concrete signatures] (rust-lang/rust#120103) - [Make matching on NaN a hard error, and remove the rest of `illegal_floating_point_literal_pattern`] (rust-lang/rust#116284) - [static mut: allow mutable reference to arbitrary types, not just slices and arrays] (rust-lang/rust#117614) - [Extend `invalid_reference_casting` to include references casting to bigger memory layout] (rust-lang/rust#118983) - [Add `non_contiguous_range_endpoints` lint for singleton gaps after exclusive ranges] (rust-lang/rust#118879) - [Add `wasm_c_abi` lint for use of older wasm-bindgen versions] (rust-lang/rust#117918) This lint currently only works when using Cargo. - [Update `indirect_structural_match` and `pointer_structural_match` lints to match RFC] (rust-lang/rust#120423) - [Make non-`PartialEq`-typed consts as patterns a hard error] (rust-lang/rust#120805) - [Split `refining_impl_trait` lint into `_reachable`, `_internal` variants] (rust-lang/rust#121720) - [Remove unnecessary type inference when using associated types inside of higher ranked `where`-bounds] (rust-lang/rust#119849) - [Weaken eager detection of cyclic types during type inference] (rust-lang/rust#119989) - [`trait Trait: Auto {}`: allow upcasting from `dyn Trait` to `dyn Auto`] (rust-lang/rust#119338) Compiler -------- - [Made `INVALID_DOC_ATTRIBUTES` lint deny by default] (rust-lang/rust#111505) - [Increase accuracy of redundant `use` checking] (rust-lang/rust#117772) - [Suggest moving definition if non-found macro_rules! is defined later] (rust-lang/rust#121130) - [Lower transmutes from int to pointer type as gep on null] (rust-lang/rust#121282) Target changes: - [Windows tier 1 targets now require at least Windows 10] (rust-lang/rust#115141) - [Enable CMPXCHG16B, SSE3, SAHF/LAHF and 128-bit Atomics in tier 1 Windows] (rust-lang/rust#120820) - [Add `wasm32-wasip1` tier 2 (without host tools) target] (rust-lang/rust#120468) - [Add `wasm32-wasip2` tier 3 target] (rust-lang/rust#119616) - [Rename `wasm32-wasi-preview1-threads` to `wasm32-wasip1-threads`] (rust-lang/rust#122170) - [Add `arm64ec-pc-windows-msvc` tier 3 target] (rust-lang/rust#119199) - [Add `armv8r-none-eabihf` tier 3 target for the Cortex-R52] (rust-lang/rust#110482) - [Add `loongarch64-unknown-linux-musl` tier 3 target] (rust-lang/rust#121832) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Bump Unicode to version 15.1.0, regenerate tables] (rust-lang/rust#120777) - [Make align_offset, align_to well-behaved in all cases] (rust-lang/rust#121201) - [PartialEq, PartialOrd: document expectations for transitive chains] (rust-lang/rust#115386) - [Optimize away poison guards when std is built with panic=abort] (rust-lang/rust#100603) - [Replace pthread `RwLock` with custom implementation] (rust-lang/rust#110211) - [Implement unwind safety for Condvar on all platforms] (rust-lang/rust#121768) - [Add ASCII fast-path for `char::is_grapheme_extended`] (rust-lang/rust#121138) Stabilized APIs --------------- - [`impl Read for &Stdin`] (https://doc.rust-lang.org/stable/std/io/struct.Stdin.html#impl-Read-for-%26Stdin) - [Accept non `'static` lifetimes for several `std::error::Error` related implementations] (rust-lang/rust#113833) - [Make `impl<Fd: AsFd>` impl take `?Sized`] (rust-lang/rust#114655) - [`impl From<TryReserveError> for io::Error`] (https://doc.rust-lang.org/stable/std/io/struct.Error.html#impl-From%3CTryReserveError%3E-for-Error) These APIs are now stable in const contexts: - [`Barrier::new()`] (https://doc.rust-lang.org/stable/std/sync/struct.Barrier.html#method.new) Cargo ----- - [Stabilize lockfile v4](rust-lang/cargo#12852) - [Respect `rust-version` when generating lockfile] (rust-lang/cargo#12861) - [Control `--charset` via auto-detecting config value] (rust-lang/cargo#13337) - [Support `target.<triple>.rustdocflags` officially] (rust-lang/cargo#13197) - [Stabilize global cache data tracking] (rust-lang/cargo#13492) Misc ---- - [rustdoc: add `--test-builder-wrapper` arg to support wrappers such as RUSTC_WRAPPER when building doctests] (rust-lang/rust#114651) Compatibility Notes ------------------- - [Many unsafe precondition checks now run for user code with debug assertions enabled] (rust-lang/rust#120594) This change helps users catch undefined behavior in their code, though the details of how much is checked are generally not stable. - [riscv only supports split_debuginfo=off for now] (rust-lang/rust#120518) - [Consistently check bounds on hidden types of `impl Trait`] (rust-lang/rust#121679) - [Change equality of higher ranked types to not rely on subtyping] (rust-lang/rust#118247) - [When called, additionally check bounds on normalized function return type] (rust-lang/rust#118882) - [Expand coverage for `arithmetic_overflow` lint] (rust-lang/rust#119432) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Update to LLVM 18](rust-lang/rust#120055) - [Build `rustc` with 1CGU on `x86_64-pc-windows-msvc`] (rust-lang/rust#112267) - [Build `rustc` with 1CGU on `x86_64-apple-darwin`] (rust-lang/rust#112268) - [Introduce `run-make` V2 infrastructure, a `run_make_support` library and port over 2 tests as example] (rust-lang/rust#113026) - [Windows: Implement condvar, mutex and rwlock using futex] (rust-lang/rust#121956)
This PR extends the
invalid_reference_casting
lint (deny-by-default) which currently lint on&T -> &mut T
casting to also lint on&(mut) A -> &(mut) B
wheresize_of::<B>() > size_of::<A>()
(bigger memory layout requirement).The goal is to detect such cases:
This is added to help people who write unsafe code, especially when people have matrix struct that they cast to simple array of arrays.
EDIT: One caveat, due to the
&Header
uncertainty the lint only fires when it can find the underline allocation.I have manually tested all the new expressions that warn against Miri, and they all report immediate UB.r? @est31