From b71e686cbd0689a3dbca55cc345de3e212ef7391 Mon Sep 17 00:00:00 2001 From: chenrl Date: Sun, 21 Mar 2021 16:46:15 +0800 Subject: [PATCH] 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 --- .../web/context/support/ServletContextResource.java | 9 +++++++-- .../web/context/support/ResourceTests.java | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResource.java b/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResource.java index 9f19b76d9971..ad236509d88d 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResource.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResource.java @@ -139,10 +139,15 @@ public boolean isFile() { 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; } } diff --git a/spring-web/src/test/java/org/springframework/web/context/support/ResourceTests.java b/spring-web/src/test/java/org/springframework/web/context/support/ResourceTests.java index 340838871814..937885e107f7 100644 --- a/spring-web/src/test/java/org/springframework/web/context/support/ResourceTests.java +++ b/spring-web/src/test/java/org/springframework/web/context/support/ResourceTests.java @@ -36,6 +36,8 @@ public void testServletContextResource() throws IOException { 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 void testServletContextResourceWithRelativePath() throws IOException { } 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 @@ private void doTestResource(Resource resource) throws IOException { 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(); + } }