JDK-8076641 : getNextEntry throws ArrayIndexOutOfBoundsException when unzipping file
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2015-03-24
  • Updated: 2016-08-24
  • Resolved: 2015-04-06
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.
JDK 8 JDK 9
8u60Fixed 9 b60Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
When attempting to unzip a data file an ArrayIndexOutOfBoundsException is thrown when iterating over the contents of the zip file. 

The file begins the following:
  50 4b 03 04 14 00 00 00 00 00 8c bc 5c 44 00 00  
  00 00 00 00 00 00 00 00 00 00 0d 00 2c 00 4e 44  
  44 46 20 50 6c 75 73 20 44 42 2f 4e 55 20 00 4e
  55 43 58 0d 00 4e 00 44 00 44 00 46 00 20 00 50 
  00 6c 00 75 00 73 00 20 00 44 00 42 00 2f 00 0a  
  00 04 00 00 00 00 00 50 4b 03 04 14 00 00 00 00  
  00 8c bc 5c 44 00 00 00 00 00 00 00 00 00 00 00  



REGRESSION.  Last worked in version 7u76

ADDITIONAL REGRESSION INFORMATION: 
c:\Program Files (x86)\Java\jre7\bin>java -version
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) Client VM (build 24.76-b04, mixed mode, sharing)


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run included test program with a zip file containing XCeed unicode extra field data. The application will crash.

I can provide a sample zip file upon request



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Tthe application will succeed in unzipping the files into the destination directory.
ACTUAL -
The actual results were the stack trace listed in the logs.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
UnzipTest>java Unzipper
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 46
        at java.util.zip.ZipUtils.get16(Unknown Source)
        at java.util.zip.ZipEntry.setExtra0(Unknown Source)
        at java.util.zip.ZipInputStream.readLOC(Unknown Source)
        at java.util.zip.ZipInputStream.getNextEntry(Unknown Source)
        at Unzipper.main(Unzipper.java:34)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class Unzipper {

	public static void main(String[] args) throws IOException {
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
		String now = LocalDateTime.now().format(df);
		String WORKPATH = "C:\\maidev\\FDBUpdate\\"; 
		String DATAPATH = WORKPATH + "DATA_" + now + "\\";
		String FDB_FILENAME = "NDDF Plus UPD.zip";

		// Unzip 
		String unzipPath = WORKPATH + FDB_FILENAME;


		Path filePath = Paths.get(unzipPath);
		byte[] fileBytes = Files.readAllBytes(filePath);
		ByteArrayInputStream bytes = new ByteArrayInputStream(fileBytes);
		ZipInputStream zis = new ZipInputStream(bytes);
		ZipEntry entry;
		while ((entry = zis.getNextEntry()) != null) {
			int count;
			int n = entry.getName().lastIndexOf("/"); 
			String filename = entry.getName().substring(n + 1);
			File fileOut = new File(DATAPATH + filename);
			if (entry.isDirectory()) {
				fileOut.mkdirs();
			}
			else
			{
				byte[] buffer = (byte[]) java.lang.reflect.Array.newInstance(java.lang.Byte .TYPE, 1024);
				FileOutputStream fos = new FileOutputStream(fileOut); 
				// read byte content from zipped file
				while ((count = zis.read(buffer, 0, 1024)) != -1) {
					fos.write(buffer, 0, count);
				}

				fos.close();
			}
		}

		zis.close();
	}
}

---------- END SOURCE ----------


Comments
Received following response from the submitter: ---------------------------------------------------------------------------------- I am aware of the change in the Java time support. My code changed from this in the Java7 version: String DATAPATH = WORKPATH + "DATA_" + DateUtil.getCurrentDate("yyyyMMddHHmmss") + "\\"; To this in the Java8 version: DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); String now = LocalDateTime.now().format(df); String WORKPATH = "C:\\maidev\\FDBUpdate\\"; String DATAPATH = WORKPATH + "DATA_" + now + "\\"; My roadblock is that the zip portion of the code, which remained the same, does not work. -------------------------------------------------------------------------------------------------------
06-04-2015

all entries of the offending zip file have "extra" data in its loc as tag=554e, sz=nnn tag=a, sz=4 The spec requires that the 000a/NTFS has at least (4 + 32) bytes for the block, but it appears the zip does "follow" the spec to put a "sz = 4" (tag/sz only) here. The implementation need to skip this data, instead of throwing an AIOOBE exception. (NTFS) 0x000a 2 bytes Tag for this "extra" block type TSize 2 bytes Size of the total "extra" block Reserved 4 bytes Reserved for future use Tag1 2 bytes NTFS attribute tag value #1 Size1 2 bytes Size of attribute #1, in bytes (var) Size1 Attribute #1 data . . . TagN 2 bytes NTFS attribute tag value #N SizeN 2 bytes Size of attribute #N, in bytes (var) SizeN Attribute #N data For NTFS, values for Tag1 through TagN are as follows: (currently only one set of attributes is defined for NTFS) Tag Size Description ----- ---- ----------- 0x0001 2 bytes Tag for attribute #1 Size1 2 bytes Size of attribute #1, in bytes Mtime 8 bytes File last modification time Atime 8 bytes File last access time Ctime 8 bytes File creation time Interestingly all ntfs timestamps are correctly recorded in its cen table. java java jdk.nio.zipfs.ZipInfo foo.zip ...
03-04-2015

1) Run the attached modified test case with supporting files (JavaApplication277.zip) for JDK 8 and above versions. 2) On a Windows 7 (64-bit) system, checked this for JDK 7u80, 8u40, and 8u60 and could reproduce this issue. **************************************************************************************** 8: FAIL 8u31: FAIL 8u40: FAIL 8u60 ea b07: FAIL ****************************************************************************************** Output of the testcase with 8u40: run: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 44 at java.util.zip.ZipUtils.get16(ZipUtils.java:103) at java.util.zip.ZipEntry.setExtra0(ZipEntry.java:455) at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:322) at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122) at unzipper.Unzipper.main(Unzipper.java:34) Java Result: 1 BUILD SUCCESSFUL (total time: 0 seconds) ******************************************************************************************* Result: This issue is reproducible with JDK 8-all. However, couldn't confirm this for 7u76 as the code is not compilable with 7u76 since package java.time does not exist. I have written back to the submitter for clarification.
03-04-2015