Name: nt126004 Date: 06/16/2003
FULL PRODUCT VERSION :
JDK 1.4.1_01-b01
FULL OS VERSION :
WindowsXP
A DESCRIPTION OF THE PROBLEM :
java.util.zip.ZipInputStream does not check CRCs for STORED (uncompressed) files. Corrupted archives with wrong CRCs are read without throwing an exception.
I've tracked this in the sources too :
read(byte[],int,int) method in the ZipInputStream class has two case branches. When current zip entry is read to the end, the 'DEFLATED' case makes a call to private readEnd(ZipEntry) method which checks CRC and throws and exception if it is invalid. However, the 'STORED' case does not call the readEnd(ZipEntry) method and does not check CRC on its own.
I've changed the archive content using a hex editor. I didn't change
anything in headers, since this would be detected and I didn't change
file length as this is also properly handled in ZipInputStream and would
cause an exception. The point is to change a few bytes so that the only
way to detect it is using CRCs.
I've prepared an example.
I took README.txt file from JRE distribution. I've archived it using the
following command :
jar cf0 testjar.jar README.txt
I've opened created archive in a hex editor and changed string "Java(TM) 2"
to "Java(TM) 3".
Now, archivers such as WinZip report a CRC error and refuse to open this
archive. ZipInputStream does not report any problems.
When I extract the README.txt from this archive using this command :
jar xf testjar.jar
I get a nice README.txt file refering to Java 3 Runtime environment !!!!!
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Take arbitrary uncompressed JAR file and corrupt it using a hex-editor. Make sure headers are not changed and file length is not changed.
Use the jar command-line tool to extract the corrupted archive ... and ... no CRC error is reported.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The archive should be reported as corrupted
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.zip.*;
public class Test {
public static void main(String[] args)
{
ZipEntry ze;
try{
String path_to_corrupted_jar = "x.jar";
JarInputStream jis =
new JarInputStream(new FileInputStream(path_to_corrupted_jar));
byte buf[] = new byte[8000];
while( (ze = jis.getNextEntry()) != null)
{
while(jis.read(buf)>0);
System.out.println("Zip entry "+ze.getName()+" read OK");
}
} catch(ZipException ex) {
/* Exception about CRC error should be thrown, but it is not */
ex.printStackTrace();
} catch(IOException ex) {
ex.printStackTrace();
}
}
}
---------- END SOURCE ----------
(Review ID: 187744)
======================================================================