United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7201156 jar tool fails to convert file separation characters for list and extract
JDK-7201156 : jar tool fails to convert file separation characters for list and extract

Details
Type:
Bug
Submit Date:
2012-09-26
Status:
Closed
Updated Date:
2012-12-13
Project Name:
JDK
Resolved Date:
2012-11-14
Component:
tools
OS:
generic
Sub-Component:
jar
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
8
Fixed Versions:

Related Reports
Backport:
Relates:

Sub Tasks

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
URL:   http://hg.openjdk.java.net/jdk8/tl/jdk/rev/83765e82cacb
User:  luchsh
Date:  2012-11-14 05:28:02 +0000

                                     
2012-11-14
URL:   http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/83765e82cacb
User:  lana
Date:  2012-11-27 20:02:56 +0000

                                     
2012-11-27
verified b66
                                     
2012-12-11



Hardware and Software, Engineered to Work Together