Skip to content

Conversation

@shipilev
Copy link
Member

@shipilev shipilev commented Jan 29, 2024

See the details in the bug. I think current ABS implementation is beyond repair, and we should just switch to uabs.

Additional testing:

  • Linux x86_64 fastdebug, all with -ftrapv (now fully passes!)
  • Linux x86_64 fastdebug, all

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8324833: Signed integer overflows in ABS (Bug - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/17617/head:pull/17617
$ git checkout pull/17617

Update a local copy of the PR:
$ git checkout pull/17617
$ git pull https://git.openjdk.org/jdk.git pull/17617/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 17617

View PR using the GUI difftool:
$ git pr show -t 17617

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/17617.diff

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Jan 29, 2024

👋 Welcome back shade! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Jan 29, 2024

@shipilev The following labels will be automatically applied to this pull request:

  • graal
  • hotspot

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added graal graal-dev@openjdk.org hotspot hotspot-dev@openjdk.org labels Jan 29, 2024
@shipilev shipilev marked this pull request as ready for review January 31, 2024 08:22
@openjdk openjdk bot added the rfr Pull request is ready for review label Jan 31, 2024
@mlbridge
Copy link

mlbridge bot commented Jan 31, 2024

Webrevs

Copy link
Contributor

@theRealAph theRealAph left a 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.

@openjdk
Copy link

openjdk bot commented Jan 31, 2024

@shipilev This change is no longer ready for integration - check the PR body for details.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jan 31, 2024
Copy link
Contributor

@vnkozlov vnkozlov left a 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.

Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My testing passed.

@shipilev
Copy link
Member Author

shipilev commented Feb 1, 2024

Thanks! Any other reviews? I am planning to integrate this today.

@dean-long
Copy link
Member

dean-long commented Feb 1, 2024

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.
@coleenp, @kimbarrett, do we still care about keeping the code -Wsigned-conversion safe?

@shipilev
Copy link
Member Author

shipilev commented Feb 2, 2024

Yes, I think we care. I would try a build with Wsigned-conversion and look where we should sprinkle more checked_cast-s.

@dean-long
Copy link
Member

Yes, I think we care. I would try a build with Wsigned-conversion and look where we should sprinkle more checked_cast-s.

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).

@dean-long
Copy link
Member

I think it's confusing and error-prone to use uabs() for signed values. Using checked_cast silences warnings but doesn't handle the undefined behavior caused by values such as min_jint and min_jlong. I suggest fixing ABS so that it first calls uabs and then safely converts to signed, checking for negative values caused by MIN INT inputs. However, that will cause some new asserts where we are relying on undefine behavior, like in exact_limit() described in JBS, so it seems like that caller needs to be fixed.
Fixing all the -Wsigned-conversion warnings in these files, or even in the changed functions, seems out of scope for this fix.

@dean-long
Copy link
Member

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.

@theRealAph
Copy link
Contributor

Yes, I think we care. I would try a build with Wsigned-conversion and look where we should sprinkle more checked_cast-s.

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).

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

@theRealAph
Copy link
Contributor

I think it's confusing and error-prone to use uabs() for signed values. Using checked_cast silences warnings but doesn't handle the undefined behavior caused by values such as min_jint and min_jlong.

uabs itself has no UB. I don't think checked_cast has either: at worst it's implementation defined.

I suggest fixing ABS so that it first calls uabs and then safely converts to signed, checking for negative values caused by MIN INT inputs.

That's a good idea too, but it doesn't solve the problems uabs was designed to solve.

@dean-long
Copy link
Member

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.

@theRealAph
Copy link
Contributor

The undefined behavior I was talking about is what abs(INT_MIN) returns on two's complement

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.

@dean-long
Copy link
Member

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."

@shipilev
Copy link
Member Author

shipilev commented Feb 22, 2024

I think it's confusing and error-prone to use uabs() for signed values. Using checked_cast silences warnings but doesn't handle the undefined behavior caused by values such as min_jint and min_jlong.

Getting back to this...

AFAICS, uabs is well-defined: all possible values of jlong passed there, including min_jlong would be mapped to a correct unsigned value. We "only" need to make sure that the math is then done over unsigned values. I agree that immediately casting to jlong after uabs is dodgy when we can reasonably get the unsigned julong value from uabs that would not fit in jlong, making it negative. I think I fixed a single place where it can possibly happen.

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;
Copy link
Member

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) {
Copy link
Member

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));
Copy link
Member

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.

@openjdk
Copy link

openjdk bot commented Mar 18, 2024

@shipilev this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

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

@openjdk openjdk bot added merge-conflict Pull request has merge conflict with target branch and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Mar 18, 2024
Copy link
Member

@dean-long dean-long left a 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).

@shipilev
Copy link
Member Author

All right, I am abandoning this PR.

@shipilev shipilev closed this Mar 28, 2024
@shipilev shipilev deleted the JDK-8324833-uabs branch January 8, 2025 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

graal graal-dev@openjdk.org hotspot hotspot-dev@openjdk.org merge-conflict Pull request has merge conflict with target branch

Development

Successfully merging this pull request may close these issues.

4 participants