6992121: StringBuilder.ensureCapacity(int minCap) throws OutOfMemoryError with minCap=Integer.MIN_VALUE
Reviewed-by: dholmes, alanb
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Tue Oct 19 09:49:08 2010 -0700
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Tue Oct 19 10:02:25 2010 -0700
@@ -100,7 +100,8 @@
* @param minimumCapacity the minimum desired capacity.
*/
public void ensureCapacity(int minimumCapacity) {
- ensureCapacityInternal(minimumCapacity);
+ if (minimumCapacity > 0)
+ ensureCapacityInternal(minimumCapacity);
}
/**
@@ -108,6 +109,7 @@
* never synchronized.
*/
private void ensureCapacityInternal(int minimumCapacity) {
+ // overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
--- a/jdk/src/share/classes/java/util/ArrayList.java Tue Oct 19 09:49:08 2010 -0700
+++ b/jdk/src/share/classes/java/util/ArrayList.java Tue Oct 19 10:02:25 2010 -0700
@@ -176,6 +176,11 @@
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
+ if (minCapacity > 0)
+ ensureCapacityInternal(minCapacity);
+ }
+
+ private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
@@ -403,7 +408,7 @@
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
- ensureCapacity(size + 1); // Increments modCount!!
+ ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
@@ -420,7 +425,7 @@
public void add(int index, E element) {
rangeCheckForAdd(index);
- ensureCapacity(size + 1); // Increments modCount!!
+ ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
@@ -524,7 +529,7 @@
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
+ ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
@@ -550,7 +555,7 @@
Object[] a = c.toArray();
int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
+ ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
--- a/jdk/src/share/classes/java/util/Vector.java Tue Oct 19 09:49:08 2010 -0700
+++ b/jdk/src/share/classes/java/util/Vector.java Tue Oct 19 10:02:25 2010 -0700
@@ -222,8 +222,10 @@
* @param minCapacity the desired minimum capacity
*/
public synchronized void ensureCapacity(int minCapacity) {
- modCount++;
- ensureCapacityHelper(minCapacity);
+ if (minCapacity > 0) {
+ modCount++;
+ ensureCapacityHelper(minCapacity);
+ }
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/EnsureCapacity.java Tue Oct 19 10:02:25 2010 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 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 6955504 6992121
+ * @summary Test the StringBuilder.ensureCapacity() with negative minimumCapacity
+ * and append() method with negative length input argument.
+ * Also, test the StringBuffer class.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+ public static void main(String[] args) {
+ testStringBuilder();
+ testStringBuffer();
+ }
+
+ private static void checkCapacity(int before, int after) {
+ if (before != after) {
+ throw new RuntimeException("capacity is expected to be unchanged: " +
+ "before=" + before + " after=" + after);
+ }
+ }
+
+ private static void testStringBuilder() {
+ StringBuilder sb = new StringBuilder("abc");
+ int cap = sb.capacity();
+
+ // test if negative minimumCapacity
+ sb.ensureCapacity(Integer.MIN_VALUE);
+ checkCapacity(cap, sb.capacity());
+
+ try {
+ char[] str = {'a', 'b', 'c', 'd'};
+ // test if negative length
+ sb.append(str, 0, Integer.MIN_VALUE + 10);
+ throw new RuntimeException("IndexOutOfBoundsException not thrown");
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ }
+
+ private static void testStringBuffer() {
+ StringBuffer sb = new StringBuffer("abc");
+ int cap = sb.capacity();
+
+ // test if negative minimumCapacity
+ sb.ensureCapacity(Integer.MIN_VALUE);
+ checkCapacity(cap, sb.capacity());
+
+ try {
+ char[] str = {'a', 'b', 'c', 'd'};
+ // test if negative length
+ sb.append(str, 0, Integer.MIN_VALUE + 10);
+ throw new RuntimeException("IndexOutOfBoundsException not thrown");
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ArrayList/EnsureCapacity.java Tue Oct 19 10:02:25 2010 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, 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 6992121
+ * @summary Test the ArrayList.ensureCapacity() and Vector.ensureCapacity
+ * method with negative minimumCapacity input argument.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+ public static void main(String[] args) {
+ testArrayList();
+ testVector();
+ }
+
+ private static void checkCapacity(int before, int after) {
+ if (before != after) {
+ throw new RuntimeException("capacity is expected to be unchanged: " +
+ "before=" + before + " after=" + after);
+ }
+ }
+
+ private static void testArrayList() {
+ ArrayList<String> al = new ArrayList<String>();
+ al.add("abc");
+ al.ensureCapacity(Integer.MIN_VALUE);
+
+ // there is no method to query the capacity of ArrayList
+ // so before and after capacity are not checked
+ }
+
+ private static void testVector() {
+ Vector<String> vector = new Vector<String>();
+ vector.add("abc");
+
+ int cap = vector.capacity();
+ vector.ensureCapacity(Integer.MIN_VALUE);
+ checkCapacity(cap, vector.capacity());
+ }
+}