This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 1317b8471d Partial put - enhance content range verification (#778)
1317b8471d is described below
commit 1317b8471d100dc1a34fa8d7c3f468e90eea9a5f
Author: Chenjp <[email protected]>
AuthorDate: Thu Nov 28 01:36:53 2024 +0800
Partial put - enhance content range verification (#778)
* enhance content range verification
ContentRange - add isValid(), more length check.
ContentRange - parse(): make sure the not-null return of parse() is valid.
force content-range unit in lowercase internally.
TestDefaultServletPut - partial put
* isValid: remove unnecessary condition.
---------
Co-authored-by: Mark Thomas <[email protected]>
---
.../apache/catalina/servlets/DefaultServlet.java | 10 ++-------
.../tomcat/util/http/parser/ContentRange.java | 26 ++++++++++++++++++++--
.../catalina/servlets/TestDefaultServletPut.java | 4 ++++
webapps/docs/changelog.xml | 5 +++++
4 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java
b/java/org/apache/catalina/servlets/DefaultServlet.java
index 5ba5c172af..9d34e7e99d 100644
--- a/java/org/apache/catalina/servlets/DefaultServlet.java
+++ b/java/org/apache/catalina/servlets/DefaultServlet.java
@@ -1239,12 +1239,6 @@ public class DefaultServlet extends HttpServlet {
contentType.contains("/javascript");
}
- private static boolean validate(ContentRange range) {
- // bytes is the only range unit supported
- return (range != null) && ("bytes".equals(range.getUnits())) &&
(range.getStart() >= 0) &&
- (range.getEnd() >= 0) && (range.getStart() <= range.getEnd())
&& (range.getLength() > 0);
- }
-
private static boolean validate(Ranges ranges, long length) {
List<long[]> rangeContext = new ArrayList<>();
for (Ranges.Entry range : ranges.getEntries()) {
@@ -1425,8 +1419,8 @@ public class DefaultServlet extends HttpServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
-
- if (!validate(contentRange)) {
+ // bytes is the only range unit supported
+ if (!"bytes".equals(contentRange.getUnits())) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
diff --git a/java/org/apache/tomcat/util/http/parser/ContentRange.java
b/java/org/apache/tomcat/util/http/parser/ContentRange.java
index d77a0e4c41..62a67c4221 100644
--- a/java/org/apache/tomcat/util/http/parser/ContentRange.java
+++ b/java/org/apache/tomcat/util/http/parser/ContentRange.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.http.parser;
import java.io.IOException;
import java.io.StringReader;
+import java.util.Locale;
public class ContentRange {
@@ -28,13 +29,21 @@ public class ContentRange {
public ContentRange(String units, long start, long end, long length) {
- this.units = units;
+ // Units are lower case (RFC 9110, section 14.1)
+ if (units == null) {
+ this.units = null;
+ } else {
+ this.units = units.toLowerCase(Locale.ENGLISH);
+ }
this.start = start;
this.end = end;
this.length = length;
}
+ /**
+ * @return rangeUnits in lower case.
+ */
public String getUnits() {
return units;
}
@@ -103,6 +112,19 @@ public class ContentRange {
return null;
}
- return new ContentRange(units, start, end, length);
+ ContentRange contentRange = new ContentRange(units, start, end,
length);
+ if (!contentRange.isValid()) {
+ // Invalid content range
+ return null;
+ }
+ return contentRange;
+ }
+
+
+ /**
+ * @return <code>true</code> if the content range is valid, per RFC 9110
section 14.4
+ */
+ public boolean isValid() {
+ return start >= 0 && end >= start && length > end;
}
}
diff --git a/test/org/apache/catalina/servlets/TestDefaultServletPut.java
b/test/org/apache/catalina/servlets/TestDefaultServletPut.java
index 74262979c3..d19b95684d 100644
--- a/test/org/apache/catalina/servlets/TestDefaultServletPut.java
+++ b/test/org/apache/catalina/servlets/TestDefaultServletPut.java
@@ -53,6 +53,8 @@ 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 });
+ parameterSets.add(new Object[] {
+ "Content-Range: ByTeS 0-" + PATCH_LEN + "/" + START_LEN +
CRLF, Boolean.TRUE, END_TEXT, Boolean.TRUE });
// Full PUT
parameterSets.add(new Object[] {
"", null, PATCH_TEXT, Boolean.TRUE });
@@ -79,6 +81,8 @@ public class TestDefaultServletPut extends TomcatBaseTest {
"Content-Range: bytes 0-5/" + CRLF, Boolean.FALSE, START_TEXT,
Boolean.TRUE });
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 });
// 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 });
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 510719291c..3cbed98ab9 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -208,6 +208,11 @@
the requested ranges overlap. Based on pull request <pr>782</pr>
provided by Chenjp. (markt)
</fix>
+ <fix>
+ The default servlet now rejects partial PUT requests than contain
+ overlapping Content-Range values. Provided by Chenjp in pull request
+ <pr>778</pr>. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]