Skip to content

Float to integer conversion may result in undefined behavior #276

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

Closed
aykevl opened this issue Apr 12, 2019 · 5 comments
Closed

Float to integer conversion may result in undefined behavior #276

aykevl opened this issue Apr 12, 2019 · 5 comments
Assignees
Labels
bug Something isn't working

Comments

@aykevl
Copy link
Member

aykevl commented Apr 12, 2019

The Go spec says this about conversions:

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

In other words, all conversions (including float-to-integer) must be implementation defined and not undefined. At the moment, we use LLVM fptui and fptosi instructions, which have this to say on the matter:

The ‘fptoui’ instruction converts its floating-point operand into the nearest (rounding towards zero) unsigned integer value. If the value cannot fit in ty2, the result is a poison value.

The ‘fptosi’ instruction converts its floating-point operand into the nearest (rounding towards zero) signed integer value. If the value cannot fit in ty2, the result is a poison value.

This basically means that floating point values that cannot be represented as integers (Infinity, NaN, negative numbers in unsigned integers) will produce an arbitrary value that if used may invoke undefined behavior.

This should be fixed. It is probably easiest to wait until https://reviews.llvm.org/D54749 is merged to avoid bloating the code too much.

Similar issue in Rust: rust-lang/rust#10184

@aykevl aykevl added the bug Something isn't working label Apr 12, 2019
@niaow
Copy link
Member

niaow commented Jul 6, 2020

I think maybe we should insert clamping checks for now since that still has not been merged and rust seems to have decided that adding checks was appropriate.

@aykevl
Copy link
Member Author

aykevl commented Jul 7, 2020

Yes that sounds reasonable. Float isn't used much anyway and often it's a softfloat implementation (so relatively slow). I think it's reasonable to add checks and look into optimizations later.

@niaow niaow self-assigned this Jan 1, 2021
@niaow
Copy link
Member

niaow commented Jan 1, 2021

For now I am going to use a select instruction to restrict the output. Once LLVM 12 lands, we can probably use this: https://reviews.llvm.org/rGa89d751fb401540c89189e7c17ff64a6eca98587

@deadprogram deadprogram added the next-release Will be part of next release label Jan 16, 2021
@deadprogram
Copy link
Member

This has been released with v0.17.0 so now closing. Thanks!

@deadprogram deadprogram removed the next-release Will be part of next release label Mar 8, 2021
@aykevl
Copy link
Member Author

aykevl commented Nov 25, 2021

Once we drop support for LLVM 11, we should start using the LLVM intrinsics instead of doing this manually.
See #2300 for progress on LLVM 12 support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants