-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8324833: Signed integer overflows in ABS #17617
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 shade! A progress list of the required criteria for merging this PR into |
Webrevs
|
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.
Looks good. All of these are improvements, I think.
|
@shipilev This change is no longer ready for integration - check the PR body for details. |
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.
Looks good. I submitted testing.
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.
My testing passed.
|
Thanks! Any other reviews? I am planning to integrate this today. |
|
This seems to introduce a lot of potential warnings if -Wsigned-conversion is ever enabled. Use of checked_cast() could solve this, but I only see it used in one place. |
|
Yes, I think we care. I would try a build with |
Let me try your latest with -Wsigned-conversion turned on. If I remember correctly, checked_cast doesn't always work right when the "signed-ness" changes (signed --> unsigned or unsigned --> signed). |
|
I think it's confusing and error-prone to use uabs() for signed values. Using |
|
Another alternative, leave ABS as is, but have it check for invalid inputs, and again fix the callers that are passing values like MIN_VALUE. |
It should work. The checked_cast from signed --> unsigned can never overflow and is always well-defined, but the overflow behaviour in the other direction is implementation defined. Having said that, it's defined the same way on every compiler we use AFAIK |
uabs itself has no UB. I don't think checked_cast has either: at worst it's implementation defined.
That's a good idea too, but it doesn't solve the problems uabs was designed to solve. |
|
The undefined behavior I was talking about is what abs(INT_MIN) returns on two's complement, and the problem with checked_cast is that checked_cast<int,uint>(0x80000000u) won't complain, because the bits match, but having the sign change to negative may not be what the caller wants, especially when using ABS. |
I don't believe ABS is undefined if we go from signed to unsigned, via uabs, and back to signed. The conversion from signed->unsigned is well defined, as is the negation of the unsigned value, and the conversion from unsigned back to signed is at worst implementation defined. ABS is undefined when there is an arithmetic overflow, and in this case there is none. |
|
I didn't mean to say ABS() can't be implemented in C++ without UB. But if it returns a negative number, then that seems surprising. For reference, the Linux man page for the abs(3) library call says "Trying to take the absolute value of the most negative integer is not defined." |
Getting back to this... AFAICS, I am re-running tests with -ftrapv now. |
| // overflow: max_jint - stride_con max. -1 so there's no need for a | ||
| // loop limit check if the exit test is <= or >=. | ||
| int iters_limit = max_jint - ABS(stride_con) - 1; | ||
| int iters_limit = max_jint - uabs(stride_con) - 1; |
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 appears iters_limit can become -1 or -2 here, depending on the value of stride_con. See below for the problem.
| #endif | ||
| // At least 2 iterations so counted loop construction doesn't fail | ||
| if (iters_limit/ABS(stride_con) < 2) { | ||
| if (iters_limit/uabs(stride_con) < 2) { |
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.
Previously negative values of iters_limit would cause us to return false here. Now the comparison is unsigned, so we can get a different result:
stride_con is max_jint
iters_limit is -1
(unsigned) -1 / max_jint is 2
so we no longer return false here.
Using uabs with signed values is error-prone.
| if (loop->is_range_check_if(if_proj, this, T_LONG, phi, range, offset, scale) && | ||
| loop->is_invariant(range) && loop->is_invariant(offset) && | ||
| original_iters_limit / ABS(scale * stride_con) >= min_iters) { | ||
| reduced_iters_limit = MIN2(reduced_iters_limit, original_iters_limit/ABS(scale)); |
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.
Mixing signed and unsigned can cause compiler warnings and a change in semantics. And again, checked_cast is not better than a raw cast here. I think it would be better to make min_iters, reduced_iters_limit, original_iters_limit all unsigned.
|
@shipilev this pull request can not be integrated into git checkout JDK-8324833-uabs
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
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.
Unfortunately, I'm now convinced this is the wrong approach and introduces bugs. I would rather see illegal inputs caught (JDK-8328934) and prevented on a case-by-case basis (see JDK-8329163 for example).
|
All right, I am abandoning this PR. |
See the details in the bug. I think current
ABSimplementation is beyond repair, and we should just switch touabs.Additional testing:
allwith-ftrapv(now fully passes!)allProgress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/17617/head:pull/17617$ git checkout pull/17617Update a local copy of the PR:
$ git checkout pull/17617$ git pull https://git.openjdk.org/jdk.git pull/17617/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 17617View PR using the GUI difftool:
$ git pr show -t 17617Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/17617.diff
Webrev
Link to Webrev Comment