JDK-8218649 : The constructor StringBuffer(CharSequence) violates spec for negatively sized argument
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 13
  • Submitted: 2019-02-08
  • Updated: 2022-08-09
  • Resolved: 2019-03-01
Related Reports
CSR :  
Description
Summary
-------

Javadoc for the constructor StringBuffer​(CharSequence seq) includes a promise that contradicts to the actual behavior.

Problem
-------

Javadoc for the constructor StringBuffer​(CharSequence seq) states that "If the length of the specified CharSequence is less than or equal to zero, then an empty buffer of capacity 16 is returned."
In fact, this promise is not kept with the current implementation:  Passing negatively sized CharSequence results in an exception to be thrown.

Moreover, the exception thrown is not consistent:  For some inputs (if length is from range [-16, -1]) it is IndexOutOfBoundsException and for other inputs (if length is less then -16) it is NegativeArraySizeException.
This behavior is also observed with the constructor StringBuilder(CharSequence).

Solution
--------

It is proposed to remove the quoted sentence from the javadoc.

For consistency, for any negatively sized argument, NegativeArraySizeException will be thrown from StringBuilder(CharSequence) and StringBuffer(CharSequence) constructors.

Specification
-------------
The javadoc will be modified as following:

    -     * <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.


Comments
Moving to Approved contingent on JDK-8219409 being addressed later in JDK 13.
01-03-2019

Filed JDK-8219409 as a follow-up issue.
20-02-2019

This issue doesn't really deal with large capacities close to Integer.MAX_VALUE. Do you think it may make sense to file a separate bug as an augment to JDK-8218227 (StringBuilder/StringBuffer constructor throws confusing NegativeArraySizeException)? Javadoc for at least four constructors (StringBuilder(CharSequence), StringBuilder(String), StringBuffer(CharSequence), StringBuffer(String)) and two methods(StringBuilder.ensureCapacity(), StringBuffer.ensureCapacity()) will need to be updated.
18-02-2019

Are there any other differences in the specs between analogous StringBuffer and StringBuilder constructors? From a quick scan, I didn't see any. I think it is fine if the spec doesn't explicitly cover how "hostile" CharSequences that return a negative length are handled. An implementation that treated them as having a length of zero might be friendlier than one that threw an exception if one was encountered (assuming there are cases now where such sequences can be processed non-exceptionally). Since Integer.MAX_VALUE isn't that big anymore, I think it is reasonable if the spec and implementation of classes like StringBuilder and spec and implemented to more gracefully handle operation near those values. With that in mind, spec like "The initial capacity of the string builder is 16 plus the length of the CharSequence argument." calls out for asking what happens if the CharSequence has a length greater than Integer.MAX_VALUE - 16. Moving back to Provisional.
15-02-2019

[~darcy] The javadoc StringBuilder does not have this issue. With respect to numeric overflow when the length of the argument is close to Integer.MAX_VALUE, I'm not certain we have to specify that the capacity will be limited up to Integer.MAX_VALUE. The way it was done with the fix for JDK-8218227 was just one possible approach to make the constructor throw OutOfMemoryError, so I think it is implementation details.
11-02-2019

Several comments: Presumably the same changes should be made to StringBuilder as well. Please include a diff of the changes to the spec text. Looking at the implementation in AbstractStringBuilder, care is taken to avoid overflows near Integer.MAX_VALUE in computing the capacity. I suggest updating the spec to require this behavior. In other words, augment: "The initial capacity of the string buffer is 16 plus the length of the string argument." with "If that sum would overflow, the capacity is Integer.MAX_VALUE." Should the spec be updated somewhere to say "if you pass in a hostile CharSequent, you might get exceptions." Moving to Provisional.
08-02-2019