This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 88c43c7964 Return 400 for content and range mismatch 88c43c7964 is described below commit 88c43c79641024b0f8d0b642aeabbb8be24896e7 Author: remm <r...@apache.org> AuthorDate: Wed Mar 5 11:31:02 2025 +0100 Return 400 for content and range mismatch Still hacked together since the existing DefaultServlet executePartialPut method signature is not appropriate. As suggested in PR#810. --- .../apache/catalina/servlets/DefaultServlet.java | 21 +++++++++++++++++---- .../catalina/servlets/LocalStrings.properties | 1 + .../catalina/servlets/TestDefaultServletPut.java | 5 +++++ webapps/docs/changelog.xml | 4 ++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java index 5ec84477cf..2cd14a2638 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -612,10 +612,12 @@ public class DefaultServlet extends HttpServlet { resourceInputStream = req.getInputStream(); } else { tempContentFile = executePartialPut(req, range, path); - resourceInputStream = new FileInputStream(tempContentFile); + if (tempContentFile != null) { + resourceInputStream = new FileInputStream(tempContentFile); + } } - if (resources.write(path, resourceInputStream, true)) { + if (resourceInputStream != null && resources.write(path, resourceInputStream, true)) { if (resource.exists()) { resp.setStatus(HttpServletResponse.SC_NO_CONTENT); } else { @@ -623,7 +625,8 @@ public class DefaultServlet extends HttpServlet { } } else { try { - resp.sendError(HttpServletResponse.SC_CONFLICT); + resp.sendError(resourceInputStream != null ? + HttpServletResponse.SC_CONFLICT : HttpServletResponse.SC_BAD_REQUEST); } catch (IllegalStateException e) { // Already committed, ignore } @@ -687,12 +690,22 @@ public class DefaultServlet extends HttpServlet { // Append data in request input stream to contentFile randAccessContentFile.seek(range.getStart()); + long received = 0; int numBytesRead; byte[] transferBuffer = new byte[BUFFER_SIZE]; try (BufferedInputStream requestBufInStream = new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) { while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) { + received += numBytesRead; + if (received > range.getEnd() - range.getStart()) { + throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", + String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + } randAccessContentFile.write(transferBuffer, 0, numBytesRead); } + if (received < range.getEnd() - range.getStart()) { + throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", + String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + } } } catch (IOException | RuntimeException | Error e) { @@ -700,7 +713,7 @@ public class DefaultServlet extends HttpServlet { if (!contentFile.delete()) { log(sm.getString("defaultServlet.deleteTempFileFailed", contentFile.getAbsolutePath())); } - throw e; + return null; } return contentFile; diff --git a/java/org/apache/catalina/servlets/LocalStrings.properties b/java/org/apache/catalina/servlets/LocalStrings.properties index c09a862802..cf55fcc832 100644 --- a/java/org/apache/catalina/servlets/LocalStrings.properties +++ b/java/org/apache/catalina/servlets/LocalStrings.properties @@ -53,6 +53,7 @@ defaultServlet.resource.name=Name defaultServlet.resource.size=Size defaultServlet.skipfail=Read failed because only [{0}] bytes were available but needed to skip [{1}] bytes to reach the start of the requested range defaultServlet.unknownBomConfig=Unrecognised value of [{0}] provided for useBomIfPresent initialization parameter +defaultServlet.wrongByteCountForRange=An invalid amount [{0}] of bytes were received for range with length [{1}] defaultServlet.xslError=XSL transformer error webdavservlet.externalEntityIgnored=The request included a reference to an external entity with PublicID [{0}] and SystemID [{1}] which was ignored diff --git a/test/org/apache/catalina/servlets/TestDefaultServletPut.java b/test/org/apache/catalina/servlets/TestDefaultServletPut.java index d19b95684d..55a04b79d6 100644 --- a/test/org/apache/catalina/servlets/TestDefaultServletPut.java +++ b/test/org/apache/catalina/servlets/TestDefaultServletPut.java @@ -86,6 +86,11 @@ public class TestDefaultServletPut extends TomcatBaseTest { // Valid partial PUT but partial PUT is disabled parameterSets.add(new Object[] { "Content-Range: bytes 0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.TRUE, START_TEXT, Boolean.FALSE }); + // Errors due to incorrect length + parameterSets.add(new Object[] { + "Content-Range: bytes 0-1/" + PATCH_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + parameterSets.add(new Object[] { + "Content-Range: bytes 0-19/20" + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); return parameterSets; } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 6f969f1ed0..b2d6b20990 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -150,6 +150,10 @@ <code>/</code>. (markt) </fix> <!-- Entries for backport and removal before 12.0.0-M1 below this line --> + <fix> + Return 400 if the amount of content sent for a partial PUT is + inconsistent with the range that was specified. (remm) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org