-
Bug
-
Resolution: Fixed
-
P3
-
8, 11, 16, 17, 18
-
b27
-
x86_64
-
generic
ADDITIONAL SYSTEM INFORMATION :
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment Corretto-16.0.1.9.1 (build 16.0.1+9)
OpenJDK 64-Bit Server VM Corretto-16.0.1.9.1 (build 16.0.1+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
com.sun.imageio.plugins.wbmp.WBMPImageReader doesn't check the return value of read() .
iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
0, height*sm.getScanlineStride());
it should check the return value and read more, or call readFully.
Using a third party ImageInputStream is a problem if read() reads less than expected, although this is legal.
https://github.com/haraldk/TwelveMonkeys/issues/606
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
success
---------- BEGIN SOURCE ----------
package jdk9test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStreamImpl;
public class WBmpBug
{
static final int LIMIT = 1000; // limit 32000 works
public static void main(String[] args) throws IOException
{
BufferedImage bw = new BufferedImage(500, 500, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g = (Graphics2D) bw.getGraphics();
g.setBackground(Color.white);
g.fillRect(0, 0, bw.getWidth(), bw.getHeight());
g.dispose();
boolean b = ImageIO.write(bw, "wbmp", new File("test2.wbmp"));
assert b = true;
BufferedImage bim2 = ImageIO.read(new LimitedImageInputStream(new File("test2.wbmp"), LIMIT));
//BufferedImage bim2 = ImageIO.read(new File("test2.wbmp")); // this works
b = ImageIO.write(bim2, "wbmp", new File("test3.wbmp"));
assert b = true;
for (int x = 0; x < bim2.getWidth(); ++x)
{
for (int y = 0; y < bim2.getHeight(); ++y)
{
int i1 = bim2.getRGB(x, y);
int i2 = bw.getRGB(x, y);
if (i1 != i2)
{
System.err.println("fail");
System.exit(-1);
}
}
}
System.out.println("success");
}
static class LimitedImageInputStream extends ImageInputStreamImpl
{
private final RandomAccessFile raf;
private final int limit;
public LimitedImageInputStream(File file, int limit) throws FileNotFoundException
{
raf = new RandomAccessFile(file, "r");
this.limit = limit;
}
@Override
public int read() throws IOException
{
return raf.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
int readlen = raf.read(b, off, Math.min(limit, len));
System.out.println("readLen: " + readlen + " of " + len);
return readlen;
}
@Override
public void close() throws IOException
{
super.close();
raf.close();
}
@Override
public void seek(long pos) throws IOException
{
super.seek(pos);
raf.seek(pos);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
use higher buffer size (32000) or use standard classes
FREQUENCY : always
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment Corretto-16.0.1.9.1 (build 16.0.1+9)
OpenJDK 64-Bit Server VM Corretto-16.0.1.9.1 (build 16.0.1+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
com.sun.imageio.plugins.wbmp.WBMPImageReader doesn't check the return value of read() .
iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
0, height*sm.getScanlineStride());
it should check the return value and read more, or call readFully.
Using a third party ImageInputStream is a problem if read() reads less than expected, although this is legal.
https://github.com/haraldk/TwelveMonkeys/issues/606
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
success
---------- BEGIN SOURCE ----------
package jdk9test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStreamImpl;
public class WBmpBug
{
static final int LIMIT = 1000; // limit 32000 works
public static void main(String[] args) throws IOException
{
BufferedImage bw = new BufferedImage(500, 500, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g = (Graphics2D) bw.getGraphics();
g.setBackground(Color.white);
g.fillRect(0, 0, bw.getWidth(), bw.getHeight());
g.dispose();
boolean b = ImageIO.write(bw, "wbmp", new File("test2.wbmp"));
assert b = true;
BufferedImage bim2 = ImageIO.read(new LimitedImageInputStream(new File("test2.wbmp"), LIMIT));
//BufferedImage bim2 = ImageIO.read(new File("test2.wbmp")); // this works
b = ImageIO.write(bim2, "wbmp", new File("test3.wbmp"));
assert b = true;
for (int x = 0; x < bim2.getWidth(); ++x)
{
for (int y = 0; y < bim2.getHeight(); ++y)
{
int i1 = bim2.getRGB(x, y);
int i2 = bw.getRGB(x, y);
if (i1 != i2)
{
System.err.println("fail");
System.exit(-1);
}
}
}
System.out.println("success");
}
static class LimitedImageInputStream extends ImageInputStreamImpl
{
private final RandomAccessFile raf;
private final int limit;
public LimitedImageInputStream(File file, int limit) throws FileNotFoundException
{
raf = new RandomAccessFile(file, "r");
this.limit = limit;
}
@Override
public int read() throws IOException
{
return raf.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
int readlen = raf.read(b, off, Math.min(limit, len));
System.out.println("readLen: " + readlen + " of " + len);
return readlen;
}
@Override
public void close() throws IOException
{
super.close();
raf.close();
}
@Override
public void seek(long pos) throws IOException
{
super.seek(pos);
raf.seek(pos);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
use higher buffer size (32000) or use standard classes
FREQUENCY : always