--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/spi/MarkTryFinallyReproducer.java Wed Dec 02 21:23:59 2015 +0000
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2015 Red Hat, Inc.
+ * 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 8144071
+ * @run main/othervm MarkTryFinallyReproducer
+ * @summary Test that call to canDecodeInput in ImageIO don't corrupt
+ * mark/reset stack in ImageInputStream
+ * @author Jiri Vanek
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.Locale;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.IIOByteBuffer;
+import javax.imageio.stream.ImageInputStream;
+
+
+public class MarkTryFinallyReproducer {
+
+ private static final byte[] bmp = new byte[]{
+ 127,127, 66, 77, -86, 0, 0, 0, 0, 0, 0, 0,
+ 122, 0, 0, 0, 108, 0, 0, 0, 4, 0, 0, 0, 4,
+ 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 48, 0, 0,
+ 0, 19, 11, 0, 0, 19, 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66, 71, 82, 115, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, -1, -1,
+ -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, 0, 0, -17,
+ 0, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, -1, -1, -1,
+ -1, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, -1
+ };
+ //first two are evil, we are skipping them later. Others are normal BMP
+
+ private static class NotClosingImageInputStream implements ImageInputStream {
+
+ private final ImageInputStream src;
+
+ private NotClosingImageInputStream(ImageInputStream createImageInputStream) {
+ this.src = createImageInputStream;
+ }
+
+ @Override
+ public void setByteOrder(ByteOrder byteOrder) {
+ src.setByteOrder(byteOrder);
+ }
+
+ @Override
+ public ByteOrder getByteOrder() {
+ return src.getByteOrder();
+ }
+
+ @Override
+ public int read() throws IOException {
+ return src.read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return src.read(b);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return src.read(b, off, len);
+ }
+
+ @Override
+ public void readBytes(IIOByteBuffer buf, int len) throws IOException {
+ src.readBytes(buf, len);
+ }
+
+ @Override
+ public boolean readBoolean() throws IOException {
+ return src.readBoolean();
+ }
+
+ @Override
+ public byte readByte() throws IOException {
+ return src.readByte();
+ }
+
+ @Override
+ public int readUnsignedByte() throws IOException {
+ return src.readUnsignedByte();
+ }
+
+ @Override
+ public short readShort() throws IOException {
+ return src.readShort();
+ }
+
+ @Override
+ public int readUnsignedShort() throws IOException {
+ return src.readUnsignedShort();
+ }
+
+ @Override
+ public char readChar() throws IOException {
+ return src.readChar();
+ }
+
+ @Override
+ public int readInt() throws IOException {
+ return src.readInt();
+ }
+
+ @Override
+ public long readUnsignedInt() throws IOException {
+ return src.readUnsignedInt();
+ }
+
+ @Override
+ public long readLong() throws IOException {
+ return src.readLong();
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return src.readFloat();
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ return src.readDouble();
+ }
+
+ @Override
+ public String readLine() throws IOException {
+ return src.readLine();
+ }
+
+ @Override
+ public String readUTF() throws IOException {
+ return src.readUTF();
+ }
+
+ @Override
+ public void readFully(byte[] b, int off, int len) throws IOException {
+ src.readFully(b, off, len);
+ }
+
+ @Override
+ public void readFully(byte[] b) throws IOException {
+ src.readFully(b);
+ }
+
+ @Override
+ public void readFully(short[] s, int off, int len) throws IOException {
+ src.readFully(s, off, len);
+ }
+
+ @Override
+ public void readFully(char[] c, int off, int len) throws IOException {
+ src.readFully(c, off, len);
+ }
+
+ @Override
+ public void readFully(int[] i, int off, int len) throws IOException {
+ src.readFully(i, off, len);
+ }
+
+ @Override
+ public void readFully(long[] l, int off, int len) throws IOException {
+ src.readFully(l, off, len);
+ }
+
+ @Override
+ public void readFully(float[] f, int off, int len) throws IOException {
+ src.readFully(f, off, len);
+ }
+
+ @Override
+ public void readFully(double[] d, int off, int len) throws IOException {
+ src.readFully(d, off, len);
+ }
+
+ @Override
+ public long getStreamPosition() throws IOException {
+ return src.getStreamPosition();
+ }
+
+ @Override
+ public int getBitOffset() throws IOException {
+ return src.getBitOffset();
+ }
+
+ @Override
+ public void setBitOffset(int bitOffset) throws IOException {
+ src.setBitOffset(bitOffset);
+ }
+
+ @Override
+ public int readBit() throws IOException {
+ return src.readBit();
+ }
+
+ @Override
+ public long readBits(int numBits) throws IOException {
+ return src.readBits(numBits);
+ }
+
+ @Override
+ public long length() throws IOException {
+ return src.length();
+ }
+
+ @Override
+ public int skipBytes(int n) throws IOException {
+ return src.skipBytes(n);
+ }
+
+ @Override
+ public long skipBytes(long n) throws IOException {
+ return src.skipBytes(n);
+ }
+
+ @Override
+ public void seek(long pos) throws IOException {
+ src.seek(pos);
+ }
+
+ @Override
+ public void mark() {
+ src.mark();
+ }
+
+ @Override
+ public void reset() throws IOException {
+ src.reset();
+ }
+
+ @Override
+ public void flushBefore(long pos) throws IOException {
+ src.flushBefore(pos);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ src.flush();
+ }
+
+ @Override
+ public long getFlushedPosition() {
+ return src.getFlushedPosition();
+ }
+
+ @Override
+ public boolean isCached() {
+ return src.isCached();
+ }
+
+ @Override
+ public boolean isCachedMemory() {
+ return src.isCachedMemory();
+ }
+
+ @Override
+ public boolean isCachedFile() {
+ return src.isCachedFile();
+ }
+
+ @Override
+ public void close() throws IOException {
+ //the only important one. nothing
+ }
+ }
+
+ static final String readerClassName
+ = MarkTryFinallyReproducerSpi.class.getName();
+ static final String[] localNames = {"myNames"};
+ static final String[] localSuffixes = {"mySuffixes"};
+ static final String[] localMIMETypes = {"myMimes"};
+
+ public static class MarkTryFinallyReproducerSpi extends ImageReaderSpi {
+
+ public MarkTryFinallyReproducerSpi() {
+ super("MarkTryFinallyReproducerSpi",
+ "1.0",
+ localNames,
+ localSuffixes,
+ localMIMETypes,
+ readerClassName,
+ new Class[]{ImageInputStream.class},
+ new String[0],
+ false,
+ null,
+ null,
+ new String[0],
+ new String[0],
+ false,
+ null,
+ null,
+ new String[0],
+ new String[0]);
+ }
+
+ @Override
+ public String getDescription(Locale locale) {
+ return "";
+ }
+
+ @Override
+ public boolean canDecodeInput(Object input) throws IOException {
+ throw new IOException("Bad luck");
+ }
+
+ @Override
+ public ImageReader createReaderInstance(Object extension) {
+ return null;
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ MarkTryFinallyReproducerSpi spi = new MarkTryFinallyReproducerSpi();
+ IIORegistry.getDefaultInstance().registerServiceProvider(spi);
+
+ ImageInputStream iis1 =
+ new NotClosingImageInputStream(ImageIO.createImageInputStream(new ByteArrayInputStream(bmp)));
+ iis1.readByte();
+ iis1.mark();
+ long p1 = iis1.getStreamPosition();
+ iis1.readByte();
+ iis1.mark();
+ long p2 = iis1.getStreamPosition();
+ BufferedImage bi1 = ImageIO.read(iis1);
+ iis1.reset();
+ long pn2 = iis1.getStreamPosition();
+ iis1.reset();
+ long pn1 = iis1.getStreamPosition();
+ if (p1 != pn1 || p2!= pn2) {
+ throw new RuntimeException("Exception from call to canDecodeInput in ImageIO. " +
+ "Corrupted stack in ImageInputStream");
+ }
+
+ }
+
+}