This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/7.0.x by this push:
new de55a69 EntityTag.parseEntityTag(): optimize comparison
de55a69 is described below
commit de55a696cdaab6079ae90d2ceeacd93b784e379d
Author: Sergey Ponomarev <[email protected]>
AuthorDate: Wed Aug 12 17:13:44 2020 +0300
EntityTag.parseEntityTag(): optimize comparison
Instead of creating a HashSet we can make in-place matching.
Note that even if first ETag matched we still checking the whole header
for correctness
---
.../apache/catalina/servlets/DefaultServlet.java | 53 ++++++++++------------
.../apache/tomcat/util/http/parser/EntityTag.java | 32 ++++++++-----
2 files changed, 46 insertions(+), 39 deletions(-)
diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java
b/java/org/apache/catalina/servlets/DefaultServlet.java
index 04db1b5..c03303d 100644
--- a/java/org/apache/catalina/servlets/DefaultServlet.java
+++ b/java/org/apache/catalina/servlets/DefaultServlet.java
@@ -35,7 +35,6 @@ import java.security.AccessController;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
-import java.util.Set;
import java.util.StringTokenizer;
import javax.naming.InitialContext;
@@ -1917,21 +1916,24 @@ public class DefaultServlet extends HttpServlet {
String headerValue = request.getHeader("If-Match");
if (headerValue != null) {
- boolean conditionSatisfied = false;
+ boolean conditionSatisfied;
if (!headerValue.equals("*")) {
String resourceETag = generateETag(resourceAttributes);
-
- // RFC 7232 requires strong comparison for If-Match headers
- Set<String> headerETags = EntityTag.parseEntityTag(new
StringReader(headerValue), false);
- if (headerETags == null) {
- if (debug > 10) {
- log("DefaultServlet.checkIfMatch: Invalid header
value [" + headerValue + "]");
+ if (resourceETag == null) {
+ conditionSatisfied = false;
+ } else {
+ // RFC 7232 requires strong comparison for If-Match headers
+ Boolean matched = EntityTag.compareEntityTag(new
StringReader(headerValue), false, resourceETag);
+ if (matched == null) {
+ if (debug > 10) {
+ log("DefaultServlet.checkIfMatch: Invalid header
value [" + headerValue + "]");
+ }
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return false;
}
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return false;
+ conditionSatisfied = matched.booleanValue();
}
- conditionSatisfied = headerETags.contains(resourceETag);
} else {
conditionSatisfied = true;
}
@@ -1998,29 +2000,24 @@ public class DefaultServlet extends HttpServlet {
String headerValue = request.getHeader("If-None-Match");
if (headerValue != null) {
- boolean conditionSatisfied = false;
+ boolean conditionSatisfied;
String resourceETag = generateETag(resourceAttributes);
if (!headerValue.equals("*")) {
-
- // RFC 7232 requires weak comparison for If-None-Match headers
- // This is done by removing any weak markers before comparison
- String comparisonETag;
- if (resourceETag.startsWith("W/")) {
- comparisonETag = resourceETag.substring(2);
+ if (resourceETag == null) {
+ conditionSatisfied = false;
} else {
- comparisonETag = resourceETag;
- }
-
- Set<String> headerETags = EntityTag.parseEntityTag(new
StringReader(headerValue), true);
- if (headerETags == null) {
- if (debug > 10) {
- log("DefaultServlet.checkIfNoneMatch: Invalid header
value [" + headerValue + "]");
+ // RFC 7232 requires weak comparison for If-None-Match
headers
+ Boolean matched = EntityTag.compareEntityTag(new
StringReader(headerValue), true, resourceETag);
+ if (matched == null) {
+ if (debug > 10) {
+ log("DefaultServlet.checkIfNoneMatch: Invalid
header value [" + headerValue + "]");
+ }
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return false;
}
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return false;
+ conditionSatisfied = matched.booleanValue();
}
- conditionSatisfied = headerETags.contains(comparisonETag);
} else {
conditionSatisfied = true;
}
diff --git a/java/org/apache/tomcat/util/http/parser/EntityTag.java
b/java/org/apache/tomcat/util/http/parser/EntityTag.java
index 2213075..b2cfaba 100644
--- a/java/org/apache/tomcat/util/http/parser/EntityTag.java
+++ b/java/org/apache/tomcat/util/http/parser/EntityTag.java
@@ -18,26 +18,34 @@ package org.apache.tomcat.util.http.parser;
import java.io.IOException;
import java.io.StringReader;
-import java.util.HashSet;
-import java.util.Set;
public class EntityTag {
/**
* Parse the given input as (per RFC 7232) 1#entity-tag.
+ * Compare an ETag header with a resource ETag as described in RFC 7232
+ * section 2.3.2.
*
- * @param input The input to parse
- * @param includeWeak Should weak tags be included in the set of returned
- * values?
+ * @param input The input to parse
+ * @param compareWeak Use weak comparison e.g. match "etag" with W/"etag"
+ * @param resourceETag Resource's ETag
*
- * @return The set of parsed entity tags or {@code null} if the header is
- * invalid
+ * @return true if ETag matched or {@code null} if the header is invalid
*
* @throws IOException If an I/O occurs during the parsing
*/
- public static Set<String> parseEntityTag(StringReader input, boolean
includeWeak) throws IOException {
+ public static Boolean compareEntityTag(StringReader input, boolean
compareWeak, String resourceETag)
+ throws IOException {
+ // The resourceETag may be weak so to do weak comparison remove /W
+ // before comparison
+ String comparisonETag;
+ if (compareWeak && resourceETag.startsWith("W/")) {
+ comparisonETag = resourceETag.substring(2);
+ } else {
+ comparisonETag = resourceETag;
+ }
- HashSet<String> result = new HashSet<String>();
+ Boolean result = Boolean.FALSE;
while (true) {
boolean strong = false;
@@ -63,8 +71,10 @@ public class EntityTag {
return null;
}
- if (strong || includeWeak) {
- result.add(value);
+ if (strong || compareWeak) {
+ if (comparisonETag.equals(value)) {
+ result = Boolean.TRUE;
+ }
}
HttpParser.skipLws(input);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]