-
Notifications
You must be signed in to change notification settings - Fork 29
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
offset_of (and the other macros, too) is unsound #24
Comments
I was reviewing this crate as a part of casual Line 86 in 903e24f
So... what's the end result? Should this crate be reported as unsafe to use right now, and RustSec advisory be filled against it? |
We are not aware of any case where using this crate from safe code causes actual problems. It is UB wrt. the Rust spec, but it turns out that the LLVM IR we generate is not UB -- and we will take care to update this crate should the compiler ever change in that regard. Deliberately having unsound code like this is unfortunate, but this crate is by far not the only one doing that. See rust-lang/unsafe-code-guidelines#158 for a non-exhaustive list. |
Should a rustc version that doe misscompile or generates UB in the IR exist, would that be enough grounds to file a rustsec advisory, negative crev reviews, and request crate yanking? |
I suppose so, but that should be evaluated when/if it happens. |
@RalfJung How would the RFC 2582 help? since doing Also, will we be able to compute the offset in a const function? (Currently, i'm using this trick to compute the offset in a static variable: struct Foo { _d : u32, field : u8 }
union Transmuter<From : Copy, To : Copy> { from : From, to: To }
static OFFSET : usize = unsafe { Transmuter::<*const _, usize>{ from: (&Transmuter::<usize, &Foo>{ from: 0 }.to.field) as *const _ }.to }; But this would also still be UB even when using &raw because we'd still dereference an invalid pointer to get its field) |
I want to add |
Where is there an invalid pointer here?
This is very UB as you are creating a NULL reference. You don't even need to dereference that to cause UB. error[E0080]: could not evaluate static initializer
--> src/lib.rs:3:71
|
3 | static OFFSET : usize = unsafe { Transmuter::<*const _, usize>{ from: (&Transmuter::<usize, &Foo>{ from: 0 }.to.field) as *const _ }.to };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
Right now, that's not possible I am afraid. It's a language feature that Rust does not have yet, comparable to things like const generics or associated type constructors. However, with rust-lang/rust#63810 we can basically use the variant this crate uses in const-eval. It's still UB though and needs |
Notice however that this issue here is about unsoundness of the current #4 is the issue for that. |
Is the |
Quoting from the reference:
The pointer is allocated and aligned. So we do not hit any of the UB clauses.
In C++, uninit memory contains an "indeterminate value" and I don't think constructing an lvalue (or whatever they call them these days) with an indeterminate value is UB. I would expect UB to only arise when the lvaue is turned into an rvalue. I might be wrong though, and it does not matter much here. |
Given that I did a quick copy-and-edit of |
@Nemo157 yes, that looks great. :) |
This is fixed with version 0.6.2 now that we can use the (newly stable!) |
offset_of is one of those things that can be quite difficult to do without triggering UB; see Gilnaa/memoffset#24 for details.
crossbeam 0.8 depends on recent versions of memoffset, which avoids reading of uninitialized memory (Gilnaa/memoffset#24). See https://rustsec.org/advisories/RUSTSEC-2023-0045.html and GHSA-wfg4-322g-9vqv. Signed-off-by: Thomas Krennwallner <tk@postsubmeta.net>
offset_of
is UB because we are creating a reference to a field that has not been initialized yet. (Miri does not currently check references transitively, so tests still pass in Miri.) There is currently no way to avoid this UB when implementingoffset_of!
. progress is blocked on rust-lang/rfcs#2582.We are also "more UB" for older versions of rustc, because we are dereferencing a dangling pointer. We only do it to compute a field address, so no memory access happens, but the dereference is enough to cause UB.
See #9 for other ways in which there used to be "more UB".
The text was updated successfully, but these errors were encountered: