-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8349241: Fix the concurrent execution JVM crash of StringBuilder::append(int/long) #23427
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 swen! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
| int spaceNeeded = count + DecimalDigits.stringSize(i); | ||
| ensureCapacityInternal(spaceNeeded); | ||
| byte[] value = ensureCapacityInternal(spaceNeeded); | ||
| if (isLatin1()) { |
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.
This is not safe. The ensureCapacityInternal can read coder == LATIN1 and allocate a small array, but this isLatin1 can read coder == UTF16 and write a UTF16 number out of bounds.
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.
A check that spaceNeeded <= (value.length >> 1) in the else branch would be needed and might be a sufficient safeguard here.
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 made further improvements to improve the thread safety of the coder by passing the newCapacity method into the coder. I think this should be safe enough.
Webrevs
|
|
/reviewers 2 reviewer |
|
@AlanBateman |
|
I am confused about the description. How exactly is the JVM crashed? Does the interpreter or compiled code crash? |
Will cause the JVM to exit directly, the error message is as follows |
|
@wenshao Thank you. This seems to be a GC problem. I adjusted the JBS issue accordingly. You set this to "24" as affected version, but if this is a mainline issue, please add 25 and if possible all other versions this occurs in. If possible, please attach an hs-err file or at least the crash stack. |
I added the hs-err file in the reply above. This is not a GC problem. The getChars method uses StringUTF16.putChar, which is equivalent to Unsafe.putChar. There is no out-of-bounds check. When concurrent, out-of-bounds writes will occur, causing JVM Crash. |
|
On a second examination, I find this is caused by #22023, which is not in 24. And I cannot replicate the oob write on 24. I have updated the affected version to 25 as a result, and updated the caused-by link in the JBS issue. |
| * greater than (Integer.MAX_VALUE >> coder) | ||
| */ | ||
| private int newCapacity(int minCapacity) { | ||
| private static int newCapacity(int minCapacity, byte[] value, byte coder) { |
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.
- Only the current length is needed and should be the argument.
- Add the @param tags for the new arguments.
| */ | ||
| private byte[] ensureCapacityInternal(int minimumCapacity, byte coder) { | ||
| // overflow-conscious code | ||
| byte[] value = this.value; |
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.
Shadowing value is a bug prone, pick a new name.
| * synchronized. | ||
| * If {@code minimumCapacity} is non positive due to numeric | ||
| * overflow, this method throws {@code OutOfMemoryError}. | ||
| */ |
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.
Complete the javadoc with the @param tags and descriptions.
|
Thanks @RogerRiggs, your suggestion is great, I have fixed it, please help me review it again. |
@wenshao I see. Yes, you are right. Interesting - I was not aware of JDK code using unsafe-like put calls internally. |
|
@wenshao This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
|
keep alive |
|
@wenshao This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
|
@wenshao This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
The following code can reproduce the problem, writing out of bounds causes JVM Crash
This problem can be avoided by using the value of ensureCapacityInternal directly.
Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/23427/head:pull/23427$ git checkout pull/23427Update a local copy of the PR:
$ git checkout pull/23427$ git pull https://git.openjdk.org/jdk.git pull/23427/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 23427View PR using the GUI difftool:
$ git pr show -t 23427Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/23427.diff
Using Webrev
Link to Webrev Comment