OpenJDK / jdk / jdk
changeset 53653:868611f0adc3
8218227: StringBuilder/StringBuffer constructor throws confusing NegativeArraySizeException
Reviewed-by: rriggs
author | igerasim |
---|---|
date | Tue, 05 Feb 2019 17:05:40 -0800 |
parents | 262afafdb266 |
children | 7054249afee5 |
files | src/java.base/share/classes/java/lang/AbstractStringBuilder.java src/java.base/share/classes/java/lang/StringBuffer.java src/java.base/share/classes/java/lang/StringBuilder.java test/jdk/java/lang/StringBuffer/HugeCapacity.java test/jdk/java/lang/StringBuilder/HugeCapacity.java |
diffstat | 5 files changed, 136 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Feb 06 00:20:37 2019 +0100 +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Tue Feb 05 17:05:40 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,19 @@ } /** + * Creates an AbstractStringBuilder with the specified coder and with + * the initial capacity equal to the smaller of (capacity + addition) + * and Integer.MAX_VALUE. + */ + AbstractStringBuilder(byte coder, int capacity, int addition) { + this.coder = coder; + capacity = (capacity < Integer.MAX_VALUE - addition) + ? capacity + addition : Integer.MAX_VALUE; + value = (coder == LATIN1) + ? new byte[capacity] : StringUTF16.newBytesFor(capacity); + } + + /** * Compares the objects of two AbstractStringBuilder implementations lexicographically. * * @since 11
--- a/src/java.base/share/classes/java/lang/StringBuffer.java Wed Feb 06 00:20:37 2019 +0100 +++ b/src/java.base/share/classes/java/lang/StringBuffer.java Tue Feb 05 17:05:40 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ */ @HotSpotIntrinsicCandidate public StringBuffer(String str) { - super(str.length() + 16); + super(str.coder(), str.length(), 16); append(str); } @@ -166,7 +166,7 @@ * @since 1.5 */ public StringBuffer(CharSequence seq) { - this(seq.length() + 16); + super(String.LATIN1, seq.length(), 16); append(seq); }
--- a/src/java.base/share/classes/java/lang/StringBuilder.java Wed Feb 06 00:20:37 2019 +0100 +++ b/src/java.base/share/classes/java/lang/StringBuilder.java Tue Feb 05 17:05:40 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,7 @@ */ @HotSpotIntrinsicCandidate public StringBuilder(String str) { - super(str.length() + 16); + super(str.coder(), str.length(), 16); append(str); } @@ -134,7 +134,7 @@ * @param seq the sequence to copy. */ public StringBuilder(CharSequence seq) { - this(seq.length() + 16); + super(String.LATIN1, seq.length(), 16); append(seq); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/lang/StringBuffer/HugeCapacity.java Tue Feb 05 17:05:40 2019 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8218227 + * @summary StringBuilder/StringBuffer constructor throws confusing + * NegativeArraySizeException + * @requires os.maxMemory >= 6G + * @run main/othervm -Xms5G -Xmx5G HugeCapacity + * @ignore This test has huge memory requirements + */ + +public class HugeCapacity { + private static int failures = 0; + + public static void main(String[] args) { + testHugeInitialString(); + testHugeInitialCharSequence(); + if (failures > 0) { + throw new RuntimeException(failures + " tests failed"); + } + } + + private static void testHugeInitialString() { + try { + String str = "Z".repeat(Integer.MAX_VALUE - 8); + StringBuffer sb = new StringBuffer(str); + } catch (OutOfMemoryError ignore) { + } catch (Throwable unexpected) { + unexpected.printStackTrace(); + failures++; + } + } + + private static void testHugeInitialCharSequence() { + try { + CharSequence seq = new MyHugeCharSeq(); + StringBuffer sb = new StringBuffer(seq); + } catch (OutOfMemoryError ignore) { + } catch (Throwable unexpected) { + unexpected.printStackTrace(); + failures++; + } + } + + private static class MyHugeCharSeq implements CharSequence { + public char charAt(int i) { + throw new UnsupportedOperationException(); + } + public int length() { return Integer.MAX_VALUE; } + public CharSequence subSequence(int st, int e) { + throw new UnsupportedOperationException(); + } + public String toString() { return ""; } + } +}
--- a/test/jdk/java/lang/StringBuilder/HugeCapacity.java Wed Feb 06 00:20:37 2019 +0100 +++ b/test/jdk/java/lang/StringBuilder/HugeCapacity.java Tue Feb 05 17:05:40 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,11 @@ /** * @test - * @bug 8149330 + * @bug 8149330 8218227 * @summary Capacity should not get close to Integer.MAX_VALUE unless * necessary - * @run main/othervm -Xmx5G HugeCapacity + * @requires os.maxMemory >= 6G + * @run main/othervm -Xms5G -Xmx5G HugeCapacity * @ignore This test has huge memory requirements */ @@ -36,6 +37,8 @@ public static void main(String[] args) { testLatin1(); testUtf16(); + testHugeInitialString(); + testHugeInitialCharSequence(); if (failures > 0) { throw new RuntimeException(failures + " tests failed"); } @@ -63,4 +66,37 @@ failures++; } } + + private static void testHugeInitialString() { + try { + String str = "Z".repeat(Integer.MAX_VALUE - 8); + StringBuilder sb = new StringBuilder(str); + } catch (OutOfMemoryError ignore) { + } catch (Throwable unexpected) { + unexpected.printStackTrace(); + failures++; + } + } + + private static void testHugeInitialCharSequence() { + try { + CharSequence seq = new MyHugeCharSeq(); + StringBuilder sb = new StringBuilder(seq); + } catch (OutOfMemoryError ignore) { + } catch (Throwable unexpected) { + unexpected.printStackTrace(); + failures++; + } + } + + private static class MyHugeCharSeq implements CharSequence { + public char charAt(int i) { + throw new UnsupportedOperationException(); + } + public int length() { return Integer.MAX_VALUE; } + public CharSequence subSequence(int st, int e) { + throw new UnsupportedOperationException(); + } + public String toString() { return ""; } + } }