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

JPEG Image Decoding questionable as a result of fixes for bugs 4836529, 4903659

XMLWordPrintable

    • b38
    • x86
    • linux



      Name: tb29552 Date: 01/12/2004


      FULL PRODUCT VERSION :
      java version "1.5.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b31)
      Java HotSpot(TM) Client VM (build 1.5.0-beta-b31, mixed mode)

      I also took the source code changes for bugs 4836529 and 4903659 and back
      ported them to the 1.4 source for the jpegimagedecoderimpl, and both my version of the 1.4 libjpeg.so and the 1.5.0-beta-b31 behaved the same way.

      ADDITIONAL OS VERSION INFORMATION :
      Linux 2.4.7-10smp #1 SMP Thu Sep 6 16:16:16 EDT 2001 i686 unknown

      I believe this problem is actually OS independent, since it's in the JPEG native library implementation.

      A DESCRIPTION OF THE PROBLEM :
      NOTE: I'm a Sun employee, Professional Services IT Architect working
      onsite at Network Solutions in Herndon, Virginia. Although I've tested
      against 1.5.0, the customer does not have access to this beta distribution.

      The fix for bug 4836529 properly prevents the JVM from crashing when
      reading a corrupted JPEG image. However, the fix for 4903659 seems to
      prevent certain seemingly-valid JPEG images from being decoded as well,
      while definitely preventing the fatal allocation-loop described in the original
      bug report.

      I can provide test images which demonstrate this problem; please email
      me at either ###@###.### or ###@###.###.
      I have three images:

         - corrupt.jpg -- proves that 4903659 is fixed;
                                   No more endless looping until an OutOfMemory crash. The
                                   decode completes without an exception thrown, which is
                                   consistent with other non-Java JPEG viewers, such as
                                   mozilla.

         - Kaat_corrupt.jpg -- proves that 4836529 is fixed;
                                    No more JVM crashes, just a friendly ImageFormatException.
                                    This file is a truly bad image, and cannot be opened by
                                    mozilla or other image viewers.

         - Kaat_good.jpg -- the problem image now that both fixes for bugs 4836529
                                     and 4903659 are in place; it throws an
                                     ImageFormatException in 1.5.0 and when I backported the
                                     fixes to the 1.4 open source. Without the fixes in place, this
                                     image decodes without an error in JDK 1.[234]. It also
                                     opens fine in other non-Java image viewers.

      If I change the code fix for bug 4903659 from:

      jpegimagedecoderimpl.c:

      572 // check for JPEG_EOI and reading errors
      573 if (src->pub.next_input_byte[len-1] == JPEG_EOI
      574 || src->err != NULL)
      575 {
      576 // no more data in the buffer, leave loop.
      577 break;
      578 }

      to this:

      572 // check for reading errors
      573 if (src->err != NULL)
      575 {
      576 // there's an error, stop reading input.
      577 break;
      578 }

      then all three images are decoded the way I'd expect them to. That is,

      - corrupt.jpg no longer loops until an OutOfMemory and doesn't throw an
      ImageFormatException,

      - Kaat_corrupt.jpg throws an ImageFormatException

      - Kaat_good.jpg decodes with no errors.

      I'm not sure why exactly checking for JPEG_EOI isn't a good thing for
      Kaat_good.jpg, but without that check, the behavior seems more correct.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See description. Email me for the test images.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The JVM I'm using is on Linux 2.4.7-10smp:

      bash-2.05$ /opt/jdk/1.4.1_01-jpegfix/bin/java -version
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      except that I've replaced the libjpeg.so with a custom built version of the 1.4
      libjpeg.so with the fixes for 4836529 and 4903659 backported from tiger,
      and with the fix for 4903659 changed to *not* check for JPEG_EOI, just
      that there are no input errors.

      bash-2.05$ /opt/jdk/1.4.1_01-jpegfix/bin/java -classpath . JpegTest corrupt.jpg
      Corrupt JPEG data: 1 extraneous bytes before marker 0xeb
      [returns to Unix prompt without an exception or crash -- this is good]

      bash-2.05$ /opt/jdk/1.4.1_01-jpegfix/bin/java -classpath . JpegTest Kaat_corrupt.jpg
      Corrupt JPEG data: 325 extraneous bytes before marker 0xd8
      com.sun.image.codec.jpeg.ImageFormatException: Invalid JPEG file structure: two SOI markers
              at sun.awt.image.codec.JPEGImageDecoderImpl.readJPEGStream(Native Method)
              at sun.awt.image.codec.JPEGImageDecoderImpl.decodeAsBufferedImage(JPEGImageDecoderImpl.java:210)
              at JpegTest.main(JpegTest.java:29)
      [this is excepted as a result of the bug fix, and is consistent with errors given
      by other non-Java image viewers]

      bash-2.05$ /opt/jdk/1.4.1_01-jpegfix/bin/java -classpath . JpegTest Kaat_good.jpg
      [returns to Unix prompt without an exception thrown -- consistent with the
      ability of other non-Java image viewers to open Kaat_good.jpg]

      ACTUAL -
      The JVM I'm using is on Linux 2.4.7-10smp:

      bash-2.05$ /opt/jdk/1.5.0/bin/java -version
      java version "1.5.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b31)
      Java HotSpot(TM) Client VM (build 1.5.0-beta-b31, mixed mode)

      bash-2.05$ /opt/jdk/1.5.0/bin/java -classpath . JpegTest corrupt.jpg
      Corrupt JPEG data: 1 extraneous bytes before marker 0xeb
      [returns to Unix prompt without an exception or crash -- this is good.]

      bash-2.05$ /opt/jdk/1.5.0/bin/java -classpath . JpegTest Kaat_corrupt.jpg
      Corrupt JPEG data: 325 extraneous bytes before marker 0xd8
      com.sun.image.codec.jpeg.ImageFormatException: Invalid JPEG file structure: two SOI markers
              at sun.awt.image.codec.JPEGImageDecoderImpl.readJPEGStream(Native Method)
              at sun.awt.image.codec.JPEGImageDecoderImpl.decodeAsBufferedImage(JPEGImageDecoderImpl.java:210)
              at JpegTest.main(JpegTest.java:29)
      [this is expected as a result of the bug fix, and is consistent with errors given
      by other non-Java image viewers]

      bash-2.05$ /opt/jdk/1.5.0/bin/java -classpath . JpegTest Kaat_good.jpg
      Corrupt JPEG data: 307 extraneous bytes before marker 0xd8
      com.sun.image.codec.jpeg.ImageFormatException: Invalid JPEG file structure: two SOI markers
              at sun.awt.image.codec.JPEGImageDecoderImpl.readJPEGStream(Native Method)
              at sun.awt.image.codec.JPEGImageDecoderImpl.decodeAsBufferedImage(JPEGImageDecoderImpl.java:210)
              at JpegTest.main(JpegTest.java:29)
      [this is the problem -- this is not consistent with other non-Java image viewers
      which are able to decode Kaat_good.jpg without an error]

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      See actual results detail.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      This is the same JpegTest class referenced in the detail for bug 4903659.

      import com.sun.image.codec.jpeg.ImageFormatException;
      import com.sun.image.codec.jpeg.JPEGCodec;
      import com.sun.image.codec.jpeg.JPEGImageDecoder;
      import com.sun.image.codec.jpeg.JPEGImageEncoder;
      import com.sun.image.codec.jpeg.TruncatedFileException;
      import java.awt.image.BufferedImage;
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.File;
      import java.io.IOException;
      import java.io.OutputStream;
      import java.io.RandomAccessFile;

      public class JpegTest
      {
          public static void main(String[] args)
          {
              ByteArrayInputStream is = null;

              try
              {
                  File sourceFile = new File(args[0]);
                  byte[] data = new byte[(int)sourceFile.length()];
                  RandomAccessFile f = new RandomAccessFile(sourceFile, "r");
                  f.readFully(data);
                  f.close();
                  is = new ByteArrayInputStream(data);
                  JPEGImageDecoder dec = JPEGCodec.createJPEGDecoder(is);
                  BufferedImage bufferedImage = dec.decodeAsBufferedImage();
              }
              catch(IOException io)
              {
                  io.printStackTrace();
              }
              catch( Throwable t)
              {
                  t.printStackTrace();
              }
              finally
              {
                  if(is != null)
                  {
                      try
                      {
                          is.close();
                      }
                      catch(IOException io)
                      {}
                  }
              }
          }
          
      }



      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Modification to code fix for bug 4903659 in jpegimagedecoderimpl.c.
      See description.
      (Incident Review ID: 233149)
      ======================================================================

            bae Andrew Brygin
            tbell Tim Bell
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: