Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8266435

WBMPImageReader.read() should not truncate the input stream

XMLWordPrintable

    • 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


              jdv Jayathirth D V
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              10 Start watching this issue

                Created:
                Updated:
                Resolved: