Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8230743: StringJoiner does not handle too large strings correctly
Reviewed-by: rriggs, psandoz, martin
  • Loading branch information
JimLaskey committed Jun 5, 2020
1 parent cb960ee commit 4de4200652e790e94cdb0b60635307df916f6dda
@@ -125,6 +125,7 @@ public StringJoiner(CharSequence delimiter,
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
checkAddLength(0, 0);
}

/**
@@ -202,13 +203,22 @@ public StringJoiner add(CharSequence newElement) {
} else {
if (size == elts.length)
elts = Arrays.copyOf(elts, 2 * size);
len += delimiter.length();
len = checkAddLength(len, delimiter.length());
}
len += elt.length();
len = checkAddLength(len, elt.length());
elts[size++] = elt;
return this;
}

private int checkAddLength(int oldLen, int inc) {
long newLen = (long)oldLen + (long)inc;
long tmpLen = newLen + (long)prefix.length() + (long)suffix.length();
if (tmpLen != (int)tmpLen) {
throw new OutOfMemoryError("Requested array size exceeds VM limit");
}
return (int)newLen;
}

/**
* Adds the contents of the given {@code StringJoiner} without prefix and
* suffix as the next element if it is non-empty. If the given {@code
@@ -25,12 +25,14 @@
* @test
* @bug 8017231 8020977 8054221
* @summary test StringJoiner::merge
* @modules java.base/jdk.internal.util
* @run testng MergeTest
*/

import java.util.StringJoiner;
import java.util.stream.Stream;
import org.testng.annotations.Test;
import static jdk.internal.util.ArraysSupport.MAX_ARRAY_LENGTH;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;

@@ -167,4 +169,19 @@ public void testMergeSelf() {
assertEquals(sj.merge(sj).toString(), fixes.pre0 + "a,b,a,b,a,b,a,b" + fixes.suf0);
});
}

public void OOM() {
String maxString = "*".repeat(MAX_ARRAY_LENGTH);

try {
StringJoiner sj1 = new StringJoiner("", "", "");
sj1.add(maxString);
StringJoiner sj2 = new StringJoiner("", "", "");
sj2.add(maxString);
sj1.merge(sj2);
fail("Should have thrown OutOfMemoryError");
} catch (OutOfMemoryError ex) {
// okay
}
}
}
@@ -24,13 +24,17 @@
* @test
* @bug 5015163 7172553
* @summary tests StringJoinerTest
* @modules java.base/jdk.internal.util
* @run testng StringJoinerTest
* @author Jim Gish
*/
import java.util.ArrayList;
import java.util.StringJoiner;
import org.testng.annotations.Test;
import static jdk.internal.util.ArraysSupport.MAX_ARRAY_LENGTH;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;


@Test(groups = {"unit","string","util","libs"})
public class StringJoinerTest {
@@ -320,5 +324,49 @@ public void testDelimiterCombinations() {
testCombos(",", "", ">");
testCombos(",", "<", ">");
}

public void OOM1() {
String maxString = "*".repeat(MAX_ARRAY_LENGTH);

try {
new StringJoiner(maxString, maxString, maxString).toString();
fail("Should have thrown OutOfMemoryError");
} catch (OutOfMemoryError ex) {
// okay
}
}

public void OOM2() {
String maxString = "*".repeat(MAX_ARRAY_LENGTH);

try {
new StringJoiner(maxString, maxString, "").toString();
fail("Should have thrown OutOfMemoryError");
} catch (OutOfMemoryError ex) {
// okay
}
}

public void OOM3() {
String maxString = "*".repeat(MAX_ARRAY_LENGTH);

try {
new StringJoiner(maxString, "", maxString).toString();
fail("Should have thrown OutOfMemoryError");
} catch (OutOfMemoryError ex) {
// okay
}
}

public void OOM4() {
String maxString = "*".repeat(MAX_ARRAY_LENGTH);

try {
new StringJoiner("", maxString, maxString).toString();
fail("Should have thrown OutOfMemoryError");
} catch (OutOfMemoryError ex) {
// okay
}
}
}

0 comments on commit 4de4200

Please sign in to comment.