-
Notifications
You must be signed in to change notification settings - Fork 562
UB: update the extra clause for provenance UB during const evaluation #2091
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
base: master
Are you sure you want to change the base?
Conversation
|
This text currently does not cover the validity of the following in consteval:
|
553a6a8 to
c0c2fb2
Compare
This is already defined to be the same as
These are just structs, from an opsem perspective. We don't currently list them at all, even outside the const-eval clause. |
|
My understanding is that async blocks behave more like unions? I'm not sure. |
|
The current wording also doesn't prohibit mixing pointer fragments with different offsets, like in rust-lang/rust#146291 |
The wording is "all bytes must be fragments of the same original pointer value in the correct order". "same pointer value" means same address/offset and same provenance. |
More like a weird kind of enum. Anyway, they are container types that have fields, and we recurse into them like we recurse into structs and enums. If you think we should be more explicit about closures and async lowering, please file an issue; that is entirely orthogonal to the const-eval clause. |
|
Turns out that async blocks in const is gated behind an unstable feature, so that's a non-issue for the purposes of the reference. |
src/behavior-considered-undefined.md
Outdated
| r[undefined.validity.const-provenance] | ||
| * **In [const context](const_eval.md#const-context)**: In addition to what is described above, | ||
| further provenance-related requirements apply during const evaluation. | ||
| Any value that holds pure integer data (the `i*`/`u*`/`f*` types as well as `bool` and `char`, enum discriminants, and slice metadata) must not carry any provenance. | ||
| Any value that holds pointer data (references, raw pointers, function pointers, and `dyn Trait` metadata) must either carry no provenance, | ||
| or all bytes must be fragments of the same original pointer value in the correct order. | ||
|
|
||
| This implies that transmuting or otherwise reinterpreting a pointer (reference, raw pointer, or function pointer) into a non-pointer type (such as integers) is Undefined Behavior if the pointer had provenance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be good to add an example or two for this section (similar to the examples we looked at on the lang side that motivated the recent changes). That would also help make clear what we mean by a pointer fragment, apropos of the question @ehuss is about to ask.
| further provenance-related requirements apply during const evaluation. | ||
| Any value that holds pure integer data (the `i*`/`u*`/`f*` types as well as `bool` and `char`, enum discriminants, and slice metadata) must not carry any provenance. | ||
| Any value that holds pointer data (references, raw pointers, function pointers, and `dyn Trait` metadata) must either carry no provenance, | ||
| or all bytes must be fragments of the same original pointer value in the correct order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like "pointer fragments" is defined anywhere. Would it be possible to come up with a definition somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's tricky to define in isolation. Maybe it's better to avoid the term and just say all bytes must "come from" the same original pointer value?
The longer answer is that during const-eval, a byte doesn't look quite like what we have defined in the reference currently. It's more like
enum Byte {
Uninit,
/// Initialized byte without provenance.
Init(u8),
/// Pointer fragment. `idx` is in the range `0..ptr_size`.
PointerFragment { ptr: Pointer, idx: u8 },
}c0c2fb2 to
be589ef
Compare
e8f09a4 to
0cea1ca
Compare
The old note didn't make it clear that the transmute is also illegal when it occurs nested inside a field. We already have the framework of "valid values" for this, so let's just use that also for this extra restriction.
Furthermore, there's another way to cause UB with provenance during const evaluation: by having a pointer whose bytes are mixed up.