[llvm-bugs] [Bug 31218] Regression(288024): clang miscompiles chromium's safe_math code on arm
via llvm-bugs
llvm-bugs at lists.llvm.org
Fri Dec 2 02:51:38 PST 2016
https://llvm.org/bugs/show_bug.cgi?id=31218
James Molloy <james.molloy at arm.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|ASSIGNED |RESOLVED
Resolution|--- |INVALID
--- Comment #5 from James Molloy <james.molloy at arm.com> ---
Hi Nico,
Sorry it took me a day to get to this.
After a heavy debugging session, I believe this stems from undefined behaviour
in the source code.
>From the ground up...
1) a CheckedNumeric<uint8_t> is constructed via a cast from a
CheckedNumeric<float> and the .IsValid() function called. This function is
expected to return false as the conversion was out of range (overflow).
2) IsValid() returns a function of __isfinitef() and the ::is_valid member. The
Cast function ends up simply calling a constructor:
9184 constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
9185 : state_(rhs.state_.value(), rhs.IsValid()) {}
3) CheckedNumeric<uint8_t>'s struct layout is simply {uint8_t value, uint8_t
is_valid_} (via CheckedNumericState). Therefore, it is represented as an i16
with the high bits being is_valid_.
4) The constructor is implemented similarly to:
i16 constructor(float value) {
i8 lo = (uint8_t)value;
i8 hi = 0;
if (!__is_finite(value)) {
hi = 1;
} else {
hi = IsValueInRangeForNumericType<uint8_t>((float)value) == 0; // This is
the test that is supposed to set _is_valid = false when value is out of range
for the dst type
}
return (i16)lo | ((i16)hi << 8);
}
5) The cast from float to uint8_t in the first line is undefined behaviour if
value is not representable in uint8_t. As the underlying storage is a register
(32 bits), this ends up setting some high bits, which makes the _is_valid
member of the struct nonzero.
6) LLVM's constant folder doesn't model it in this way, modelling it as a
truncation. This is why the expression succeeds or fails depending on the
inlining heuristic.
There should be an explicit bitmask to avoid the undefined behaviour.
Phew! That was actually quite a fun morning...
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20161202/4e0d55f5/attachment.html>
More information about the llvm-bugs
mailing list