JDK-7201156 : jar tool fails to convert file separation characters for list and extract
  • Type: Bug
  • Component: tools
  • Sub-Component: jar
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2012-09-26
  • Updated: 2013-06-26
  • Resolved: 2012-11-14
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 7 JDK 8
7u40Fixed 8 b66Fixed
Related Reports
Relates :  
Description
SYNOPSIS
--------
jar tool fails to convert file separation characters for list and extract


OPERATING SYSTEMS
-----------------
Windows, although the code is platform independent and the problem would occur on any operating system that uses something other than '/' as the file separation character


FULL JDK VERSIONS
-----------------
All since 6u18, including latest Java 7 and JDK 8


PROBLEM DESCRIPTION from LICENSEE
---------------------------------
If a JAR file contains an entry inside a directory, that file cannot be extracted on Windows if the entry name on the command line is constructed with backslashes as the file separation character.

For example, consider a JAR file (test.jar) containing the following entries:

     0 Wed Aug 29 13:48:26 BST 2012 META-INF/
    71 Wed Aug 29 13:48:26 BST 2012 META-INF/MANIFEST.MF
     0 Wed Aug 29 13:47:54 BST 2012 test/
     4 Wed Aug 29 13:47:58 BST 2012 test/test.txt

The following commands work on 6u17, but fail on all releases since 6u18:

    jar -tvf test.jar test\test.txt
    jar -xvf test.jar test\test.txt

The problem is in the new private method replaceFSC() in src/share/classes/sun/tools/jar/Main.java, which was introduced by the changes for CR 6496274. This method is clearly intended to replace the file separation character given on the command line with '/' to ensure that the entry name complies with the ZIP specification, but it fails to do so because it uses a foreach loop:

    void replaceFSC(String files[]) {
        if (files != null) {
            for (String file : files) {
                file = file.replace(File.separatorChar, '/');
            }
        }
    }

According to the page below, the foreach construct cannot be used "for loops where you need to replace elements in a list or array as you traverse it":

    http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

Unfortunately that is precisely what the replaceFSC() implementation is trying to do...


TESTCASE
--------
Example jar attached.


REPRODUCTION INSTRUCTIONS
-------------------------
Simply run jar against the attached jar file as follows:

    jar -tvf test.jar test\test.txt
    jar -xvf test.jar test\test.txt

Expected output for "jar -tvf":
    4 Wed Aug 29 13:47:58 BST 2012 test/test.txt

Expected output for "jar -xvf":
    inflated: test/test.txt

Observed output:
No output is produced, and no files are listed/extracted.


WORKAROUND
----------
Use forward slashes instead of backslashes as the file separator on the command line.


SUGGESTED FIX from LICENSEE
---------------------------
The fix is to use a regular for loop - i.e. the implementation for replaceFSC() becomes:

    void replaceFSC(String files[]) {
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                files[i] = files[i].replace(File.separatorChar, '/');
            }
        }
    }

Comments
verified b66
11-12-2012