This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push: new 6b412a9239 Fix off by one validation logic for partial PUT ranges 6b412a9239 is described below commit 6b412a9239eed40e87be359582cc9e80f6cfe0d1 Author: remm <r...@apache.org> AuthorDate: Mon Apr 14 13:05:03 2025 +0200 Fix off by one validation logic for partial PUT ranges The testcase was also wrong, so this includes a fix. Submitted by Chenjp with PR#843 --- .../apache/catalina/servlets/DefaultServlet.java | 9 ++++--- .../catalina/servlets/TestDefaultServletPut.java | 29 +++++++++++----------- webapps/docs/changelog.xml | 4 +++ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java index 48a34d0b39..c8fa8135a4 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -756,17 +756,18 @@ public class DefaultServlet extends HttpServlet { int numBytesRead; byte[] transferBuffer = new byte[BUFFER_SIZE]; try (BufferedInputStream requestBufInStream = new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) { + long rangeBytes = range.getEnd() - range.getStart() + 1L; while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) { received += numBytesRead; - if (received > range.getEnd() - range.getStart()) { + if (received > rangeBytes) { throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", - String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + String.valueOf(received), String.valueOf(rangeBytes))); } randAccessContentFile.write(transferBuffer, 0, numBytesRead); } - if (received < range.getEnd() - range.getStart()) { + if (received < rangeBytes) { throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", - String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + String.valueOf(received), String.valueOf(rangeBytes))); } } diff --git a/test/org/apache/catalina/servlets/TestDefaultServletPut.java b/test/org/apache/catalina/servlets/TestDefaultServletPut.java index 55a04b79d6..0255819497 100644 --- a/test/org/apache/catalina/servlets/TestDefaultServletPut.java +++ b/test/org/apache/catalina/servlets/TestDefaultServletPut.java @@ -41,9 +41,9 @@ import org.apache.tomcat.util.buf.ByteChunk; public class TestDefaultServletPut extends TomcatBaseTest { private static final String START_TEXT= "Starting text"; - private static final String START_LEN = Integer.toString(START_TEXT.length()); + private static final int START_LEN = START_TEXT.length(); private static final String PATCH_TEXT= "Ending *"; - private static final String PATCH_LEN = Integer.toString(PATCH_TEXT.length()); + private static final int PATCH_LEN = PATCH_TEXT.length(); private static final String END_TEXT= "Ending * text"; @Parameterized.Parameters(name = "{index} rangeHeader [{0}]") @@ -52,23 +52,23 @@ public class TestDefaultServletPut extends TomcatBaseTest { // Valid partial PUT parameterSets.add(new Object[] { - "Content-Range: bytes 0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.TRUE, END_TEXT, Boolean.TRUE }); + "Content-Range: bytes 0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.TRUE, END_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: ByTeS 0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.TRUE, END_TEXT, Boolean.TRUE }); + "Content-Range: ByTeS 0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.TRUE, END_TEXT, Boolean.TRUE }); // Full PUT parameterSets.add(new Object[] { "", null, PATCH_TEXT, Boolean.TRUE }); // Invalid range parameterSets.add(new Object[] { - "Content-Range: apples 0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: apples 0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: bytes00-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: bytes00-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: bytes0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: bytes0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: bytes=0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: bytes=0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: bytes@0-" + PATCH_LEN + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: bytes@0-" + (PATCH_LEN-1) + "/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { "Content-Range: bytes 9-7/" + START_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { @@ -82,16 +82,17 @@ public class TestDefaultServletPut extends TomcatBaseTest { parameterSets.add(new Object[] { "Content-Range: bytes 0-5/0x5" + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); parameterSets.add(new Object[] { - "Content-Range: bytes 0-" + PATCH_LEN + "/" + PATCH_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); + "Content-Range: bytes 0-" + (PATCH_LEN) + "/" + PATCH_LEN + CRLF, Boolean.FALSE, START_TEXT, Boolean.TRUE }); // 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 }); + "Content-Range: bytes 0-" + (PATCH_LEN-1) + "/" + 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 }); - + parameterSets.add(new Object[] { "Content-Range: bytes 0-" + PATCH_LEN + "/20" + CRLF, Boolean.FALSE, + START_TEXT, Boolean.TRUE }); + parameterSets.add(new Object[] { "Content-Range: bytes 0-" + (PATCH_LEN - 2) + "/20" + CRLF, Boolean.FALSE, + START_TEXT, Boolean.TRUE }); return parameterSets; } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 038a0e9b64..359dd465f2 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -129,6 +129,10 @@ <bug>69643</bug>: Optimize directory listing for large amount of files. Patch submitted by Loic de l'Eprevier. (remm) </fix> + <fix> + <pr>843</pr>: Fix off by one validation logic for partial PUT ranges + and associated test case. Submitted by Chenjp. (remm) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org