You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Do you have a concrete example where this leads to breaking memory safety? I can imagine how it might theoretically happen (that is, the behavior of the program as a whole is technically undefined), but I'm not sure that it actually does? I guess I can imagine some compiler saying that "since i1 >> i2 implies i2 < 32, then I'll do some wacky optimization to some expression involving i2..."
@nikomatsakis: LLVM won't reserve a register for the return value, and will just read arbitrary registers on a read of the value, so for example a bounds check could fail to work
an ‘undef‘ “variable” can arbitrarily change its value over its “live range”. This is true because the variable doesn’t actually have a live range. Instead, the value is logically read from arbitrary registers that happen to be around when needed, so the value is not necessarily consistent over time.
I see. Fascinating! Is there a way to "capture" an undefined value and make it constant? For example, storing it to a stack slot and reading it back? (Presumably this load/store could be optimized away, so prob not). If so, we could capture the output of shift operations in this way.
This bug isn't asking for a change in semantics, it's filed to cover a known memory safety hole in the language. The fact that a clear solution has been specified doesn't mean the bug is fixed... pretending memory safety holes don't exist in the implementation doesn't make them go away.
I don't think the RFC addresses this issue at all. Under "unresolved questions", it lists "shifts by an excessive number of bits". It just proposes debug assertions and doesn't prevent undefined behavior in release builds.
Here is a variant of @ruud-v-a 's example that assert fails (in different places) in both -O0 and -O2 modes. (It was adapted from #23551.)
#![allow(exceeding_bitshifts)]fnid<T>(x:T) -> T{ x }fnmain(){let sh = 32;assert_eq!(0,1_i32 << 32);// note that this line "is the same" as the two belowassert_eq!(0,1_i32 << sh);// fails here with -O0assert_eq!(0,1_i32 << id(sh));// fails here with -O2}
Activity
nikomatsakis commentedon Oct 31, 2013
At some point we discussed this in a meeting and decided it was acceptable.
thestinger commentedon Oct 31, 2013
@nikomatsakis: it's not just an unspecified result as I previously thought though, it breaks memory safety
nikomatsakis commentedon Oct 31, 2013
Do you have a concrete example where this leads to breaking memory safety? I can imagine how it might theoretically happen (that is, the behavior of the program as a whole is technically undefined), but I'm not sure that it actually does? I guess I can imagine some compiler saying that "since i1 >> i2 implies i2 < 32, then I'll do some wacky optimization to some expression involving i2..."
thestinger commentedon Oct 31, 2013
@nikomatsakis: LLVM won't reserve a register for the return value, and will just read arbitrary registers on a read of the value, so for example a bounds check could fail to work
nikomatsakis commentedon Oct 31, 2013
@thestinger return value of what function? read of what value? Can you spell it out more?
thestinger commentedon Oct 31, 2013
For example, a pattern like this:
The indexing operation will essentially expand to this:
The
index
value as read for the comparison may be different than the value passed tounsafe_index
.http://llvm.org/docs/LangRef.html#undefined-values
In practice, it likely won't be in most cases, but in a more complex example where there was register pressure it would be.
thestinger commentedon Oct 31, 2013
The key part:
brson commentedon Oct 31, 2013
Nominating.
nikomatsakis commentedon Oct 31, 2013
I see. Fascinating! Is there a way to "capture" an undefined value and make it constant? For example, storing it to a stack slot and reading it back? (Presumably this load/store could be optimized away, so prob not). If so, we could capture the output of shift operations in this way.
pnkfelix commentedon Nov 7, 2013
Accepted for P-backcompat lang. There are a variety of ways to deal with this. We need to choose one. Will discuss further (e.g. in tues mtg).
pcwalton commentedon Nov 22, 2013
I don't think this is backwards incompatible at a language level. It will not cause code that was working OK to stop working. Nominating.
pnkfelix commentedon Dec 19, 2013
changing priority to P-high. not assigning to 1.0 milestone.
27 remaining items
thestinger commentedon Feb 17, 2015
This is a memory safety hole in the implementation. It's an issue regardless of how the language is intended to work per RFCs...
srh commentedon Feb 17, 2015
@steveklabnik How does the overflow RFC address this?
steveklabnik commentedon Feb 17, 2015
Sorry, by 'address' I mean a decision was made, and I'll be documenting the result. Not that it's any different than today.
thestinger commentedon Feb 17, 2015
This bug isn't asking for a change in semantics, it's filed to cover a known memory safety hole in the language. The fact that a clear solution has been specified doesn't mean the bug is fixed... pretending memory safety holes don't exist in the implementation doesn't make them go away.
Gankra commentedon Feb 17, 2015
Agreed this issue should not be closed until UB in safe Rust does not occur.
ben0x539 commentedon Feb 17, 2015
I don't think the RFC addresses this issue at all. Under "unresolved questions", it lists "shifts by an excessive number of bits". It just proposes debug assertions and doesn't prevent undefined behavior in release builds.
pnkfelix commentedon Mar 20, 2015
Here is a variant of @ruud-v-a 's example that assert fails (in different places) in both
-O0
and-O2
modes. (It was adapted from #23551.)playpen
pnkfelix commentedon Mar 20, 2015
@ben0x539 I believe the intent of the RFC is to ensure that the fallback behaviors, when reasonable, do not expose undefined behavior from LLVM.
In these cases, it seems like the fallbacks should simply mask-out the higher order bits as appropriate for each type.
Added panic-on-overflow for rhs of left and right shift expressions.