From d0f3de3b59f19c9e440e782466a7ced03f84f2c7 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 19 Oct 2010 10:02:25 -0700 Subject: [PATCH] 6992121: StringBuilder.ensureCapacity(int minCap) throws OutOfMemoryError with minCap=Integer.MIN_VALUE Reviewed-by: dholmes, alanb --- .../java/lang/AbstractStringBuilder.java | 4 +- .../share/classes/java/util/ArrayList.java | 13 ++- jdk/src/share/classes/java/util/Vector.java | 6 +- .../lang/StringBuilder/EnsureCapacity.java | 81 +++++++++++++++++++ .../java/util/ArrayList/EnsureCapacity.java | 64 +++++++++++++++ 5 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 jdk/test/java/lang/StringBuilder/EnsureCapacity.java create mode 100644 jdk/test/java/util/ArrayList/EnsureCapacity.java diff --git a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java index 46a14a0aa20..d495f07c3f6 100644 --- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java @@ -100,7 +100,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @param minimumCapacity the minimum desired capacity. */ public void ensureCapacity(int minimumCapacity) { - ensureCapacityInternal(minimumCapacity); + if (minimumCapacity > 0) + ensureCapacityInternal(minimumCapacity); } /** @@ -108,6 +109,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * never synchronized. */ private void ensureCapacityInternal(int minimumCapacity) { + // overflow-conscious code if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); } diff --git a/jdk/src/share/classes/java/util/ArrayList.java b/jdk/src/share/classes/java/util/ArrayList.java index 4b746ea0124..7c6eded3a83 100644 --- a/jdk/src/share/classes/java/util/ArrayList.java +++ b/jdk/src/share/classes/java/util/ArrayList.java @@ -176,6 +176,11 @@ public class ArrayList extends AbstractList * @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 @@ public class ArrayList extends AbstractList * @return true (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 class ArrayList extends AbstractList 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 class ArrayList extends AbstractList public boolean addAll(Collection 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 @@ public class ArrayList extends AbstractList 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) diff --git a/jdk/src/share/classes/java/util/Vector.java b/jdk/src/share/classes/java/util/Vector.java index 8517b887746..e508aa5b5c0 100644 --- a/jdk/src/share/classes/java/util/Vector.java +++ b/jdk/src/share/classes/java/util/Vector.java @@ -222,8 +222,10 @@ public class Vector * @param minCapacity the desired minimum capacity */ public synchronized void ensureCapacity(int minCapacity) { - modCount++; - ensureCapacityHelper(minCapacity); + if (minCapacity > 0) { + modCount++; + ensureCapacityHelper(minCapacity); + } } /** diff --git a/jdk/test/java/lang/StringBuilder/EnsureCapacity.java b/jdk/test/java/lang/StringBuilder/EnsureCapacity.java new file mode 100644 index 00000000000..f1ef16ee8d3 --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/EnsureCapacity.java @@ -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) { + } + } +} diff --git a/jdk/test/java/util/ArrayList/EnsureCapacity.java b/jdk/test/java/util/ArrayList/EnsureCapacity.java new file mode 100644 index 00000000000..a8e5f42ac6b --- /dev/null +++ b/jdk/test/java/util/ArrayList/EnsureCapacity.java @@ -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 al = new ArrayList(); + 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 vector = new Vector(); + vector.add("abc"); + + int cap = vector.capacity(); + vector.ensureCapacity(Integer.MIN_VALUE); + checkCapacity(cap, vector.capacity()); + } +}