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, '/');
}
}
}