8218228: The constructor StringBuffer(CharSequence) violates spec for negatively sized argument
authorigerasim
Fri, 01 Mar 2019 12:47:30 -0800
changeset 53977 723f665d0596
parent 53976 5d97784f08bf
child 53978 581c2f4f82d3
8218228: The constructor StringBuffer(CharSequence) violates spec for negatively sized argument Reviewed-by: rriggs, darcy
src/java.base/share/classes/java/lang/AbstractStringBuilder.java
src/java.base/share/classes/java/lang/StringBuffer.java
test/jdk/java/lang/StringBuffer/AppendCharSequence.java
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Fri Mar 01 11:01:49 2019 -0800
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Fri Mar 01 12:47:30 2019 -0800
@@ -93,13 +93,16 @@
 
     /**
      * Creates an AbstractStringBuilder with the specified coder and with
-     * the initial capacity equal to the smaller of (capacity + addition)
+     * the initial capacity equal to the smaller of (length + addition)
      * and Integer.MAX_VALUE.
      */
-    AbstractStringBuilder(byte coder, int capacity, int addition) {
+    AbstractStringBuilder(byte coder, int length, int addition) {
+        if (length < 0) {
+            throw new NegativeArraySizeException("Negative length: " + length);
+        }
         this.coder = coder;
-        capacity = (capacity < Integer.MAX_VALUE - addition)
-                ? capacity + addition : Integer.MAX_VALUE;
+        int capacity = (length < Integer.MAX_VALUE - addition)
+                ? length + addition : Integer.MAX_VALUE;
         value = (coder == LATIN1)
                 ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
     }
--- a/src/java.base/share/classes/java/lang/StringBuffer.java	Fri Mar 01 11:01:49 2019 -0800
+++ b/src/java.base/share/classes/java/lang/StringBuffer.java	Fri Mar 01 12:47:30 2019 -0800
@@ -157,10 +157,6 @@
      * as the specified {@code CharSequence}. The initial capacity of
      * the string buffer is {@code 16} plus the length of the
      * {@code CharSequence} argument.
-     * <p>
-     * If the length of the specified {@code CharSequence} is
-     * less than or equal to zero, then an empty buffer of capacity
-     * {@code 16} is returned.
      *
      * @param      seq   the sequence to copy.
      * @since 1.5
--- a/test/jdk/java/lang/StringBuffer/AppendCharSequence.java	Fri Mar 01 11:01:49 2019 -0800
+++ b/test/jdk/java/lang/StringBuffer/AppendCharSequence.java	Fri Mar 01 12:47:30 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, 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
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4812591 4705328 5019111
+ * @bug 4812591 4705328 5019111 8218228
  * @summary Test append and insert methods with CharSequence params
  * @key randomness
  */
@@ -230,6 +230,35 @@
                 throw new RuntimeException("CharSequence constructor failure");
             }
         }
+        checkNegativeLenCharSeq(-1);
+        checkNegativeLenCharSeq(-16);
+        checkNegativeLenCharSeq(-17);
+        checkNegativeLenCharSeq(Integer.MIN_VALUE);
     }
 
+    // Test constructing from CharSequence of negative length
+    private static void checkNegativeLenCharSeq(int len) {
+        try {
+            CharSequence seq = new MyNegativeLenCharSeq(len);
+            StringBuffer sb = new StringBuffer(seq);
+        } catch (NegativeArraySizeException expected) {
+        } catch (Throwable exc) {
+            throw new RuntimeException("Unexpected: " + exc, exc);
+        }
+    }
+
+    private static class MyNegativeLenCharSeq implements CharSequence {
+        int length;
+        MyNegativeLenCharSeq(int length) {
+            this.length = length;
+        }
+        public char charAt(int i) {
+            throw new UnsupportedOperationException();
+        }
+        public int length() { return length; }
+        public CharSequence subSequence(int st, int e) {
+            throw new UnsupportedOperationException();
+        }
+        public String toString() { return ""; }
+    }
 }