8287102: ImageReaderSpi.canDecodeInput() for standard plugins should return false if a stream is too short
Reviewed-by: prr
This commit is contained in:
parent
7a0c8b14aa
commit
a7e07fdbc1
src/java.desktop/share/classes/com/sun/imageio/plugins
bmp
common
gif
png
tiff
wbmp
test/jdk/javax/imageio/plugins
@ -28,11 +28,11 @@ package com.sun.imageio.plugins.bmp;
|
||||
import java.util.Locale;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.spi.IIORegistry;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.IIOException;
|
||||
import com.sun.imageio.plugins.common.ReaderUtil;
|
||||
|
||||
public class BMPImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
@ -81,10 +81,10 @@ public class BMPImageReaderSpi extends ImageReaderSpi {
|
||||
ImageInputStream stream = (ImageInputStream)source;
|
||||
byte[] b = new byte[2];
|
||||
stream.mark();
|
||||
stream.readFully(b);
|
||||
boolean full = ReaderUtil.tryReadFully(stream, b);
|
||||
stream.reset();
|
||||
|
||||
return (b[0] == 0x42) && (b[1] == 0x4d);
|
||||
return full && (b[0] == 0x42) && (b[1] == 0x4d);
|
||||
}
|
||||
|
||||
public ImageReader createReaderInstance(Object extension)
|
||||
|
@ -258,4 +258,28 @@ public class ReaderUtil {
|
||||
}
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to read {@code b.length} bytes from the stream,
|
||||
* and stores them into {@code b} starting at index 0.
|
||||
* If the end of the stream is reached, a {@code false}
|
||||
* will be returned.
|
||||
*
|
||||
* @param iis the stream to read.
|
||||
* @param b an array where to store the {@code byte}s.
|
||||
* @return {@code true} on success, or {@code false} on EOF.
|
||||
*/
|
||||
public static boolean tryReadFully(ImageInputStream iis, byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
int offset = 0;
|
||||
do {
|
||||
int n = iis.read(b, offset, b.length - offset);
|
||||
if (n < 0) {
|
||||
return false; // EOF
|
||||
}
|
||||
offset += n;
|
||||
} while (offset < b.length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,10 @@ package com.sun.imageio.plugins.gif;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Iterator;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.metadata.IIOMetadataFormat;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import com.sun.imageio.plugins.common.ReaderUtil;
|
||||
|
||||
public class GIFImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
@ -85,10 +83,11 @@ public class GIFImageReaderSpi extends ImageReaderSpi {
|
||||
ImageInputStream stream = (ImageInputStream)input;
|
||||
byte[] b = new byte[6];
|
||||
stream.mark();
|
||||
stream.readFully(b);
|
||||
boolean full = ReaderUtil.tryReadFully(stream, b);
|
||||
stream.reset();
|
||||
|
||||
return b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' &&
|
||||
return full &&
|
||||
b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' &&
|
||||
(b[4] == '7' || b[4] == '9') && b[5] == 'a';
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,10 @@ package com.sun.imageio.plugins.png;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Iterator;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.metadata.IIOMetadataFormat;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import com.sun.imageio.plugins.common.ReaderUtil;
|
||||
|
||||
public class PNGImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
@ -84,10 +82,11 @@ public class PNGImageReaderSpi extends ImageReaderSpi {
|
||||
ImageInputStream stream = (ImageInputStream)input;
|
||||
byte[] b = new byte[8];
|
||||
stream.mark();
|
||||
stream.readFully(b);
|
||||
boolean full = ReaderUtil.tryReadFully(stream, b);
|
||||
stream.reset();
|
||||
|
||||
return (b[0] == (byte)137 &&
|
||||
return full &&
|
||||
(b[0] == (byte)137 &&
|
||||
b[1] == (byte)80 &&
|
||||
b[2] == (byte)78 &&
|
||||
b[3] == (byte)71 &&
|
||||
|
@ -30,6 +30,7 @@ import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import com.sun.imageio.plugins.common.ReaderUtil;
|
||||
|
||||
public class TIFFImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
@ -67,10 +68,11 @@ public class TIFFImageReaderSpi extends ImageReaderSpi {
|
||||
ImageInputStream stream = (ImageInputStream)input;
|
||||
byte[] b = new byte[4];
|
||||
stream.mark();
|
||||
stream.readFully(b);
|
||||
boolean full = ReaderUtil.tryReadFully(stream, b);
|
||||
stream.reset();
|
||||
|
||||
return ((b[0] == (byte)0x49 && b[1] == (byte)0x49 &&
|
||||
return full &&
|
||||
((b[0] == (byte)0x49 && b[1] == (byte)0x49 &&
|
||||
b[2] == (byte)0x2a && b[3] == (byte)0x00) ||
|
||||
(b[0] == (byte)0x4d && b[1] == (byte)0x4d &&
|
||||
b[2] == (byte)0x00 && b[3] == (byte)0x2a));
|
||||
|
@ -28,12 +28,10 @@ package com.sun.imageio.plugins.wbmp;
|
||||
import java.util.Locale;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.spi.IIORegistry;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.IIOException;
|
||||
import com.sun.imageio.plugins.common.ReaderUtil;
|
||||
|
||||
public class WBMPImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
@ -86,16 +84,16 @@ public class WBMPImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
stream.mark();
|
||||
try {
|
||||
int type = stream.readByte(); // TypeField
|
||||
int fixHeaderField = stream.readByte();
|
||||
int type = stream.read(); // TypeField, or -1 if EOF
|
||||
int fixHeaderField = stream.read();
|
||||
// check WBMP "header"
|
||||
if (type != 0 || fixHeaderField != 0) {
|
||||
// while WBMP reader does not support ext WBMP headers
|
||||
return false;
|
||||
}
|
||||
|
||||
int width = ReaderUtil.readMultiByteInteger(stream);
|
||||
int height = ReaderUtil.readMultiByteInteger(stream);
|
||||
int width = tryReadMultiByteInteger(stream);
|
||||
int height = tryReadMultiByteInteger(stream);
|
||||
// check image dimension
|
||||
if (width <= 0 || height <= 0) {
|
||||
return false;
|
||||
@ -123,6 +121,34 @@ public class WBMPImageReaderSpi extends ImageReaderSpi {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a positive integer value encoded on a variable number of bytes,
|
||||
* but stops the reading on end-of-file (EOF) or on integer overflow.
|
||||
*
|
||||
* @param stream the image input stream to read.
|
||||
* @return the integer value, or -1 if EOF or integer overflow.
|
||||
*/
|
||||
private static int tryReadMultiByteInteger(ImageInputStream stream)
|
||||
throws IOException {
|
||||
int value = stream.read();
|
||||
if (value < 0) {
|
||||
return -1; // EOF
|
||||
}
|
||||
int result = value & 0x7f;
|
||||
while ((value & 0x80) == 0x80) {
|
||||
if ((result & 0xfe000000) != 0) {
|
||||
return -1; // 7 highest bits already used
|
||||
}
|
||||
result <<= 7;
|
||||
value = stream.read();
|
||||
if (value < 0) {
|
||||
return -1; // EOF
|
||||
}
|
||||
result |= (value & 0x7f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ImageReader createReaderInstance(Object extension)
|
||||
throws IIOException {
|
||||
return new WBMPImageReader(this);
|
||||
|
69
test/jdk/javax/imageio/plugins/shared/CanDecodeTest.java
Normal file
69
test/jdk/javax/imageio/plugins/shared/CanDecodeTest.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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
|
||||
* @summary Verifies that canDecode does not throw EOFException
|
||||
* if the file has too few bytes.
|
||||
* @run main CanDecodeTest
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
public class CanDecodeTest {
|
||||
|
||||
private static final String[] FORMATS = {
|
||||
"WBMP", "BMP", "GIF", "PNG", "TIFF", "JPEG"
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (String format : FORMATS) {
|
||||
ImageReader reader =
|
||||
ImageIO.getImageReadersByFormatName(format).next();
|
||||
ImageReaderSpi spi = reader.getOriginatingProvider();
|
||||
|
||||
for (int n=0; n<8; n++) {
|
||||
InputStream dataStream =
|
||||
new ByteArrayInputStream(new byte[n]);
|
||||
try {
|
||||
ImageInputStream iis =
|
||||
ImageIO.createImageInputStream(dataStream);
|
||||
|
||||
if (spi.canDecodeInput(iis)) {
|
||||
throw new RuntimeException("Test failed for " +
|
||||
format + " format: shall not decode.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Test failed for " +
|
||||
format + " format: " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -66,6 +66,7 @@ public class CanDecodeTest {
|
||||
(byte) 0x0a, (byte) 0x00}, 39693, false));
|
||||
v.add(new TestCase("ico", new byte[]{(byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x01, (byte) 0x00}, 1078, false));
|
||||
v.add(new TestCase("empty", new byte[0], 0, false));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user