Details
-
Bug
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
1.0
-
None
-
None
Description
Attempting to open a ZIP file with an embedded relative path causes an exception.
To create a sample zip:
mkdir dir
echo "foo" > dir/test.txt
mkdir test
cd test
zip test.zip ../dir/test.txt
test.zip will now contain a path with a relative path that ascends above the root of the zip. unzip -l output will look something like:
4 10-15-05 12:24 ../dir/test.txt
The ZIP was created with InfoZIP: Zip 2.32 (June 19th 2006).
When the file is accessed programatically with:
VFS.getManager().resolveFile("zip:///path/to/test/test.zip");
The following exception occurs:
org.apache.commons.vfs.FileSystemException: Invalid relative file name.
at org.apache.commons.vfs.provider.UriParser.normalisePath(UriParser.java:154)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveName(DefaultFileSystemManager.java:731)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveName(DefaultFileSystemManager.java:684)
at org.apache.commons.vfs.provider.zip.ZipFileSystem.init(ZipFileSystem.java:88)
at org.apache.commons.vfs.provider.AbstractVfsContainer.addComponent(AbstractVfsContainer.java:53)
at org.apache.commons.vfs.provider.AbstractFileProvider.addFileSystem(AbstractFileProvider.java:96)
at org.apache.commons.vfs.provider.AbstractLayeredFileProvider.createFileSystem(AbstractLayeredFileProvider.java:80)
at org.apache.commons.vfs.provider.AbstractLayeredFileProvider.findFile(AbstractLayeredFileProvider.java:59)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:641)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:602)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:570)
UriParser.normalisePath() contains the following code:
if (elemLen == 1 && path.charAt(startElem) == '.')
{
// A '.' element - axe it
path.delete(startElem, endElem + 1);
maxlen = path.length();
continue;
}
if (elemLen == 2 && path.charAt(startElem) == '.'
&& path.charAt(startElem + 1) == '.')
{
// A '..' element - remove the previous element
if (startElem == startFirstElem)
// Find start of previous element
int pos = startElem - 2;
for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--)
{
}
startElem = pos + 1;
path.delete(startElem, endElem + 1);
maxlen = path.length();
continue;
}
// A regular element
startElem = endElem + 1;
}
I think it would be appropriate to change the throw in the middle to 'continue' as in the case for a single dot above.