8230744: Several classes throw OutOfMemoryError without message

Reviewed-by: psandoz, martin, bchristi, rriggs, smarks
This commit is contained in:
Jim Laskey 2020-06-11 10:08:23 -03:00
parent 2085fd32ff
commit 03642a01af
9 changed files with 27 additions and 53 deletions

View file

@ -31,6 +31,7 @@ import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
import jdk.internal.util.ArraysSupport;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.UTF16;
@ -239,7 +240,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by the same amount + 2 if
* Returns the current capacity increased by the current length + 2 if
* that suffices.
* Will not return a capacity greater than
* {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity
@ -250,26 +251,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than (Integer.MAX_VALUE >> coder)
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
int oldLength = value.length;
int newLength = minCapacity << coder;
int growth = newLength - oldLength;
int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder));
if (length == Integer.MAX_VALUE) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
if (UNSAFE_BOUND - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > SAFE_BOUND)
? minCapacity : SAFE_BOUND;
return length >> coder;
}
/**

View file

@ -2187,7 +2187,7 @@ public final class String
resultLen = Math.addExact(thisLen, Math.multiplyExact(
Math.addExact(thisLen, 1), replLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
StringBuilder sb = new StringBuilder(resultLen);
@ -3571,15 +3571,14 @@ public final class String
if (len == 0 || count == 0) {
return "";
}
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (len == 1) {
final byte[] single = new byte[count];
Arrays.fill(single, value[0]);
return new String(single, coder);
}
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
final int limit = len * count;
final byte[] multiple = new byte[limit];
System.arraycopy(value, 0, multiple, 0, len);

View file

@ -357,7 +357,7 @@ final class StringLatin1 {
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (resultLen == 0) {
return "";

View file

@ -661,7 +661,7 @@ final class StringUTF16 {
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (resultLen == 0) {
return "";