You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/10/17 17:49:55 UTC

[tomcat] branch 7.0.x updated (af963c6 -> 6a63a68)

This is an automated email from the ASF dual-hosted git repository.

markt pushed a change to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git.


    from af963c6  Fix typo
     new 463b5ca  Refactor Vary parser to the more generic TokenList parser
     new 7ff5a51  Add a case sensitive / insensitive option to the token list parser
     new 70f264a  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63824
     new 6d53968  Simplify on the grounds all tokens of interest are case-insensitive
     new 6a63a68  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63825

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../coyote/http11/AbstractHttp11Processor.java     | 26 ++++++++++------
 java/org/apache/tomcat/util/http/ResponseUtil.java |  4 +--
 .../util/http/parser/{Vary.java => TokenList.java} | 21 +++++++++----
 java/org/apache/tomcat/util/http/parser/Vary.java  | 36 +++-------------------
 .../parser/{TestVary.java => TestTokenList.java}   |  9 +++++-
 webapps/docs/changelog.xml                         |  5 +++
 6 files changed, 52 insertions(+), 49 deletions(-)
 copy java/org/apache/tomcat/util/http/parser/{Vary.java => TokenList.java} (75%)
 rename test/org/apache/tomcat/util/http/parser/{TestVary.java => TestTokenList.java} (93%)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 04/05: Simplify on the grounds all tokens of interest are case-insensitive

Posted by ma...@apache.org.
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

commit 6d5396843e252418603ae2c97b5b501bf8f5da55
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 17 17:39:35 2019 +0100

    Simplify on the grounds all tokens of interest are case-insensitive
---
 .../apache/tomcat/util/http/parser/TokenList.java  | 31 ++--------------------
 1 file changed, 2 insertions(+), 29 deletions(-)

diff --git a/java/org/apache/tomcat/util/http/parser/TokenList.java b/java/org/apache/tomcat/util/http/parser/TokenList.java
index 7160623..3837b51 100644
--- a/java/org/apache/tomcat/util/http/parser/TokenList.java
+++ b/java/org/apache/tomcat/util/http/parser/TokenList.java
@@ -41,25 +41,6 @@ public class TokenList {
      * @throws IOException If an I/O error occurs reading the header
      */
     public static void parseTokenList(Reader input, Collection<String> result) throws IOException {
-        parseTokenList(input, true, result);
-    }
-
-
-    /**
-     * Parses a header of the form 1#token.
-     *
-     * @param input          The header to parse
-     * @param forceLowerCase Should parsed tokens be forced to lower case? This
-     *                           is intended for headers where the values are
-     *                           case-insensitive
-     * @param result         The Collection (usually a list of a set) to which
-     *                           the parsed token should be added
-     *
-     * @throws IOException If an I/O error occurs reading the header
-     */
-    public static void parseTokenList(Reader input, boolean forceLowerCase, Collection<String> result)
-            throws IOException {
-
         do {
             String fieldName = HttpParser.readToken(input);
             if (fieldName == null) {
@@ -76,18 +57,10 @@ public class TokenList {
             SkipResult skipResult = HttpParser.skipConstant(input, ",");
             if (skipResult == SkipResult.EOF) {
                 // EOF
-                if (forceLowerCase) {
-                    result.add(fieldName.toLowerCase(Locale.ENGLISH));
-                } else {
-                    result.add(fieldName);
-                }
+                result.add(fieldName.toLowerCase(Locale.ENGLISH));
                 break;
             } else if (skipResult == SkipResult.FOUND) {
-                if (forceLowerCase) {
-                    result.add(fieldName.toLowerCase(Locale.ENGLISH));
-                } else {
-                    result.add(fieldName);
-                }
+                result.add(fieldName.toLowerCase(Locale.ENGLISH));
                 continue;
             } else {
                 // Not a token - ignore it


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 02/05: Add a case sensitive / insensitive option to the token list parser

Posted by ma...@apache.org.
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

commit 7ff5a51b6655591ac762d6a65daa98992c9b05d6
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Oct 16 17:45:25 2019 +0100

    Add a case sensitive / insensitive option to the token list parser
---
 .../apache/tomcat/util/http/parser/TokenList.java  | 35 +++++++++++++++++++---
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/tomcat/util/http/parser/TokenList.java b/java/org/apache/tomcat/util/http/parser/TokenList.java
index facd2ad..7160623 100644
--- a/java/org/apache/tomcat/util/http/parser/TokenList.java
+++ b/java/org/apache/tomcat/util/http/parser/TokenList.java
@@ -31,15 +31,34 @@ public class TokenList {
 
 
     /**
-     * Parses a header of the form 1#token.
+     * Parses a header of the form 1#token, forcing all parsed values to lower
+     * case. This is typically used when header values are case-insensitive.
      *
      * @param input  The header to parse
      * @param result The Collection (usually a list of a set) to which the
-     *                  parsed token should be added
+     *                   parsed token should be added
      *
      * @throws IOException If an I/O error occurs reading the header
      */
     public static void parseTokenList(Reader input, Collection<String> result) throws IOException {
+        parseTokenList(input, true, result);
+    }
+
+
+    /**
+     * Parses a header of the form 1#token.
+     *
+     * @param input          The header to parse
+     * @param forceLowerCase Should parsed tokens be forced to lower case? This
+     *                           is intended for headers where the values are
+     *                           case-insensitive
+     * @param result         The Collection (usually a list of a set) to which
+     *                           the parsed token should be added
+     *
+     * @throws IOException If an I/O error occurs reading the header
+     */
+    public static void parseTokenList(Reader input, boolean forceLowerCase, Collection<String> result)
+            throws IOException {
 
         do {
             String fieldName = HttpParser.readToken(input);
@@ -57,10 +76,18 @@ public class TokenList {
             SkipResult skipResult = HttpParser.skipConstant(input, ",");
             if (skipResult == SkipResult.EOF) {
                 // EOF
-                result.add(fieldName.toLowerCase(Locale.ENGLISH));
+                if (forceLowerCase) {
+                    result.add(fieldName.toLowerCase(Locale.ENGLISH));
+                } else {
+                    result.add(fieldName);
+                }
                 break;
             } else if (skipResult == SkipResult.FOUND) {
-                result.add(fieldName.toLowerCase(Locale.ENGLISH));
+                if (forceLowerCase) {
+                    result.add(fieldName.toLowerCase(Locale.ENGLISH));
+                } else {
+                    result.add(fieldName);
+                }
                 continue;
             } else {
                 // Not a token - ignore it


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 03/05: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63824

Posted by ma...@apache.org.
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

commit 70f264a2d6745bfc8372324b75061d0355851d47
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 17 15:01:45 2019 +0100

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63824
    
    Correctly parse the Connection header when checking to see if the
    "close" option is present.
---
 .../coyote/http11/AbstractHttp11Processor.java     | 30 ++++++++++++++++------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/java/org/apache/coyote/http11/AbstractHttp11Processor.java b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
index 3fddabf..4d93cca 100644
--- a/java/org/apache/coyote/http11/AbstractHttp11Processor.java
+++ b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.io.StringReader;
 import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -53,6 +54,7 @@ import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.http.ResponseUtil;
 import org.apache.tomcat.util.http.parser.AcceptEncoding;
 import org.apache.tomcat.util.http.parser.HttpParser;
+import org.apache.tomcat.util.http.parser.TokenList;
 import org.apache.tomcat.util.log.UserDataHelper;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
@@ -1590,7 +1592,7 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
      * When committing the response, we have to validate the set of headers, as
      * well as setup the response filters.
      */
-    private void prepareResponse() {
+    private void prepareResponse() throws IOException {
 
         boolean entityBody = true;
         contentDelimitation = false;
@@ -1664,7 +1666,7 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
         }
 
         long contentLength = response.getContentLengthLong();
-        boolean connectionClosePresent = false;
+        boolean connectionClosePresent = isConnectionClose(headers);
         if (contentLength != -1) {
             headers.setValue("Content-Length").setLong(contentLength);
             getOutputBuffer().addActiveFilter
@@ -1673,10 +1675,8 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
         } else {
             // If the response code supports an entity body and we're on
             // HTTP 1.1 then we chunk unless we have a Connection: close header
-            connectionClosePresent = isConnectionClose(headers);
-            if (entityBody && http11 && !connectionClosePresent) {
-                getOutputBuffer().addActiveFilter
-                    (outputFilters[Constants.CHUNKED_FILTER]);
+            if (http11 && entityBody && !connectionClosePresent) {
+                getOutputBuffer().addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
                 headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
             } else {
@@ -1746,14 +1746,28 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
 
     }
 
-    private boolean isConnectionClose(MimeHeaders headers) {
+    private boolean isConnectionClose(MimeHeaders headers) throws IOException {
         MessageBytes connection = headers.getValue(Constants.CONNECTION);
         if (connection == null) {
             return false;
         }
-        return connection.equals(Constants.CLOSE);
+
+        Enumeration<String> values = headers.values(Constants.CONNECTION);
+        Set<String> result = null;
+        while (values.hasMoreElements()) {
+            if (result == null) {
+                result = new HashSet<String>();
+            }
+            TokenList.parseTokenList(new StringReader(values.nextElement()), result);
+        }
+
+        if (result == null) {
+            return false;
+        }
+        return result.contains(Constants.CLOSE);
     }
 
+
     protected abstract boolean prepareSendfile(OutputFilter[] outputFilters);
 
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 05/05: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63825

Posted by ma...@apache.org.
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

commit 6a63a680de6a12bbf27ccf0b3297ba62da4ff3ee
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 17 18:49:33 2019 +0100

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63825
    
    The expect header has a single defined value "100-continue" so look for
    the exact value rather than a value that starts with "100-continue"
---
 .../apache/coyote/http11/AbstractHttp11Processor.java    | 16 +++++-----------
 webapps/docs/changelog.xml                               |  5 +++++
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/java/org/apache/coyote/http11/AbstractHttp11Processor.java b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
index 4d93cca..4bd7b3f 100644
--- a/java/org/apache/coyote/http11/AbstractHttp11Processor.java
+++ b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
@@ -1349,7 +1349,7 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
         if (http11) {
             MessageBytes expectMB = headers.getValue("expect");
             if (expectMB != null && !expectMB.isNull()) {
-                if (expectMB.indexOfIgnoreCase("100-continue", 0) != -1) {
+                if (expectMB.toString().trim().equalsIgnoreCase("100-continue")) {
                     getInputBuffer().setSwallowInput(false);
                     expectation = true;
                 } else {
@@ -1666,7 +1666,7 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
         }
 
         long contentLength = response.getContentLengthLong();
-        boolean connectionClosePresent = isConnectionClose(headers);
+        boolean connectionClosePresent = isConnectionToken(headers, Constants.CLOSE);
         if (contentLength != -1) {
             headers.setValue("Content-Length").setLong(contentLength);
             getOutputBuffer().addActiveFilter
@@ -1746,25 +1746,19 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
 
     }
 
-    private boolean isConnectionClose(MimeHeaders headers) throws IOException {
+    private static boolean isConnectionToken(MimeHeaders headers, String token) throws IOException {
         MessageBytes connection = headers.getValue(Constants.CONNECTION);
         if (connection == null) {
             return false;
         }
 
         Enumeration<String> values = headers.values(Constants.CONNECTION);
-        Set<String> result = null;
+        Set<String> result = new HashSet<String>();
         while (values.hasMoreElements()) {
-            if (result == null) {
-                result = new HashSet<String>();
-            }
             TokenList.parseTokenList(new StringReader(values.nextElement()), result);
         }
 
-        if (result == null) {
-            return false;
-        }
-        return result.contains(Constants.CLOSE);
+        return result.contains(token);
     }
 
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a48d4bd..9d45831 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -87,6 +87,11 @@
         that started asynchronous processing has completed processing the
         current request/response. (markt)
       </fix>
+      <fix>
+        <bug>63825</bug>: When processing the <code>Expect</code> and
+        <code>Connection</code> HTTP headers looking for a specific token, be
+        stricter in ensuring that the exact token is present. (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 01/05: Refactor Vary parser to the more generic TokenList parser

Posted by ma...@apache.org.
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

commit 463b5caab72a58eba93844fe0853a0e909936094
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Oct 16 17:38:53 2019 +0100

    Refactor Vary parser to the more generic TokenList parser
---
 java/org/apache/tomcat/util/http/ResponseUtil.java |  4 +--
 .../util/http/parser/{Vary.java => TokenList.java} | 19 +++++++++---
 java/org/apache/tomcat/util/http/parser/Vary.java  | 36 +++-------------------
 .../parser/{TestVary.java => TestTokenList.java}   |  9 +++++-
 4 files changed, 29 insertions(+), 39 deletions(-)

diff --git a/java/org/apache/tomcat/util/http/ResponseUtil.java b/java/org/apache/tomcat/util/http/ResponseUtil.java
index 330cb11..1c40d3b 100644
--- a/java/org/apache/tomcat/util/http/ResponseUtil.java
+++ b/java/org/apache/tomcat/util/http/ResponseUtil.java
@@ -27,7 +27,7 @@ import java.util.Set;
 
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.tomcat.util.http.parser.Vary;
+import org.apache.tomcat.util.http.parser.TokenList;
 
 public class ResponseUtil {
 
@@ -81,7 +81,7 @@ public class ResponseUtil {
         for (String varyHeader : varyHeaders) {
             StringReader input = new StringReader(varyHeader);
             try {
-                Vary.parseVary(input, fieldNames);
+                TokenList.parseTokenList(input, fieldNames);
             } catch (IOException ioe) {
                 // Should never happen
             }
diff --git a/java/org/apache/tomcat/util/http/parser/Vary.java b/java/org/apache/tomcat/util/http/parser/TokenList.java
similarity index 79%
copy from java/org/apache/tomcat/util/http/parser/Vary.java
copy to java/org/apache/tomcat/util/http/parser/TokenList.java
index 16c65ed..facd2ad 100644
--- a/java/org/apache/tomcat/util/http/parser/Vary.java
+++ b/java/org/apache/tomcat/util/http/parser/TokenList.java
@@ -17,20 +17,29 @@
 package org.apache.tomcat.util.http.parser;
 
 import java.io.IOException;
-import java.io.StringReader;
+import java.io.Reader;
+import java.util.Collection;
 import java.util.Locale;
-import java.util.Set;
 
 import org.apache.tomcat.util.http.parser.HttpParser.SkipResult;
 
-public class Vary {
+public class TokenList {
 
-    private Vary() {
+    private TokenList() {
         // Utility class. Hide default constructor.
     }
 
 
-    public static void parseVary(StringReader input, Set<String> result) throws IOException {
+    /**
+     * Parses a header of the form 1#token.
+     *
+     * @param input  The header to parse
+     * @param result The Collection (usually a list of a set) to which the
+     *                  parsed token should be added
+     *
+     * @throws IOException If an I/O error occurs reading the header
+     */
+    public static void parseTokenList(Reader input, Collection<String> result) throws IOException {
 
         do {
             String fieldName = HttpParser.readToken(input);
diff --git a/java/org/apache/tomcat/util/http/parser/Vary.java b/java/org/apache/tomcat/util/http/parser/Vary.java
index 16c65ed..e064620 100644
--- a/java/org/apache/tomcat/util/http/parser/Vary.java
+++ b/java/org/apache/tomcat/util/http/parser/Vary.java
@@ -18,11 +18,12 @@ package org.apache.tomcat.util.http.parser;
 
 import java.io.IOException;
 import java.io.StringReader;
-import java.util.Locale;
 import java.util.Set;
 
-import org.apache.tomcat.util.http.parser.HttpParser.SkipResult;
-
+/**
+ * @deprecated  Use {@link TokenList}.
+ */
+@Deprecated
 public class Vary {
 
     private Vary() {
@@ -31,33 +32,6 @@ public class Vary {
 
 
     public static void parseVary(StringReader input, Set<String> result) throws IOException {
-
-        do {
-            String fieldName = HttpParser.readToken(input);
-            if (fieldName == null) {
-                // Invalid field-name, skip to the next one
-                HttpParser.skipUntil(input, 0, ',');
-                continue;
-            }
-
-            if (fieldName.length() == 0) {
-                // No more data to read
-                break;
-            }
-
-            SkipResult skipResult = HttpParser.skipConstant(input, ",");
-            if (skipResult == SkipResult.EOF) {
-                // EOF
-                result.add(fieldName.toLowerCase(Locale.ENGLISH));
-                break;
-            } else if (skipResult == SkipResult.FOUND) {
-                result.add(fieldName.toLowerCase(Locale.ENGLISH));
-                continue;
-            } else {
-                // Not a token - ignore it
-                HttpParser.skipUntil(input, 0, ',');
-                continue;
-            }
-        } while (true);
+        TokenList.parseTokenList(input, result);
     }
 }
diff --git a/test/org/apache/tomcat/util/http/parser/TestVary.java b/test/org/apache/tomcat/util/http/parser/TestTokenList.java
similarity index 93%
rename from test/org/apache/tomcat/util/http/parser/TestVary.java
rename to test/org/apache/tomcat/util/http/parser/TestTokenList.java
index fc3a1a9..74053bb 100644
--- a/test/org/apache/tomcat/util/http/parser/TestVary.java
+++ b/test/org/apache/tomcat/util/http/parser/TestTokenList.java
@@ -25,7 +25,7 @@ import java.util.Set;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class TestVary {
+public class TestTokenList {
 
     @Test
     public void testAll() throws IOException {
@@ -127,10 +127,17 @@ public class TestVary {
     }
 
 
+    @SuppressWarnings("deprecation")
     private void doTestVary(String input, Set<String> expected) throws IOException {
         StringReader reader = new StringReader(input);
         Set<String> result = new HashSet<String>();
         Vary.parseVary(reader, result);
         Assert.assertEquals(expected, result);
+
+        // Can't use reset(). Parser uses marks.
+        reader = new StringReader(input);
+        result.clear();
+        TokenList.parseTokenList(reader, result);
+        Assert.assertEquals(expected, result);
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org