This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new 7e9d514 EntityTag.parseEntityTag(): optimize comparison 7e9d514 is described below commit 7e9d514a733bfe5ccf43df2899d8f39ab852d3e2 Author: Sergey Ponomarev <stok...@gmail.com> 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 1392bb9..c3be79b 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -44,7 +44,6 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Set; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; @@ -2237,21 +2236,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(resource); - - // 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; } @@ -2318,29 +2320,24 @@ public class DefaultServlet extends HttpServlet { String headerValue = request.getHeader("If-None-Match"); if (headerValue != null) { - boolean conditionSatisfied = false; + boolean conditionSatisfied; String resourceETag = generateETag(resource); 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 9384b8d..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<>(); + 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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org