Issue #3983 - JarFileResource directory listing is invalid

+ Correcting encoded path searching
+ Adding more unit tests to ensure no regression

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2019-08-16 15:48:42 -05:00
parent f65e59cadf
commit 472ede48cd
3 changed files with 84 additions and 8 deletions

View File

@ -29,7 +29,6 @@ import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -116,9 +115,11 @@ public class JarFileResource extends JarResource
_jarFile = null;
_list = null;
int sep = _urlString.lastIndexOf("!/");
_jarUrl = _urlString.substring(0, sep + 2);
_path = URIUtil.decodePath(_urlString.substring(sep + 2));
// Work with encoded URL path
String urlFilePath = _url.getPath();
int sep = urlFilePath.lastIndexOf("!/");
_jarUrl = urlFilePath.substring(0, sep + 2);
_path = URIUtil.decodePath(urlFilePath.substring(sep + 2));
if (_path.length() == 0)
_path = null;
_jarFile = _jarConnection.getJarFile();
@ -316,11 +317,12 @@ public class JarFileResource extends JarResource
}
Enumeration<JarEntry> e = jarFile.entries();
String dir = _urlString.substring(_urlString.lastIndexOf("!/") + 2);
String encodedDir = _urlString.substring(_urlString.lastIndexOf("!/") + 2);
String dir = URIUtil.decodePath(encodedDir);
while (e.hasMoreElements())
{
JarEntry entry = e.nextElement();
String name = StringUtil.replace(entry.getName(), '\\', '/');
String name = entry.getName();
if (!name.startsWith(dir) || name.length() == dir.length())
{
continue;

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.util.resource;
import java.io.IOException;
import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
@ -41,6 +42,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -138,9 +140,9 @@ public class JarResourceTest
@Test
public void testJarFileCopyToDirectoryTraversal() throws Exception
{
Path testZip = MavenTestingUtils.getTestResourcePathFile("TestData/extract.zip");
Path extractZip = MavenTestingUtils.getTestResourcePathFile("TestData/extract.zip");
String s = "jar:" + testZip.toUri().toASCIIString() + "!/";
String s = "jar:" + extractZip.toUri().toASCIIString() + "!/";
Resource r = Resource.newResource(s);
assertThat(r, instanceOf(JarResource.class));
@ -188,6 +190,78 @@ public class JarResourceTest
assertTrue(r.exists());
}
@Test
public void testJarFileResourceList() throws Exception
{
Path testJar = MavenTestingUtils.getTestResourcePathFile("jar-file-resource.jar");
String uri = "jar:" + testJar.toUri().toASCIIString() + "!/";
Resource resource = new JarFileResource(URI.create(uri).toURL());
Resource rez = resource.addPath("rez/");
assertThat("path /rez/ is a dir", rez.isDirectory(), is(true));
List<String> actual = Arrays.asList(rez.list());
String[] expected = new String[]{
"one",
"aaa",
"bbb",
"oddities/",
"another dir/",
"ccc",
"deep/",
};
assertThat("Dir contents", actual, containsInAnyOrder(expected));
}
/**
* Test getting a file listing of a Directory in a JAR
* Where the JAR entries contain names that are URI encoded / escaped
*/
@Test
public void testJarFileResourceList_PreEncodedEntries() throws Exception
{
Path testJar = MavenTestingUtils.getTestResourcePathFile("jar-file-resource.jar");
String uri = "jar:" + testJar.toUri().toASCIIString() + "!/";
Resource resource = new JarFileResource(URI.create(uri).toURL());
Resource rez = resource.addPath("rez/oddities/");
assertThat("path /rez/oddities/ is a dir", rez.isDirectory(), is(true));
List<String> actual = Arrays.asList(rez.list());
String[] expected = new String[]{
";",
"#hashcode",
"index.html#fragment",
"other%2fkind%2Fof%2fslash", // pre-encoded / escaped
"a file with a space",
";\" onmousedown=\"alert(document.location)\"",
"some\\slash\\you\\got\\there" // not encoded, stored as backslash native
};
assertThat("Dir contents", actual, containsInAnyOrder(expected));
}
@Test
public void testJarFileResourceList_DirWithSpace() throws Exception
{
Path testJar = MavenTestingUtils.getTestResourcePathFile("jar-file-resource.jar");
String uri = "jar:" + testJar.toUri().toASCIIString() + "!/";
Resource resource = new JarFileResource(URI.create(uri).toURL());
Resource anotherDir = resource.addPath("rez/another dir/");
assertThat("path /rez/another dir/ is a dir", anotherDir.isDirectory(), is(true));
List<String> actual = Arrays.asList(anotherDir.list());
String[] expected = new String[]{
"a file.txt",
"another file.txt",
"..\\a different file.txt",
};
assertThat("Dir contents", actual, containsInAnyOrder(expected));
}
private List<Path> listFiles(Path dir) throws IOException
{
return Files.list(dir).collect(Collectors.toList());

Binary file not shown.