-
Bug
-
Resolution: Fixed
-
P3
-
8, 9, 10
-
b01
-
x86_64
-
generic
FULL PRODUCT VERSION :
openjdk version "9.0.1"
OpenJDK Runtime Environment (build 9.0.1+11)
OpenJDK 64-Bit Server VM (build 9.0.1+11, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Ubuntu Linux 64-bit
A DESCRIPTION OF THE PROBLEM :
The ImageReader com.sun.imageio.plugins.png.PNGImageReader throws a NegativeArraySizeException when attempting to read malformed PNG image files that contain tEXt sections containing keywords that are larger than the length of the tEXt chunk.
The PNG specification defines a tEXt chunk as follows: Upto 80 bytes of a null-terminated "keyword" followed by a textual section of length N: the total length of the chunk, say chunkLength, should be N + keyword.length() + 1. Therefore, the textual section contains N = chunkLength - keyword.length() - 1 bytes, and N must be greater or equal to zero.
However, when keyword.length() >= chunkLength, the PngImageReader calculates N to be a negative value and attempts to allocate a negative-sized array for the textual section, resulting in a NegativeArraySizeException to be thrown in parse_tEXt_chunk(). Instead, an IOException should be thrown as the PNG input is malformed if a null byte is not found within tEXt chunk length.
A suggested fix is to replace this line in PngImageReader#parse_tEXt_chunk():
byte[] b = new byte[chunkLength - keyword.length() - 1];
with:
int n = chunkLength - keyword.length() - 1;
if (n < 0 || keyword.length() == 80) {
throw new IIOException("tEXt chunk length is smaller than keyword size");
}
byte[] b = new byte[n];
The second condition is required because reading in the keyword with `readNullTerminatedString("ISO-8859-1", 80)` does not guarantee that a null byte has been read; the chunk is still malformed if 80 non-null bytes are read in the beginning of the chunk.
This bug was found using AFL.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the test program attached below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An IOException should be thrown (e.g. javax.imagio.IIOException).
ACTUAL -
A java.lang.NegativeArraySizeException is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NegativeArraySizeException
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.parse_tEXt_chunk(PNGImageReader.java:555)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readMetadata(PNGImageReader.java:757)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1263)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1627)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1363)
at PngReaderTextChunkSizeIssue.main(PngReaderTextChunkSizeIssue.java:21)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import javax.imageio.ImageIO;
public class PngReaderTextChunkSizeIssue {
// PNG image test case (encoded as base64)
private static String inputImageBase64 = "iVBORw0KGgoAAAANSUhEUgAAACA" +
"AAAAgCAMAAABEpIrGAAAAGXRFWHRTb2Z0d2FyZWVBZG9iZSBJbWFnZVJlYWR59oLevgA" +
"AAA9QTFRFZszM////AAAAM5lmmf/MPkyvFQAAAGFJREFUeNrckzEOwCAMA5OY/7+5NBQ" +
"J1DphYaA3sPgkCwtEE0TVAm7BCkfMBaHgp4JvFwjPulSoITAabwHwk1a0PBB6TSBM+bc" +
"w5ERIlkQiTEPuqTj2ydWbUWzl8yZcAgwA0mYDNbDXy5oAAAAASUVORK5CYII=";
public static void main(String[] args) throws java.io.IOException {
// Convert test case into input stream
byte[] inputBytes = Base64.getDecoder().decode(inputImageBase64);
InputStream in = new ByteArrayInputStream(inputBytes);
// Attempt to read PNG
ImageIO.read(in); // Throws java.lang.NegativeArraySizeException!
}
}
---------- END SOURCE ----------
openjdk version "9.0.1"
OpenJDK Runtime Environment (build 9.0.1+11)
OpenJDK 64-Bit Server VM (build 9.0.1+11, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Ubuntu Linux 64-bit
A DESCRIPTION OF THE PROBLEM :
The ImageReader com.sun.imageio.plugins.png.PNGImageReader throws a NegativeArraySizeException when attempting to read malformed PNG image files that contain tEXt sections containing keywords that are larger than the length of the tEXt chunk.
The PNG specification defines a tEXt chunk as follows: Upto 80 bytes of a null-terminated "keyword" followed by a textual section of length N: the total length of the chunk, say chunkLength, should be N + keyword.length() + 1. Therefore, the textual section contains N = chunkLength - keyword.length() - 1 bytes, and N must be greater or equal to zero.
However, when keyword.length() >= chunkLength, the PngImageReader calculates N to be a negative value and attempts to allocate a negative-sized array for the textual section, resulting in a NegativeArraySizeException to be thrown in parse_tEXt_chunk(). Instead, an IOException should be thrown as the PNG input is malformed if a null byte is not found within tEXt chunk length.
A suggested fix is to replace this line in PngImageReader#parse_tEXt_chunk():
byte[] b = new byte[chunkLength - keyword.length() - 1];
with:
int n = chunkLength - keyword.length() - 1;
if (n < 0 || keyword.length() == 80) {
throw new IIOException("tEXt chunk length is smaller than keyword size");
}
byte[] b = new byte[n];
The second condition is required because reading in the keyword with `readNullTerminatedString("ISO-8859-1", 80)` does not guarantee that a null byte has been read; the chunk is still malformed if 80 non-null bytes are read in the beginning of the chunk.
This bug was found using AFL.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the test program attached below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An IOException should be thrown (e.g. javax.imagio.IIOException).
ACTUAL -
A java.lang.NegativeArraySizeException is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NegativeArraySizeException
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.parse_tEXt_chunk(PNGImageReader.java:555)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readMetadata(PNGImageReader.java:757)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1263)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1627)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1363)
at PngReaderTextChunkSizeIssue.main(PngReaderTextChunkSizeIssue.java:21)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import javax.imageio.ImageIO;
public class PngReaderTextChunkSizeIssue {
// PNG image test case (encoded as base64)
private static String inputImageBase64 = "iVBORw0KGgoAAAANSUhEUgAAACA" +
"AAAAgCAMAAABEpIrGAAAAGXRFWHRTb2Z0d2FyZWVBZG9iZSBJbWFnZVJlYWR59oLevgA" +
"AAA9QTFRFZszM////AAAAM5lmmf/MPkyvFQAAAGFJREFUeNrckzEOwCAMA5OY/7+5NBQ" +
"J1DphYaA3sPgkCwtEE0TVAm7BCkfMBaHgp4JvFwjPulSoITAabwHwk1a0PBB6TSBM+bc" +
"w5ERIlkQiTEPuqTj2ydWbUWzl8yZcAgwA0mYDNbDXy5oAAAAASUVORK5CYII=";
public static void main(String[] args) throws java.io.IOException {
// Convert test case into input stream
byte[] inputBytes = Base64.getDecoder().decode(inputImageBase64);
InputStream in = new ByteArrayInputStream(inputBytes);
// Attempt to read PNG
ImageIO.read(in); // Throws java.lang.NegativeArraySizeException!
}
}
---------- END SOURCE ----------
- duplicates
-
JDK-8191076 PngReader: NegativeArraySizeException in parse_zTXt_chunk when keyword length exceeds chunk size
-
- Closed
-
-
JDK-8191109 PngReader: NegativeArraySizeException in parse_iCCP_chunk when keyword length exceeds chunk size
-
- Closed
-
- relates to
-
JDK-8212116 IIOException "tEXt chunk length is not proper" on opening png file
-
- Resolved
-