JDK-8219196 : DataOutputStream.writeUTF may throw unexpected exceptions
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 8,11,12,13
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2019-02-17
  • Updated: 2024-04-06
  • Resolved: 2019-03-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13
13 b14Fixed
Related Reports
CSR :  
Duplicate :  
Relates :  
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
For very long strings of length greater than Integer.MAX_VALUE / 3 DataOutputStream.writeUTF might not behave as expected, if the byte length of the UTF encoding exceeds Integer.MAX_VALUE. In this case the internal variable "utflen" overflows and becomes negative such that this case is not caught by the if case (utflen > 65535). As a result the method might end up in an ArrayIndexOutOfBoundsException or a NegativeArraySizeException. However, the expected exception in this case would be an UTFDataFormatException.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The issue can be reproduced using the two attached unit tests.


---------- BEGIN SOURCE ----------
@Test
public void testArrayIndexOutOfBoundsException() throws IOException {
	int size = Integer.MAX_VALUE / 3 + 1;
	StringBuilder sb = new StringBuilder(size);
	char c = 0x0800; // this character gives 3 bytes when encoded using UTF-8
	for (int i = 0; i < size; ++i) {
		sb.append(c);
	}
	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	DataOutputStream dos = new DataOutputStream(bos);
	String s = sb.toString();
	dos.writeUTF(s); //throws ArrayIndexOutOfBoundsException instead of expected UTFDataFormatException
}

@Test
public void testNegativeArraySizeException() throws IOException {
	int size = Integer.MAX_VALUE / 2 + 1;
	StringBuilder sb = new StringBuilder(size);
	char c = 0x0800; // this character gives 3 bytes when encoded using UTF-8
	for (int i = 0; i < size; ++i) {
		sb.append(c);
	}
	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	DataOutputStream dos = new DataOutputStream(bos);
	String s = sb.toString();
	dos.writeUTF(s); //throws NegativeArraySizeException instead of expected UTFDataFormatException
}
---------- END SOURCE ----------


Comments
URL: http://hg.openjdk.java.net/jdk/jdk/rev/c4c225b49c5f User: bpb Date: 2019-03-27 14:22:08 +0000
27-03-2019

To reproduce the issue, run the attached test case. With JDK 8u201, I had to run with max heap size option -Xmx4G to avoid OutofMemoryError. For JDK 11, 12 and 13 , reproducible without this option. JDK 8u201 - Fail JDK 11.0.2 - Fail JDK 12-ea + 30 - Fail JDK 13-ea + 6 - Fail Output: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4 at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:395) at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:323) at JI9059415.main(JI9059415.java:17) Exception in thread "main" java.lang.OutOfMemoryError: UTF16 String size is 1073741824, should be less than 1073741823 at java.base/java.lang.StringUTF16.newBytesFor(StringUTF16.java:49) at java.base/java.lang.AbstractStringBuilder.inflate(AbstractStringBuilder.java:228) at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:753) at java.base/java.lang.StringBuilder.append(StringBuilder.java:241) at JI9059415.main(JI9059415.java:23)
18-02-2019