JDK-4764639 : Errors when loading PNG/GIF images from compressed JAR files
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 1.4.0,1.4.2,1.4.2_02,5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,solaris_7
  • CPU: generic,sparc
  • Submitted: 2002-10-17
  • Updated: 2003-04-21
  • Resolved: 2003-04-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Duplicate :  
Duplicate :  
Description
Image I/O developers are having trouble loading PNG/GIF images from
compressed JAR files (uncompressed JAR files and loading the classes/resources
directly from disk work correctly).  I've written a small testcase that mimicks
the PNGImageReader's usage of InputStreams.  Basically, it uses an
InflaterInputStream (wrapped by a BufferedInputStream/DataInputStream)
in order to read the ZLIB compressed portion of the PNG image.  The test
reads these uncompressed bytes and prints them one line at a time.  I
have a feeling this is problematic when the original InputStream is a
ZipFileInputStream (because the PNG is loaded from a compressed JAR file).  I
can run my testcase in an uncompressed JAR, and it's fine (because the original
InputStream is a plain FileInputStream), but when I run it in a compressed
JAR file, the printed bytes do not match the uncompressed case.  In
practice, the PNGImageReader sees this garbage as unknown markers and
emits warnings/exceptions.  The GIFImageReader simply produces a visibly
corrupted image.

Testcase source code, image, and JAR files are attached.

The testcase is JarredImage.java, and the test image is key40grey.png. 
comp.jar contains the class files and PNG (compressed), and nocomp.jar 
contains the same files, but store-only (non-compressed).  The testcase 
mimicks our IIO PNGImageReader, and as it reads the ZLIB compressed 
portion of the PNG image, it spits the byte index and value line by line 
to stdout.  You can diff the results from the comp.jar run and the 
nocomp.jar run, and you'll see they begin to differ around line number 
660 (that is, the 660th byte in the compressed image segment).

Usage:
% java -cp comp.jar JarredImage > comp.txt
% java -cp nocomp.jar JarredImage > nocomp.txt
% java JarredImage > nojar.txt (should be the same as nocomp.jar)
% diff comp.txt nocomp.txt

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b05
14-06-2004

EVALUATION May be related to the bogus values returned from ZipFileInputStream.available(). If so it is the same problem as reported in bugs 4401122 and 4675817. ###@###.### 2002-12-03 The above is probably not related. Problem occurs when more than one inflater is used in a single chain of streams. ###@###.### 2002-12-06 The problem appears to be a bug in javax.imageio.stream.MemoryCache.loadFromStream(). When it reads a block of data and gets less than it asked for, it puts the results of the next read into another block but that data gets corrupted. I have attached a short program that demonstrates this. ###@###.### 2002-12-10 The fix suggested in the comments section is essentially correct, but is missing one element. After incrementing offset, we must check to see if we've filled the current buffer, and if so, nullify buf so that a new one will be allocated on the next iteration. Here are the final diffs: 103d102 < buf = null; 106a106,112 > offset += nbytes; > > if (offset >= BUFFER_LENGTH) { > // we've filled the current buffer, so a new one will be > // allocated next time around (and offset will be reset to 0) > buf = null; > } ###@###.### 2003-01-08
08-01-2003

WORK AROUND Put the data into a storage spot before doing the second inflation. That is, don't use a chain of streams that includes more than one zip inflater at a time. ###@###.### 2002-12-06
06-12-2002