-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
floating point to integer casts can cause undefined behaviour #10184
Comments
Nominating |
accepted for P-high, same reasoning as #10183 |
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. |
changing to P-high, same reasoning as #10183 |
How do we propose to solve this and #10185? Since whether behaviour is defined or not depends on the dynamic value of the number being cast, it seems the only solution is to insert dynamic checks. We seem to agree we do not want to do that for arithmetic overflow, are we happy to do it for cast overflow? |
We could add an intrinsic to LLVM that performs a "safe conversion". @zwarich may have other ideas. |
AFAIK the only solution at the moment is to use the target-specific intrinsics. That's what JavaScriptCore does, at least according to someone I asked. |
Oh, that's easy enough then. |
ping @pnkfelix is this covered by the new overflow checking stuff? |
These casts are not checked by rustc with debug assertions. |
I'm happy to handle this, but I need a concrete solution. I personally think that it should be checked along with overflowing integer arithmetic, as it's a very similar issue. I don't really mind what we do though. Note that this issue is currently causing an ICE when used in certain constant expressions. |
This allows violating memory safety in safe rust, example from this forum post:
#[inline(never)]
pub fn f(ary: &[u8; 5]) -> &[u8] {
let idx = 1e100f64 as usize;
&ary[idx..]
}
fn main() {
println!("{}", f(&[1; 5])[0xdeadbeef]);
}
|
Marking with I-unsound given the violation of memory safety in safe rust. |
@bluss , this does not segfualt for me, just gives an assertion error. untagging since i was the one who added it |
Sigh, I forgot the -O, re-tagging. |
re-nominating for P-high. Apparently this was at some point P-high but got lower over time. This seems pretty important for correctness. EDIT: didn’t react to triage comment, adding label manually. |
It seems like the precedent from the overflow stuff (e.g. for shifting) is to just settle on some behavior. Java seems to produce the result modulo the range, which seems not unreasonable; I'm not sure just what kind of LLVM code we'd need to handle that. |
I've posted #71269 (comment) which documents the current state as I understood it and that PR also moves to stabilize the behavior of the saturating -Z flag. Given the length of this thread I think if folks feel that I've missed anything in that comment, I would direct commentary to the PR, or, if it's minor, feel free to ping me on Zulip or Discord (simulacrum) and I can fix things up to avoid unnecessary noise on the PR thread. I expect that someone on the language team will likely start an FCP proposal on that PR soon, and merging it will automatically close this issue out :) |
Are there plans for checked conversions? Something like |
You'll need to consider what should |
…nikic Define UB in float-to-int casts to saturate This closes rust-lang#10184 by defining the behavior there to saturate infinities and values exceeding the integral range (on the lower or upper end). `NaN` is sent to zero.
Allow implementing `Hash` with derived `PartialEq` (`derive_hash_xor_eq` This is a common pattern and is totally allowed by the `Hash` trait. Fixes rust-lang#2627 changelog: Move: Renamed `derive_hash_xor_eq` to [`derived_hash_with_manual_eq`] [rust-lang#10184](rust-lang/rust-clippy#10184) changelog: Enhancement: [`derived_hash_with_manual_eq`]: Now allows `#[derive(PartialEq)]` with custom `Hash` implementations [rust-lang#10184](rust-lang/rust-clippy#10184) <!-- changelog_checked -->
This is a backport of a change from Raph made in the CPU sparse strips experiment. When converting from `f32` to `u8`, the code was clamping to be sure that the values were within range. This was necessary in the past, but hasn't been needed for some years now, since <rust-lang/rust#10184>. This clamping is not necessary and the compiler is not optimizing it away as of Rust 1.83 on Apple Silicon.
This is a backport of a change from Raph made in the CPU sparse strips experiment. When converting from `f32` to `u8`, the code was clamping to be sure that the values were within range. This was necessary in the past, but hasn't been needed for some years now, since <rust-lang/rust#10184>. This clamping is not necessary and the compiler is not optimizing it away as of Rust 1.83 on Apple Silicon.
Status as of 2020-04-18
We intend to stabilize the saturating-float-casts behavior for
as
, and have stabilized unsafe library functions that handle the previous behavior. See #71269 for the latest discussion on that stabilization process.Status as of 2018-11-05
A flag has been implemented in the compiler,
-Zsaturating-float-casts
, which will cause all float to integer casts have "saturating" behavior where if it's out of bounds it's clamped to the nearest bound. A call for benchmarking of this change went out awhile ago. Results, while positive in many projects, are quite negative for some projects and indicates that we're not done here.The next steps are figuring out how to recover performance for these cases:
as
cast behavior (which is UB in some cases) and addunsafe
functions for the relevant types and such.freeze
concept which means that we get a garbage bit pattern, but it's at least not UBOld status
UPDATE (by @nikomatsakis): After much discussion, we've got the rudiments of a plan for how to address this problem. But we need some help with actually investigating the performance impact and working out the final details!
ORIGINAL ISSUE FOLLOWS:
The text was updated successfully, but these errors were encountered: