JDK-4766057 : Reading entries from certain zipped files causes JVM death (native exception)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 1.3.1,1.4.1
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_8,windows_2000
  • CPU: x86,sparc
  • Submitted: 2002-10-21
  • Updated: 2004-01-06
  • Resolved: 2003-01-22
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 Other
1.3.1_11 11Fixed 1.4.2Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description

Name: nt126004			Date: 10/21/2002


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

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
(with Service Pack 2)

EXTRA RELEVANT SYSTEM CONFIGURATION :
Intel Pentium 4 2.26Ghz CPU with 1G RAM

A DESCRIPTION OF THE PROBLEM :
Opening zip files created with PKWare's PKZip version 2.50
for DOS randomly causes an exception in native code and
kills the VM.

There have been several bug reports that could be related,
but this one seems different because I have no reason to
suspect that the zip file is corrupt, and am not doing any
multi-threaded interactions with a ZipFile.

The closest existing bug id is 4731870, but that bug is
only an RFE for a better error message.  This is not
sufficient.  This is a VM death issue and should not go
unsolved, esp. if the input zip file is not corrupt.

I have managed to create a test program that provides good
reproducibility of this bug, but it is fragile.  The
reasons for this fragility are unclear to me, but making
small, seemingly innocent, changes to the program will
cause the bug to be much harder to reproduce.  Because of
this I think the problem might be an interaction between
the hotspot compiler and the zip.dll native code.

In the steps to reproduce below, I have given instructions
on how to recreate the data files that cause problems.  If
it is desirable, however, please contact me for the binary
files that reproduce this behavor (also true if the
compiled java class doesn't reproduce the problem, because
I'm slighlty worried by the fragility of this bug).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
You need two zip files to reproduce this.  How to create
them:
1.  Create a test1.txt file that contains some actual text
data (my test contains the string "This is a stupid test
string.\n" repeated 132 times).
2.  Copy this file into test2.txt, test3.txt, and test4.txt
3.  Using PKZip version 2.50 for DOS (available as
shareware), zip these text files into a zip file
called "pkware123456789012345.zip".  This name must be
exact or the test program won't work.  Changing the test
program will cause it to not reproduce as frequently.
4.  Using WinZip (I used 8.0), zip
these text files into a zip file
called "pkware123456789012345.zip".  Once again, this name
is important (actually, the length of the name is
important).
5.  Create a directory on your C: drive titles "zipcrash"
and put these zip files there.  Once again, this is only
necessary because the java class is fragile, and changing
it can cause the bug to fail to reproduce.

Now that the data files have been created:
1.  Compile to ZipCrash.java class.  To cause a crash, make
sure that line 17 is uncommented and line 20 is commented.
  To use the WinZip file and see that it doesn't crash,
reverse those line numbers.
2.  Execute ZipCrash.  It is hardcoded to look in
c:\zipcrash for the two files created earlier.
3.  If after about 30 seconds it hasn't crashed, CTRL-C to
break out and rerun.  I've never had to do this step more
than once or twice to get a crash to occur with the PKZip
file.

EXPECTED VERSUS ACTUAL BEHAVIOR :
I expect the zip code to work with any valid zip file.  The
actual result is a native code failure (which is NOT
acceptable).

ERROR MESSAGES/STACK TRACES THAT OCCUR :
The death occurs with two different stack traces in this simple test program.
I thought it might be useful to see both of them.

This is a failure when iterating through the entries:

An unexpected exception has been detected in native code outside the VM.
Unexpected Signal : EXCEPTION_ACCESS_VIOLATION occurred at PC=0x6D32797D
Function=ZIP_Open+0x369
Library=c:\webctrl_2.0\java\windows\jre\bin\zip.dll

Current Java thread:
	at java.util.zip.ZipFile.getNextEntry(Native Method)
	at java.util.zip.ZipFile.access$400(ZipFile.java:26)
	at java.util.zip.ZipFile$2.nextElement(ZipFile.java:301)
	at java.util.Collections.list(Collections.java:2481)
	at ZipCrash.crashZip1(ZipCrash.java:45)
	at ZipCrash.main(ZipCrash.java:32)

Dynamic libraries:
0x00400000 - 0x00406000 	c:\webctrl_2.0\java\windows\bin\java.exe
0x77F80000 - 0x77FFB000 	C:\WINNT\System32\ntdll.dll
0x77DB0000 - 0x77E0C000 	C:\WINNT\system32\ADVAPI32.dll
0x77E80000 - 0x77F35000 	C:\WINNT\system32\KERNEL32.DLL
0x77D40000 - 0x77DAD000 	C:\WINNT\system32\RPCRT4.DLL
0x78000000 - 0x78046000 	C:\WINNT\system32\MSVCRT.dll
0x6D330000 - 0x6D45C000 	c:\webctrl_2.0
\java\windows\jre\bin\client\jvm.dll
0x77E10000 - 0x77E74000 	C:\WINNT\system32\USER32.dll
0x77F40000 - 0x77F7C000 	C:\WINNT\system32\GDI32.DLL
0x77570000 - 0x775A0000 	C:\WINNT\System32\WINMM.dll
0x6D1D0000 - 0x6D1D7000 	c:\webctrl_2.0\java\windows\jre\bin\hpi.dll
0x6D300000 - 0x6D30D000 	c:\webctrl_2.0\java\windows\jre\bin\verify.dll
0x6D210000 - 0x6D229000 	c:\webctrl_2.0\java\windows\jre\bin\java.dll
0x6D320000 - 0x6D32D000 	c:\webctrl_2.0\java\windows\jre\bin\zip.dll
0x77920000 - 0x77943000 	C:\WINNT\system32\imagehlp.dll
0x72A00000 - 0x72A2D000 	C:\WINNT\system32\DBGHELP.dll
0x690A0000 - 0x690AB000 	C:\WINNT\System32\PSAPI.DLL

Local Time = Thu Oct 17 11:32:17 2002
Elapsed Time = 0
#
# The exception above was detected in native code outside the VM
#
# Java VM: Java HotSpot(TM) Client VM (1.4.1-b21 mixed mode)
#


and this is a failure when getting the input stream to an entry:

An unexpected exception has been detected in native code outside the VM.
Unexpected Signal : EXCEPTION_ACCESS_VIOLATION occurred at PC=0x6D32797D
Function=ZIP_Open+0x369
Library=c:\webctrl_2.0\java\windows\jre\bin\zip.dll

Current Java thread:
	at java.util.zip.ZipFile.getEntry(Native Method)
	at java.util.zip.ZipFile.getInputStream(ZipFile.java:194)
	at java.util.zip.ZipFile.getInputStream(ZipFile.java:182)
	at ZipCrash.crashZip1(ZipCrash.java:53)
	at ZipCrash.main(ZipCrash.java:32)

Dynamic libraries:
0x00400000 - 0x00406000 	c:\webctrl_2.0\java\windows\bin\java.exe
0x77F80000 - 0x77FFB000 	C:\WINNT\System32\ntdll.dll
0x77DB0000 - 0x77E0C000 	C:\WINNT\system32\ADVAPI32.dll
0x77E80000 - 0x77F35000 	C:\WINNT\system32\KERNEL32.DLL
0x77D40000 - 0x77DAD000 	C:\WINNT\system32\RPCRT4.DLL
0x78000000 - 0x78046000 	C:\WINNT\system32\MSVCRT.dll
0x6D330000 - 0x6D45C000 	c:\webctrl_2.0
\java\windows\jre\bin\client\jvm.dll
0x77E10000 - 0x77E74000 	C:\WINNT\system32\USER32.dll
0x77F40000 - 0x77F7C000 	C:\WINNT\system32\GDI32.DLL
0x77570000 - 0x775A0000 	C:\WINNT\System32\WINMM.dll
0x6D1D0000 - 0x6D1D7000 	c:\webctrl_2.0\java\windows\jre\bin\hpi.dll
0x6D300000 - 0x6D30D000 	c:\webctrl_2.0\java\windows\jre\bin\verify.dll
0x6D210000 - 0x6D229000 	c:\webctrl_2.0\java\windows\jre\bin\java.dll
0x6D320000 - 0x6D32D000 	c:\webctrl_2.0\java\windows\jre\bin\zip.dll
0x77920000 - 0x77943000 	C:\WINNT\system32\imagehlp.dll
0x72A00000 - 0x72A2D000 	C:\WINNT\system32\DBGHELP.dll
0x690A0000 - 0x690AB000 	C:\WINNT\System32\PSAPI.DLL

Local Time = Thu Oct 17 11:27:02 2002
Elapsed Time = 0
#
# The exception above was detected in native code outside the VM
#
# Java VM: Java HotSpot(TM) Client VM (1.4.1-b21 mixed mode)
#


REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.util.*;
import java.io.*;

public class ZipCrash
{
   private static File tmpDir;
   private static File zFile;

   public static void main(String[] args)
   {
      File startDir = new File("c:\\zipcrash");
      tmpDir  = new File(startDir, "tmpdir");

      // uncomment this line to cause the crash (and line 20 must be commented
out)
      zFile = new File(startDir, "pkware123456789012345.zip");

      // uncomment this line to avoid the crash (and line 17 must be commented
out)
//      zFile = new File(startDir, "winzip123456789012345.zip");

      crashZip1();
   }

   private static void crashZip1()
   {
      try
      {
         while (true)
         {
            ZipFile zipFile = null;
            try
            {
               zipFile = new ZipFile(zFile);
               List entries = Collections.list(zipFile.entries());

               for (Iterator it = entries.iterator(); it.hasNext();)
               {
                  ZipEntry zipEntry = (ZipEntry)it.next();
                  File destFile = new File(tmpDir, zipEntry.getName());
                  destFile.getParentFile().exists();

                  InputStream in = zipFile.getInputStream(zipEntry);
                  in.close();
               }
            }
            finally
            {
               if (zipFile != null)
                  zipFile.close();
            }
         }
      }
      catch (Throwable e)
      {
         System.out.println("ZipCrash died: "+e.getMessage());
      }
   }



   ////////////////////////////////////////////////////////////////////////////
   // The code below this comment is not used, but removing it
   // from the class greatly reduces the likelihood of a crash.
   ////////////////////////////////////////////////////////////////////////////

   private static void notUsed1()
   {
      try
      {
         while (true)
         {
            tmpDir.delete();
            tmpDir.mkdir();

            ZipFile zipFile = null;
            try
            {
               zipFile = new ZipFile(zFile);
               List entries = notUsed2(Collections.list(zipFile.entries()));

               for (Iterator it = entries.iterator(); it.hasNext();)
               {
                  String zipEntryName = (String)it.next();
                  File destFile = new File(tmpDir, zipEntryName);
                  destFile.getParentFile().mkdirs();

                  InputStream in = null;
                  OutputStream out = null;
                  try
                  {
                     zipFile.close();
                     zipFile = new ZipFile(zFile);
                     ZipEntry zipEntry = zipFile.getEntry(zipEntryName);
                     in = zipFile.getInputStream(zipEntry);

                     out = new FileOutputStream(destFile);
                     notUsed3(in, out);
                  }
                  finally
                  {
                     if (in != null) in.close();
                     if (out != null) out.close();
                  }
               }
            }
            finally
            {
               if (zipFile != null)
                  zipFile.close();
            }

            System.out.print('.');
         }
      }
      catch (Throwable e)
      {
         System.out.println("ZipCrash died: "+e.getMessage());
      }
   }

   private static List notUsed2(ArrayList list)
   {
      int listSize = list.size();
      List resultList = new ArrayList(Collections.nCopies(listSize, null));
      Random rand = new Random();

      for (Iterator it = list.iterator(); it.hasNext();)
      {
         ZipEntry e = (ZipEntry)it.next();
         while(true)
         {
            int idx = rand.nextInt(listSize);
            if (resultList.get(idx) == null)
            {
               // YAY!  Found a free slot!
               resultList.set(idx, e.getName());
               break;
            }
         }
      }

      return resultList;
   }

   private static void notUsed3( InputStream in, OutputStream out )
      throws java.io.IOException
   {
      // declare a 10000 byte buffer for copy operations.
      int bufferSize = 10000;
      byte[] buffer = new byte[bufferSize];

      while (true)
      {
         int bytesRead = in.read(buffer);
         if (bytesRead == -1) break;
         out.write(buffer, 0, bytesRead);
      }
   }

}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Don't use zip files created using PKZip 2.50 for DOS.
Other zip tools may also cause problems.  This assumes that
you have control over the creation of the zip files,
however.
(Review ID: 165907) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_11 generic mantis-beta FIXED IN: 1.3.1_11 mantis-beta INTEGRATED IN: 1.3.1_11 mantis-b14 mantis-beta VERIFIED IN: 1.3.1_11 mantis-beta
14-06-2004

EVALUATION Please attach a zip file with which this problem is known to be reproducible. -- ###@###.### 2002/12/4 I have the files but haven't been able to reproduce this problem yet. ###@###.### 2002-12-05 Caused by buffer overflow in src/share/native/java/util/zip/zip_util.c, in the readLOC function. ###@###.### 2002-12-11
05-12-2002