-
Enhancement
-
Resolution: Won't Fix
-
P4
-
None
-
8u66
-
generic
-
generic
A DESCRIPTION OF THE REQUEST :
ZipInputStream throws a ZipException (with message "only DEFLATED entries can have EXT descriptor") when there is a zero-length entry and the compression method is not set to DEFLATE. This is compliant with PKZIP standard 2.04g - however, later versions of the PKZIP standard have relaxed this requirement and any compression method can be used for zero-length entries.
JUSTIFICATION :
From the Zip Format Specification [https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT] section 4.4.4 general purpose bit flag:
Bit 3: If this bit is set, the fields crc-32, compressed size and uncompressed size are set to zero in the local header. The correct values are put in the data descriptor immediately following the compressed data. (Note: PKZIP version 2.04g for DOS only recognizes this bit for method 8 compression, newer versions of PKZIP recognize this bit for any compression method.)
ZipInputStream appears to comply strictly to version 2.04g and throws a ZipException when the General Purpose Bit Flag is set and the compression is not set to DEFLATE (method 8).
This is not compliant with later PKZIP versions and causes ZipInputStream to be unable to read some zip files.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
ZipInputStream to handle zip files which are compliant to the latest PKZip standard.
ACTUAL -
ZipInputStream throws ZipException when it reads a zip file which is valid under a later specification.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.zip.*;
public class TestZip {
public static void main( final String[] args ) throws IOException {
final File file = new File( args[0] );
if ( file.exists() )
{
System.out.println( "File already exists" );
return;
}
final boolean general_purpose_bit_flag_bit3_on = true;
final byte gpbf = general_purpose_bit_flag_bit3_on ? 0x08 : 0x00;
final byte[] contents = new byte[]{
// Local File header
'P', 'K', 3, 4, // Local File Header Signature
13, 0, // Version needed to extract
gpbf, 8, // General purpose bit flag
ZipEntry.STORED, 0, // Compression method
'q', 'l', 't', 'G', // Last Modification time & date
0, 0, 0, 0, // CRC32
0, 0, 0, 0, // Compressed Size
0, 0, 0, 0, // Uncompressed Size
12, 0, // File name length
0, 0, // Extra field length
'F', 'o', 'l', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '/',
// File name
// Central directory file header
'P', 'K', 1, 2, // Central Directory File Header Signature
13, 0, // Version made by
13, 0, // Version needed to extract
gpbf, 8, // General purpose bit flag
ZipEntry.STORED, 0, // Compression method
'q', 'l', 't', 'G', // Last Modification time & date
0, 0, 0, 0, // CRC32
0, 0, 0, 0, // Compressed Size
0, 0, 0, 0, // Uncompressed Size
12, 0, // File name length
0, 0, // Extra field length
0, 0, // File comment length
0, 0, // Disk number where file starts
0, 0, // Internal File attributes
0, 0, 0, 0, // External File attributes
0, 0, 0, 0, // Relative offset of local header file
'F', 'o', 'l', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '/',
// File name
// End of Central Directory Record
'P', 'K', 5, 6, // Local File Header Signature
0, 0, // Number of this disk
0, 0, // Disk where CD starts
1, 0, // Number of CD records on this disk
1, 0, // Total number of records
58, 0, 0, 0, // Size of CD
42, 0, 0, 0, // Offset of start of CD
0, 0, // Comment length
};
try ( FileOutputStream fos = new FileOutputStream( file ) )
{
fos.write(contents);
}
try ( ZipInputStream zis = new ZipInputStream( new FileInputStream( file ) ) )
{
ZipEntry entry = zis.getNextEntry();
System.out.println( entry.getName() );
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None found
ZipInputStream throws a ZipException (with message "only DEFLATED entries can have EXT descriptor") when there is a zero-length entry and the compression method is not set to DEFLATE. This is compliant with PKZIP standard 2.04g - however, later versions of the PKZIP standard have relaxed this requirement and any compression method can be used for zero-length entries.
JUSTIFICATION :
From the Zip Format Specification [https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT] section 4.4.4 general purpose bit flag:
Bit 3: If this bit is set, the fields crc-32, compressed size and uncompressed size are set to zero in the local header. The correct values are put in the data descriptor immediately following the compressed data. (Note: PKZIP version 2.04g for DOS only recognizes this bit for method 8 compression, newer versions of PKZIP recognize this bit for any compression method.)
ZipInputStream appears to comply strictly to version 2.04g and throws a ZipException when the General Purpose Bit Flag is set and the compression is not set to DEFLATE (method 8).
This is not compliant with later PKZIP versions and causes ZipInputStream to be unable to read some zip files.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
ZipInputStream to handle zip files which are compliant to the latest PKZip standard.
ACTUAL -
ZipInputStream throws ZipException when it reads a zip file which is valid under a later specification.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.zip.*;
public class TestZip {
public static void main( final String[] args ) throws IOException {
final File file = new File( args[0] );
if ( file.exists() )
{
System.out.println( "File already exists" );
return;
}
final boolean general_purpose_bit_flag_bit3_on = true;
final byte gpbf = general_purpose_bit_flag_bit3_on ? 0x08 : 0x00;
final byte[] contents = new byte[]{
// Local File header
'P', 'K', 3, 4, // Local File Header Signature
13, 0, // Version needed to extract
gpbf, 8, // General purpose bit flag
ZipEntry.STORED, 0, // Compression method
'q', 'l', 't', 'G', // Last Modification time & date
0, 0, 0, 0, // CRC32
0, 0, 0, 0, // Compressed Size
0, 0, 0, 0, // Uncompressed Size
12, 0, // File name length
0, 0, // Extra field length
'F', 'o', 'l', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '/',
// File name
// Central directory file header
'P', 'K', 1, 2, // Central Directory File Header Signature
13, 0, // Version made by
13, 0, // Version needed to extract
gpbf, 8, // General purpose bit flag
ZipEntry.STORED, 0, // Compression method
'q', 'l', 't', 'G', // Last Modification time & date
0, 0, 0, 0, // CRC32
0, 0, 0, 0, // Compressed Size
0, 0, 0, 0, // Uncompressed Size
12, 0, // File name length
0, 0, // Extra field length
0, 0, // File comment length
0, 0, // Disk number where file starts
0, 0, // Internal File attributes
0, 0, 0, 0, // External File attributes
0, 0, 0, 0, // Relative offset of local header file
'F', 'o', 'l', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '/',
// File name
// End of Central Directory Record
'P', 'K', 5, 6, // Local File Header Signature
0, 0, // Number of this disk
0, 0, // Disk where CD starts
1, 0, // Number of CD records on this disk
1, 0, // Total number of records
58, 0, 0, 0, // Size of CD
42, 0, 0, 0, // Offset of start of CD
0, 0, // Comment length
};
try ( FileOutputStream fos = new FileOutputStream( file ) )
{
fos.write(contents);
}
try ( ZipInputStream zis = new ZipInputStream( new FileInputStream( file ) ) )
{
ZipEntry entry = zis.getNextEntry();
System.out.println( entry.getName() );
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None found
- relates to
-
JDK-8327690 Unzipping Dropbox Files: Only DEFLATED entries can have EXT descriptor
- Closed