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 <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 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: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to