United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4879507 ZipInputStream does not check CRC for stored (uncompressed) files
4879507 : ZipInputStream does not check CRC for stored (uncompressed) files

Details
Type:
Bug
Submit Date:
2003-06-16
Status:
Closed
Updated Date:
2010-07-09
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
core-libs
OS:
solaris_9,windows_xp
Sub-Component:
java.util.jar
CPU:
x86,sparc
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.1,1.4.2_06
Fixed Versions:
7

Related Reports
Backport:
Backport:
Backport:
Relates:
Relates:

Sub Tasks

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

                                    

Comments
EVALUATION

We should compare CRCs for complete entries only. Found by David Bristor.
                                     
2006-11-28
SUGGESTED FIX

--- ZipInputStream.java-	2006-11-14 16:37:38.000000000 +0300
+++ ZipInputStream.java	2006-11-30 19:05:24.000000000 +0300
@@ -158,10 +158,15 @@
            if (len == -1) {
                throw new ZipException("unexpected EOF");
            }
            crc.update(b, off, len);
            remaining -= len;
+           if (remaining == 0 && entry.crc != crc.getValue()) {
+               throw new ZipException(
+                   "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
+                   " but got 0x" + Long.toHexString(crc.getValue()) + ")");
+           }
            return len;
        default:
            throw new InternalError("invalid compression method");
        }
     }
                                     
2006-11-21
EVALUATION

The problem could be fixed adding explicit CRC check to the read(byte[], int, int)
function into the STORED case. See Suggested Fix.
                                     
2006-11-21
EVALUATION

Fixing 6332094 (use ZipFile instead of ZipInputStream) will alleviate the situation at least for the jar command, though not for the APIs.
                                     
2006-10-10
EVALUATION

The zip/unzip command handles corrupted stored file contents
correctly:

 $ echo data > file; rm -f my.zip; zip my.zip file; perl -pi -e 's/data/tada/' my.zip; unzip -o my.zip
  adding: file (stored 0%)
Archive:  my.zip
 extracting: file                     bad CRC 9a07f170  (should be e6c1c582)

jar should implement the same algorithm.
###@###.### 2003-06-18
                                     
2003-06-18



Hardware and Software, Engineered to Work Together