jai-imageio / jai-imageio-core

JAI ImageIO Core (without javax.media.jai dependencies)
Other
234 stars 87 forks source link

WBMPImageReader doesn't check read() result #75

Open THausherr opened 3 years ago

THausherr commented 3 years ago

com.sun.imageio.plugins.wbmp.WBMPImageReader doesn't check its read() result:

iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
                     0, height*sm.getScanlineStride());

It should call readFully() or check the read() result and do a loop. See also https://github.com/haraldk/TwelveMonkeys/issues/606

Because of that, this code fails if LIMIT is less than the file size:


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);
        }

    }
}
THausherr commented 3 years ago

https://bugs.openjdk.java.net/browse/JDK-8266435