Backport to fix iTXt chunk handling for pngs
Deepak Bhole
dbhole at redhat.com
Thu Dec 23 14:30:07 PST 2010
* Deepak Bhole <dbhole at redhat.com> [2010-12-23 17:21]:
> * Deepak Bhole <dbhole at redhat.com> [2010-12-23 15:41]:
> > Given that both have been in 7 for over 2 years, I'd like to propose
> > that this also be applied to 1.7, 1.8 and 1.9.
> >
>
> Just noticed that the original email has an incorrect copyright header.
> New patch with correct header attached.
>
> Also, please see Joe's note here:
> http://mail.openjdk.java.net/pipermail/jdk6-dev/2010-December/002185.html
>
> Should we follow suit for IcedTea and backport 6782079 too? There are no
> bugs open for it atm (that I know of), but it'd certainly be a nice fix
> to have.
>
New patch attached for real this time!
Sorry for the double spam :/
Deepak
-------------- next part --------------
diff -r 7219bd74962a Makefile.am
--- a/Makefile.am Thu Dec 23 14:56:09 2010 +0100
+++ b/Makefile.am Thu Dec 23 17:14:05 2010 -0500
@@ -312,8 +312,10 @@
patches/openjdk/6979979-gtk_font_size_rounding.patch \
patches/openjdk/6795356-proxylazyvalue-leak.patch \
patches/rendering-engine-tests.patch \
- patches/jtreg-TestXEmbedServer-fix.patch
- patches/openjdk/6800846-printing-quality.patch
+ patches/jtreg-TestXEmbedServer-fix.patch \
+ patches/openjdk/6800846-printing-quality.patch \
+ patches/openjdk/6687968-pngimagereader_mem_leak.patch \
+ patches/openjdk/6541476-png-iTXt-chunk.patch
if WITH_ALT_HSBUILD
ICEDTEA_PATCHES += \
diff -r 7219bd74962a NEWS
--- a/NEWS Thu Dec 23 14:56:09 2010 +0100
+++ b/NEWS Thu Dec 23 17:14:05 2010 -0500
@@ -51,6 +51,8 @@
- S6979979, RH508185: Rounding error in font sizes selected by the GTK Look and Feel
- S6795356: Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc
- S6800846, RH662230: Printing quality degraded with Java 6 compared to 5.0, index out of bounds exception.
+ - S6687968: PNGImageReader leaks native memory through an Inflater
+ - S6541476, RH665355: PNG imageio plugin incorrectly handles iTXt chunk
* Bug fixes
- S7003777, RH647674: JTextPane produces incorrect content after parsing the html text
diff -r 7219bd74962a patches/openjdk/6541476-png-iTXt-chunk.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/openjdk/6541476-png-iTXt-chunk.patch Thu Dec 23 17:14:05 2010 -0500
@@ -0,0 +1,549 @@
+diff -urN openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java 2010-12-23 17:11:16.193446425 -0500
++++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java 2010-12-23 17:11:29.399447037 -0500
+@@ -44,7 +44,6 @@
+ import java.util.Arrays;
+ import java.util.Enumeration;
+ import java.util.Iterator;
+-import java.util.List;
+ import java.util.zip.Inflater;
+ import java.util.zip.InflaterInputStream;
+ import javax.imageio.IIOException;
+@@ -57,6 +56,7 @@
+ import com.sun.imageio.plugins.common.InputStreamAdapter;
+ import com.sun.imageio.plugins.common.ReaderUtil;
+ import com.sun.imageio.plugins.common.SubImageInputStream;
++import java.io.ByteArrayOutputStream;
+ import sun.awt.image.ByteInterleavedRaster;
+
+ class PNGImageDataEnumeration implements Enumeration {
+@@ -209,6 +209,15 @@
+ resetStreamSettings();
+ }
+
++ private String readNullTerminatedString(String charset) throws IOException {
++ ByteArrayOutputStream baos = new ByteArrayOutputStream();
++ int b;
++ while ((b = stream.read()) != 0) {
++ baos.write(b);
++ }
++ return new String(baos.toByteArray(), charset);
++ }
++
+ private String readNullTerminatedString() throws IOException {
+ StringBuilder b = new StringBuilder();
+ int c;
+@@ -447,26 +456,27 @@
+ metadata.iTXt_keyword.add(keyword);
+
+ int compressionFlag = stream.readUnsignedByte();
+- metadata.iTXt_compressionFlag.add(new Integer(compressionFlag));
++ metadata.iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag == 1));
+
+ int compressionMethod = stream.readUnsignedByte();
+- metadata.iTXt_compressionMethod.add(new Integer(compressionMethod));
++ metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
+
+- String languageTag = readNullTerminatedString();
++ String languageTag = readNullTerminatedString("UTF8");
+ metadata.iTXt_languageTag.add(languageTag);
+
+- String translatedKeyword = stream.readUTF();
++ String translatedKeyword =
++ readNullTerminatedString("UTF8");
+ metadata.iTXt_translatedKeyword.add(translatedKeyword);
+- stream.skipBytes(1); // Null separator
+
+ String text;
++ long pos = stream.getStreamPosition();
++ byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
++ stream.readFully(b);
++
+ if (compressionFlag == 1) { // Decompress the text
+- long pos = stream.getStreamPosition();
+- byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
+- stream.readFully(b);
+- text = inflate(b);
++ text = new String(inflate(b), "UTF8");
+ } else {
+- text = stream.readUTF();
++ text = new String(b, "UTF8");
+ }
+ metadata.iTXt_text.add(text);
+ }
+@@ -615,20 +625,20 @@
+ metadata.tRNS_present = true;
+ }
+
+- private static String inflate(byte[] b) throws IOException {
++ private static byte[] inflate(byte[] b) throws IOException {
+ InputStream bais = new ByteArrayInputStream(b);
+ InputStream iis = new InflaterInputStream(bais);
++ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+- StringBuilder sb = new StringBuilder(80);
+ int c;
+ try {
+ while ((c = iis.read()) != -1) {
+- sb.append((char)c);
++ baos.write(c);
+ }
+ } finally {
+ iis.close();
+ }
+- return sb.toString();
++ return baos.toByteArray();
+ }
+
+ private void parse_zTXt_chunk(int chunkLength) throws IOException {
+@@ -640,7 +650,7 @@
+
+ byte[] b = new byte[chunkLength - keyword.length() - 2];
+ stream.readFully(b);
+- metadata.zTXt_text.add(inflate(b));
++ metadata.zTXt_text.add(new String(inflate(b)));
+ }
+
+ private void readMetadata() throws IIOException {
+diff -urN openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java 2010-12-23 17:11:16.193446425 -0500
++++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java 2010-12-23 17:11:29.400446993 -0500
+@@ -671,13 +671,13 @@
+ }
+ }
+
+- private byte[] deflate(String s) throws IOException {
++ private byte[] deflate(byte[] b) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DeflaterOutputStream dos = new DeflaterOutputStream(baos);
+
+- int len = s.length();
++ int len = b.length;
+ for (int i = 0; i < len; i++) {
+- dos.write((int)s.charAt(i));
++ dos.write((int)(0xff & b[i]));
+ }
+ dos.close();
+
+@@ -685,38 +685,37 @@
+ }
+
+ private void write_iTXt() throws IOException {
+- Iterator keywordIter = metadata.iTXt_keyword.iterator();
+- Iterator flagIter = metadata.iTXt_compressionFlag.iterator();
+- Iterator methodIter = metadata.iTXt_compressionMethod.iterator();
+- Iterator languageIter = metadata.iTXt_languageTag.iterator();
+- Iterator translatedKeywordIter =
++ Iterator<String> keywordIter = metadata.iTXt_keyword.iterator();
++ Iterator<Boolean> flagIter = metadata.iTXt_compressionFlag.iterator();
++ Iterator<Integer> methodIter = metadata.iTXt_compressionMethod.iterator();
++ Iterator<String> languageIter = metadata.iTXt_languageTag.iterator();
++ Iterator<String> translatedKeywordIter =
+ metadata.iTXt_translatedKeyword.iterator();
+- Iterator textIter = metadata.iTXt_text.iterator();
++ Iterator<String> textIter = metadata.iTXt_text.iterator();
+
+ while (keywordIter.hasNext()) {
+ ChunkStream cs = new ChunkStream(PNGImageReader.iTXt_TYPE, stream);
+- String keyword = (String)keywordIter.next();
+- cs.writeBytes(keyword);
++
++ cs.writeBytes(keywordIter.next());
+ cs.writeByte(0);
+
+- int flag = ((Integer)flagIter.next()).intValue();
+- cs.writeByte(flag);
+- int method = ((Integer)methodIter.next()).intValue();
+- cs.writeByte(method);
++ Boolean compressed = flagIter.next();
++ cs.writeByte(compressed ? 1 : 0);
+
+- String languageTag = (String)languageIter.next();
+- cs.writeBytes(languageTag);
++ cs.writeByte(methodIter.next().intValue());
++
++ cs.writeBytes(languageIter.next());
+ cs.writeByte(0);
+
+- String translatedKeyword = (String)translatedKeywordIter.next();
+- cs.writeBytes(translatedKeyword);
++
++ cs.write(translatedKeywordIter.next().getBytes("UTF8"));
+ cs.writeByte(0);
+
+- String text = (String)textIter.next();
+- if (flag == 1) {
+- cs.write(deflate(text));
++ String text = textIter.next();
++ if (compressed) {
++ cs.write(deflate(text.getBytes("UTF8")));
+ } else {
+- cs.writeUTF(text);
++ cs.write(text.getBytes("UTF8"));
+ }
+ cs.finish();
+ }
+@@ -737,7 +736,7 @@
+ cs.writeByte(compressionMethod);
+
+ String text = (String)textIter.next();
+- cs.write(deflate(text));
++ cs.write(deflate(text.getBytes()));
+ cs.finish();
+ }
+ }
+diff -urN openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java 2010-06-21 17:15:11.000000000 -0400
++++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java 2010-12-23 17:11:29.401446953 -0500
+@@ -176,12 +176,12 @@
+ public byte[] iCCP_compressedProfile;
+
+ // iTXt chunk
+- public ArrayList iTXt_keyword = new ArrayList(); // Strings
+- public ArrayList iTXt_compressionFlag = new ArrayList(); // Integers
+- public ArrayList iTXt_compressionMethod = new ArrayList(); // Integers
+- public ArrayList iTXt_languageTag = new ArrayList(); // Strings
+- public ArrayList iTXt_translatedKeyword = new ArrayList(); // Strings
+- public ArrayList iTXt_text = new ArrayList(); // Strings
++ public ArrayList<String> iTXt_keyword = new ArrayList<String>();
++ public ArrayList<Boolean> iTXt_compressionFlag = new ArrayList<Boolean>();
++ public ArrayList<Integer> iTXt_compressionMethod = new ArrayList<Integer>();
++ public ArrayList<String> iTXt_languageTag = new ArrayList<String>();
++ public ArrayList<String> iTXt_translatedKeyword = new ArrayList<String>();
++ public ArrayList<String> iTXt_text = new ArrayList<String>();
+
+ // pHYs chunk
+ public boolean pHYs_present;
+@@ -599,19 +599,17 @@
+ if (iTXt_keyword.size() > 0) {
+ IIOMetadataNode iTXt_parent = new IIOMetadataNode("iTXt");
+ for (int i = 0; i < iTXt_keyword.size(); i++) {
+- Integer val;
+-
+ IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
+- iTXt_node.setAttribute("keyword", (String)iTXt_keyword.get(i));
+- val = (Integer)iTXt_compressionFlag.get(i);
+- iTXt_node.setAttribute("compressionFlag", val.toString());
+- val = (Integer)iTXt_compressionMethod.get(i);
+- iTXt_node.setAttribute("compressionMethod", val.toString());
++ iTXt_node.setAttribute("keyword", iTXt_keyword.get(i));
++ iTXt_node.setAttribute("compressionFlag",
++ iTXt_compressionFlag.get(i) ? "1" : "0");
++ iTXt_node.setAttribute("compressionMethod",
++ iTXt_compressionMethod.get(i).toString());
+ iTXt_node.setAttribute("languageTag",
+- (String)iTXt_languageTag.get(i));
++ iTXt_languageTag.get(i));
+ iTXt_node.setAttribute("translatedKeyword",
+- (String)iTXt_translatedKeyword.get(i));
+- iTXt_node.setAttribute("text", (String)iTXt_text.get(i));
++ iTXt_translatedKeyword.get(i));
++ iTXt_node.setAttribute("text", iTXt_text.get(i));
+
+ iTXt_parent.appendChild(iTXt_node);
+ }
+@@ -1039,11 +1037,11 @@
+
+ for (int i = 0; i < iTXt_keyword.size(); i++) {
+ node = new IIOMetadataNode("TextEntry");
+- node.setAttribute("keyword", (String)iTXt_keyword.get(i));
+- node.setAttribute("value", (String)iTXt_text.get(i));
++ node.setAttribute("keyword", iTXt_keyword.get(i));
++ node.setAttribute("value", iTXt_text.get(i));
+ node.setAttribute("language",
+- (String)iTXt_languageTag.get(i));
+- if (((Integer)iTXt_compressionFlag.get(i)).intValue() == 1) {
++ iTXt_languageTag.get(i));
++ if (iTXt_compressionFlag.get(i)) {
+ node.setAttribute("compression", "deflate");
+ } else {
+ node.setAttribute("compression", "none");
+@@ -1429,11 +1427,11 @@
+
+ boolean compressionFlag =
+ getBooleanAttribute(iTXt_node, "compressionFlag");
+- iTXt_compressionFlag.add(new Boolean(compressionFlag));
++ iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
+
+ String compressionMethod =
+ getAttribute(iTXt_node, "compressionMethod");
+- iTXt_compressionMethod.add(compressionMethod);
++ iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
+
+ String languageTag =
+ getAttribute(iTXt_node, "languageTag");
+@@ -1952,13 +1950,10 @@
+ tEXt_text.add(value);
+ }
+ } else {
+- int flag = compression.equals("zip") ?
+- 1 : 0;
+-
+ // Use an iTXt node
+ iTXt_keyword.add(keyword);
+- iTXt_compressionFlag.add(new Integer(flag));
+- iTXt_compressionMethod.add(new Integer(0));
++ iTXt_compressionFlag.add(Boolean.valueOf(compression.equals("zip")));
++ iTXt_compressionMethod.add(Integer.valueOf(0));
+ iTXt_languageTag.add(language);
+ iTXt_translatedKeyword.add(keyword); // fake it
+ iTXt_text.add(value);
+@@ -1995,12 +1990,12 @@
+ gAMA_present = false;
+ hIST_present = false;
+ iCCP_present = false;
+- iTXt_keyword = new ArrayList();
+- iTXt_compressionFlag = new ArrayList();
+- iTXt_compressionMethod = new ArrayList();
+- iTXt_languageTag = new ArrayList();
+- iTXt_translatedKeyword = new ArrayList();
+- iTXt_text = new ArrayList();
++ iTXt_keyword = new ArrayList<String>();
++ iTXt_compressionFlag = new ArrayList<Boolean>();
++ iTXt_compressionMethod = new ArrayList<Integer>();
++ iTXt_languageTag = new ArrayList<String>();
++ iTXt_translatedKeyword = new ArrayList<String>();
++ iTXt_text = new ArrayList<String>();
+ pHYs_present = false;
+ sBIT_present = false;
+ sPLT_present = false;
+diff -urN openjdk.orig/jdk/test/javax/imageio/plugins/png/ITXtTest.java openjdk/jdk/test/javax/imageio/plugins/png/ITXtTest.java
+--- openjdk.orig/jdk/test/javax/imageio/plugins/png/ITXtTest.java 1969-12-31 19:00:00.000000000 -0500
++++ openjdk/jdk/test/javax/imageio/plugins/png/ITXtTest.java 2010-12-23 17:12:58.538446639 -0500
+@@ -0,0 +1,236 @@
++/*
++ * Copyright (c) 2008, 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 6541476
++ * @summary Test verifies that ImageIO PNG plugin correcly handles the
++ * iTxt chunk (International textual data).
++ *
++ * @run main ITXtTest
++ */
++
++
++import java.awt.Color;
++import java.awt.Graphics2D;
++import java.awt.image.BufferedImage;
++import java.io.File;
++
++import javax.imageio.ImageIO;
++import javax.imageio.ImageReader;
++import javax.imageio.IIOImage;
++import javax.imageio.ImageTypeSpecifier;
++import javax.imageio.ImageWriter;
++import javax.imageio.metadata.IIOMetadata;
++import javax.imageio.metadata.IIOMetadataNode;
++import javax.imageio.stream.ImageOutputStream;
++import javax.imageio.stream.ImageInputStream;
++
++import org.w3c.dom.Node;
++
++public class ITXtTest {
++ static public void main(String args[]) {
++ ITXtTest t_en = new ITXtTest();
++ t_en.description = "xml - en";
++ t_en.keyword = "XML:com.adobe.xmp";
++ t_en.isCompressed = false;
++ t_en.compression = 0;
++ t_en.language = "en";
++ t_en.trasKeyword = "XML:com.adobe.xmp";
++ t_en.text = "<xml>Something</xml>";
++
++ doTest(t_en);
++
++ // check compression case
++ t_en.isCompressed = true;
++ t_en.description = "xml - en - compressed";
++
++ doTest(t_en);
++
++ ITXtTest t_ru = new ITXtTest();
++ t_ru.description = "xml - ru";
++ t_ru.keyword = "XML:com.adobe.xmp";
++ t_ru.isCompressed = false;
++ t_ru.compression = 0;
++ t_ru.language = "ru";
++ t_ru.trasKeyword = "\u0410\u0410\u0410\u0410\u0410 XML";
++ t_ru.text = "<xml>\u042A\u042F\u042F\u042F\u042F\u042F\u042F</xml>";
++
++ doTest(t_ru);
++
++ t_ru.isCompressed = true;
++ t_ru.description = "xml - ru - compressed";
++
++ doTest(t_ru);
++ }
++
++
++ String description;
++
++ String keyword;
++ boolean isCompressed;
++ int compression;
++ String language;
++ String trasKeyword;
++ String text;
++
++
++ public IIOMetadataNode getNode() {
++ IIOMetadataNode iTXt = new IIOMetadataNode("iTXt");
++ IIOMetadataNode iTXtEntry = new IIOMetadataNode("iTXtEntry");
++ iTXtEntry.setAttribute("keyword", keyword);
++ iTXtEntry.setAttribute("compressionFlag",
++ isCompressed ? "true" : "false");
++ iTXtEntry.setAttribute("compressionMethod",
++ Integer.toString(compression));
++ iTXtEntry.setAttribute("languageTag", language);
++ iTXtEntry.setAttribute("translatedKeyword",
++ trasKeyword);
++ iTXtEntry.setAttribute("text", text);
++ iTXt.appendChild(iTXtEntry);
++ return iTXt;
++ }
++
++ public static ITXtTest getFromNode(IIOMetadataNode n) {
++ ITXtTest t = new ITXtTest();
++
++ if (!"iTXt".equals(n.getNodeName())) {
++ throw new RuntimeException("Invalid node");
++ }
++ IIOMetadataNode e = (IIOMetadataNode)n.getFirstChild();
++ if (!"iTXtEntry".equals(e.getNodeName())) {
++ throw new RuntimeException("Invalid entry node");
++ }
++ t.keyword = e.getAttribute("keyword");
++ t.isCompressed =
++ (Integer.valueOf(e.getAttribute("compressionFlag")).intValue() == 1);
++ t.compression =
++ Integer.valueOf(e.getAttribute("compressionMethod")).intValue();
++ t.language = e.getAttribute("languageTag");
++ t.trasKeyword = e.getAttribute("translatedKeyword");
++ t.text = e.getAttribute("text");
++
++ return t;
++ }
++
++ @Override
++ public boolean equals(Object o) {
++ if (! (o instanceof ITXtTest)) {
++ return false;
++ }
++ ITXtTest t = (ITXtTest)o;
++ if (!keyword.equals(t.keyword)) { return false; }
++ if (isCompressed != t.isCompressed) { return false; }
++ if (compression != t.compression) { return false; }
++ if (!language.equals(t.language)) { return false; }
++ if (!trasKeyword.equals(t.trasKeyword)) { return false; }
++ if (!text.equals(t.text)) { return false; }
++
++ return true;
++ }
++
++
++
++ private static void doTest(ITXtTest src) {
++
++ System.out.println("Test: " + src.description);
++
++ File file = new File("test.png");
++
++ writeTo(file, src);
++ ITXtTest dst = readFrom(file);
++
++ if (dst == null || !dst.equals(src)) {
++ throw new RuntimeException("Test failed.");
++ }
++
++ System.out.println("Test passed.");
++ }
++
++ private static void writeTo(File f, ITXtTest t) {
++ BufferedImage src = createBufferedImage();
++ try {
++ ImageOutputStream imageOutputStream =
++ ImageIO.createImageOutputStream(f);
++
++ ImageTypeSpecifier imageTypeSpecifier =
++ new ImageTypeSpecifier(src);
++ ImageWriter imageWriter =
++ ImageIO.getImageWritersByFormatName("PNG").next();
++
++ imageWriter.setOutput(imageOutputStream);
++
++ IIOMetadata m =
++ imageWriter.getDefaultImageMetadata(imageTypeSpecifier, null);
++
++ String format = m.getNativeMetadataFormatName();
++ Node root = m.getAsTree(format);
++
++ IIOMetadataNode iTXt = t.getNode();
++ root.appendChild(iTXt);
++ m.setFromTree(format, root);
++
++ imageWriter.write(new IIOImage(src, null, m));
++ imageOutputStream.close();
++ System.out.println("Writing done.");
++ } catch (Throwable e) {
++ throw new RuntimeException("Writing test failed.", e);
++ }
++ }
++
++ private static ITXtTest readFrom(File f) {
++ try {
++ ImageInputStream iis = ImageIO.createImageInputStream(f);
++ ImageReader r = ImageIO.getImageReaders(iis).next();
++ r.setInput(iis);
++
++ IIOImage dst = r.readAll(0, null);
++
++ // look for iTXt node
++ IIOMetadata m = dst.getMetadata();
++ Node root = m.getAsTree(m.getNativeMetadataFormatName());
++ Node n = root.getFirstChild();
++ while (n != null && !"iTXt".equals(n.getNodeName())) {
++ n = n.getNextSibling();
++ }
++ if (n == null) {
++ throw new RuntimeException("No iTXt node!");
++ }
++ ITXtTest t = ITXtTest.getFromNode((IIOMetadataNode)n);
++ return t;
++ } catch (Throwable e) {
++ throw new RuntimeException("Reading test failed.", e);
++ }
++ }
++
++ private static BufferedImage createBufferedImage() {
++ BufferedImage image = new BufferedImage(128, 128,
++ BufferedImage.TYPE_4BYTE_ABGR_PRE);
++ Graphics2D graph = image.createGraphics();
++ graph.setPaintMode();
++ graph.setColor(Color.orange);
++ graph.fillRect(32, 32, 64, 64);
++ graph.dispose();
++ return image;
++ }
++}
diff -r 7219bd74962a patches/openjdk/6687968-pngimagereader_mem_leak.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/openjdk/6687968-pngimagereader_mem_leak.patch Thu Dec 23 17:14:05 2010 -0500
@@ -0,0 +1,126 @@
+diff -urN openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java 2010-06-21 17:15:11.000000000 -0400
++++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java 2010-12-23 15:12:24.471446202 -0500
+@@ -618,10 +618,15 @@
+ private static String inflate(byte[] b) throws IOException {
+ InputStream bais = new ByteArrayInputStream(b);
+ InputStream iis = new InflaterInputStream(bais);
++
+ StringBuilder sb = new StringBuilder(80);
+ int c;
+- while ((c = iis.read()) != -1) {
+- sb.append((char)c);
++ try {
++ while ((c = iis.read()) != -1) {
++ sb.append((char)c);
++ }
++ } finally {
++ iis.close();
+ }
+ return sb.toString();
+ }
+@@ -1246,13 +1251,26 @@
+ destinationBands = param.getDestinationBands();
+ destinationOffset = param.getDestinationOffset();
+ }
+-
++ Inflater inf = null;
+ try {
+ stream.seek(imageStartPosition);
+
+ Enumeration e = new PNGImageDataEnumeration(stream);
+ InputStream is = new SequenceInputStream(e);
+- is = new InflaterInputStream(is, new Inflater());
++
++ /* InflaterInputStream uses an Inflater instance which consumes
++ * native (non-GC visible) resources. This is normally implicitly
++ * freed when the stream is closed. However since the
++ * InflaterInputStream wraps a client-supplied input stream,
++ * we cannot close it.
++ * But the app may depend on GC finalization to close the stream.
++ * Therefore to ensure timely freeing of native resources we
++ * explicitly create the Inflater instance and free its resources
++ * when we are done with the InflaterInputStream by calling
++ * inf.end();
++ */
++ inf = new Inflater();
++ is = new InflaterInputStream(is, inf);
+ is = new BufferedInputStream(is);
+ this.pixelStream = new DataInputStream(is);
+
+@@ -1285,6 +1303,10 @@
+ }
+ } catch (IOException e) {
+ throw new IIOException("Error reading PNG image data", e);
++ } finally {
++ if (inf != null) {
++ inf.end();
++ }
+ }
+ }
+
+diff -urN openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java 2010-06-21 17:15:11.000000000 -0400
++++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java 2010-12-23 15:12:24.472446225 -0500
+@@ -244,13 +244,17 @@
+ }
+
+ public void finish() throws IOException {
+- if (!def.finished()) {
+- def.finish();
+- while (!def.finished()) {
+- deflate();
++ try {
++ if (!def.finished()) {
++ def.finish();
++ while (!def.finished()) {
++ deflate();
++ }
+ }
++ finishChunk();
++ } finally {
++ def.end();
+ }
+- finishChunk();
+ }
+
+ protected void finalize() throws Throwable {
+@@ -928,23 +932,24 @@
+ // Use sourceXOffset, etc.
+ private void write_IDAT(RenderedImage image) throws IOException {
+ IDATOutputStream ios = new IDATOutputStream(stream, 32768);
+-
+- if (metadata.IHDR_interlaceMethod == 1) {
+- for (int i = 0; i < 7; i++) {
+- encodePass(ios, image,
+- PNGImageReader.adam7XOffset[i],
+- PNGImageReader.adam7YOffset[i],
+- PNGImageReader.adam7XSubsampling[i],
+- PNGImageReader.adam7YSubsampling[i]);
+- if (abortRequested()) {
+- break;
++ try {
++ if (metadata.IHDR_interlaceMethod == 1) {
++ for (int i = 0; i < 7; i++) {
++ encodePass(ios, image,
++ PNGImageReader.adam7XOffset[i],
++ PNGImageReader.adam7YOffset[i],
++ PNGImageReader.adam7XSubsampling[i],
++ PNGImageReader.adam7YSubsampling[i]);
++ if (abortRequested()) {
++ break;
++ }
+ }
++ } else {
++ encodePass(ios, image, 0, 0, 1, 1);
+ }
+- } else {
+- encodePass(ios, image, 0, 0, 1, 1);
++ } finally {
++ ios.finish();
+ }
+-
+- ios.finish();
+ }
+
+ private void writeIEND() throws IOException {
More information about the distro-pkg-dev
mailing list