-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8338449: ubsan: division by zero in sharedRuntimeTrans.cpp #21500
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
Conversation
👋 Welcome back mbaesken! A progress list of the required criteria for merging this PR into |
@MBaesken This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 138 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
static double __ieee754_log(double x) { | ||
double hfsq,f,s,z,R,w,t1,t2,dk; | ||
int k,hx,i,j; | ||
unsigned lx; | ||
|
||
static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 required"); |
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.
I'm not sure what the implications of this actually are. Do we really need it? Maybe @jddarcy can comment?
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.
I'm not sure what the implications of this actually are. Do we really need it? Maybe @jddarcy can comment?
It needs to return -Inf. ubsan seems wrong here: this IEEE-754 arithmetic is well defined, and has been for a very long while.
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.
Ubsan is just following the C++ standard
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
5.6 Multiplicative operators
....
'The binary / operator yields the quotient, and the binary % operator yields the remainder from the division
of the first expression by the second. If the second operand of / or % is zero the behavior is undefined.'
See also https://stackoverflow.com/questions/42926763/the-behaviour-of-floating-point-division-by-zero .
However on our set of platforms in OpenJDK we probably get away with the expected results when dividing by 0 (because they all seem to follow IEEE-754).
That's why I just added the static_assert.
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.
To me, this feels like the C++ standard is not compatible with IEEE-754 arithmetic. Undefined behavior would give the optimizer freedom to do whatever it likes to do. That is in contrast to the well-defined IEEE-754 requirement.
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.
ATTRIBUTE_NO_UBSAN
suppresses conditions found by ubsan instrumentation. If
ubsan is enabled, the compiler's optimizer presumably doesn't take advantage
of the no-UB assumption, as that would defeat the point of ubsan. But in a
non-ubsan-enabled build, I think that attribute does nothing and the compiler
may take advantage of the no-UB assumption. So that part of the change may not
do anything useful for non-ubsan builds.
cppreference is inconsistent about this. It first states that division by zero
is UB, as per the standard. But then it says if the type is_iec599
, then
division by zero returns the IEEE defined value (correctly signed infinity if
lhs is non-zero, NaN if lhs is zero) and raises the appropriate floating point
trap. I think this claim makes sense for a C compiler that supports Annex F.
But C++ isn't C, and I don't see anything comparable in a C++ standard.
I can't find any text in any version of either the C or C++ standard to
support the claimed is_iec599
behavior though.
I did find this, which has some interesting bits.
https://stackoverflow.com/questions/42926763/the-behaviour-of-floating-point-division-by-zero
For example, it is suggested that claiming is_iec599
implicity defines the
behavior for floating point division by zero (among other things). It is also
mentioned that gcc does that, but (some version of?) clang-the-compiler
doesn't implement iec599, even though the standard library one is using might
claim so. Hm...
It also mentions that the default for -fsanitize=undefined
for clang includes
float-divide-by-zero
, while gcc does not. Any chance the reported issue is
arising with clang as the compiler?
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.
Never mind my question about whether this was happening with clang as the compiler rather than gcc.
Our ubsan configuration explicitly includes -fsantize=float-divide-by-zero
.
https://github.com/openjdk/jdk/blame/8bcd4920f1b03d0ef8e295e53557c629f05ceaa4/make/autoconf/jdk-options.m4#L516
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.
I'm not sure what the implications of this actually are. Do we really need it? Maybe @jddarcy can comment?
Catching up on email, whatever the appropriate C/C++ idiom is, it is appropriate for this file to assert "use IEEE 754 semantics for floating-point operations." The divide by zero behavior is well-defined by IEEE 754/IEC 559.
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's not clear there is any in-language mechanism (whether portable or compiler-specific) for reliably requesting or verifying that one will get that behavior. A static_assert of is_iec599 might be sufficient verification, but the standard is at least unclear on that. But that seems to be the best we've got.
java/text/Format/CompactNumberFormat/TestCompactNumber.java trigger the issue too (when using ubsan - enabled binaries on linux ppc64le). |
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.
After all the discussion: LGTM.
If this file requires certain IEEE divide-by-zero semantics, then should we also add static asserts for those? Something like: |
These expressions are UB, so not constexpr, so shouldn't be usable in a static_assert. And indeed, gcc says
|
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.
I don't see a better approach than the addition of the static_asserts. I wish
the language standards were clearer, but oh well...
OK, then how about regular runtime asserts? They would only be in debug builds and the compiler should be able to figure out the result at build time. |
UB => nasal demons, including passing the test on a platform that should fail. |
Thanks for the reviews ! The other static_assert could be added in a separate PR if they are really desired. /integrate |
Going to push as commit 37cfaa8.
Your commit was automatically rebased without conflicts. |
When running with ubsan enabled binaries on Linux ppc64le, some divisions by zero are detected in the java/lang/Math jdk jtreg tests dealing with log - related calculations.
java/lang/Math/Log10Tests.java: Tests for {Math, StrictMath}.log10
/jdk/src/hotspot/share/runtime/sharedRuntimeTrans.cpp:219:27: runtime error: division by zero
#0 0x7fffa7e14abc in SharedRuntime::dlog10(double) (/build_ubsan/images/jdk/lib/server/libjvm.so+0x69f4abc)
#1 0x7fff8b8fc8e8 ()
test
java/lang/Math/LogTests.java: Tests for {Math, StrictMath}.log
/jdk/src/hotspot/share/runtime/sharedRuntimeTrans.cpp:125:27: runtime error: division by zero
#0 0x7fff887f48bc in __ieee754_log(double) (/build_ubsan/images/jdk/lib/server/libjvm.so+0x69f48bc)
#1 0x7fff6b8fc768 ()
test
java/lang/Math/PowTests.java: Tests for {Math, StrictMath}.pow
/jdk/src/hotspot/share/runtime/sharedRuntimeTrans.cpp:508:23: runtime error: division by zero
#0 0x7fff92fd61f0 in SharedRuntime::dpow(double, double) (/build_ubsan/images/jdk/lib/server/libjvm.so+0x69f61f0)
#1 0x7fff7701c8ec ()
The coding does intentional division by zero.
We should probably check for IEEE compliance (or rewrite the coding); but checking for compliance might be sufficient.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/21500/head:pull/21500
$ git checkout pull/21500
Update a local copy of the PR:
$ git checkout pull/21500
$ git pull https://git.openjdk.org/jdk.git pull/21500/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 21500
View PR using the GUI difftool:
$ git pr show -t 21500
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/21500.diff
Webrev
Link to Webrev Comment