Fix ServletContextResource isFile check

Prior to this commit, `ServletContextResource` could rely on
`ServletContext#getRealPath` to check whether a resource exists.
This behavior is not enforced on some Servlet containers, as this method
is only meant to translate virtual paths to real paths, but not
necessarily check for the existence of the file.

See https://bz.apache.org/bugzilla/show_bug.cgi?id=55837#c3 for a
rationale of this behavior in Tomcat.

This commit enforces an additional check, resolving the path as a `File`
and checking that is exists and is a file.

Closes gh-26707
This commit is contained in:
chenrl 2021-03-21 16:46:15 +08:00 committed by Brian Clozel
parent 433a23a0bd
commit b71e686cbd
2 changed files with 17 additions and 2 deletions

View File

@ -139,10 +139,15 @@ public class ServletContextResource extends AbstractFileResolvingResource implem
return true;
}
else {
return (this.servletContext.getRealPath(this.path) != null);
String realPath = this.servletContext.getRealPath(this.path);
if (realPath == null) {
return false;
}
File file = new File(realPath);
return (file.exists() && file.isFile());
}
}
catch (MalformedURLException ex) {
catch (IOException ex) {
return false;
}
}

View File

@ -36,6 +36,8 @@ public class ResourceTests {
MockServletContext sc = new MockServletContext();
Resource resource = new ServletContextResource(sc, "org/springframework/core/io/Resource.class");
doTestResource(resource);
Resource resourceNotExists = new ServletContextResource(sc, "org/springframework/core/io/ResourceNotExists.class");
doTestNotExistsResource(resourceNotExists);
assertThat(new ServletContextResource(sc, "org/springframework/core/../core/io/./Resource.class")).isEqualTo(resource);
}
@ -48,6 +50,9 @@ public class ResourceTests {
}
private void doTestResource(Resource resource) throws IOException {
assertThat(resource.getFile()).isNotNull();
assertThat(resource.exists()).isTrue();
assertThat(resource.isFile()).isTrue();
assertThat(resource.getFilename()).isEqualTo("Resource.class");
assertThat(resource.getURL().getFile().endsWith("Resource.class")).isTrue();
@ -61,4 +66,9 @@ public class ResourceTests {
assertThat(relative2.getURL().getFile().endsWith("ResourcePatternResolver.class")).isTrue();
assertThat(relative2.exists()).isTrue();
}
private void doTestNotExistsResource(Resource resource) throws IOException {
assertThat(resource.exists()).isFalse();
assertThat(resource.isFile()).isFalse();
}
}