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)
======================================================================