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 0c756e4 Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63829 0c756e4 is described below commit 0c756e4252cd1d3669fdb693990bc8da9820a615 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Oct 23 11:30:54 2019 +0200 Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63829 Improve the check of the Content-Encoding header when looking to see if Tomcat is serving pre-compressed content. Ensure that only a full token is matched and that the match is case insensitive. --- .../coyote/http11/AbstractHttp11Processor.java | 35 +++++++++++----------- .../apache/coyote/http11/LocalStrings.properties | 1 + .../apache/tomcat/util/http/parser/TokenList.java | 24 ++++++++++++++- webapps/docs/changelog.xml | 6 ++++ 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/java/org/apache/coyote/http11/AbstractHttp11Processor.java b/java/org/apache/coyote/http11/AbstractHttp11Processor.java index 37ecc9a..2064f93 100644 --- a/java/org/apache/coyote/http11/AbstractHttp11Processor.java +++ b/java/org/apache/coyote/http11/AbstractHttp11Processor.java @@ -19,7 +19,6 @@ package org.apache.coyote.http11; import java.io.IOException; import java.io.InterruptedIOException; import java.io.StringReader; -import java.util.Collection; import java.util.Enumeration; import java.util.HashSet; import java.util.List; @@ -611,10 +610,21 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> { // Check if content is not already compressed MessageBytes contentEncodingMB = response.getMimeHeaders().getValue("Content-Encoding"); - if ((contentEncodingMB != null) && - (contentEncodingMB.indexOf("gzip") != -1 || - contentEncodingMB.indexOf("br") != -1)) { - return false; + if (contentEncodingMB != null) { + // Content-Encoding values are ordered but order is not important + // for this check so use a Set rather than a List + Set<String> tokens = new HashSet<String>(); + try { + TokenList.parseTokenList(response.getMimeHeaders().values("Content-Encoding"), tokens); + } catch (IOException e) { + // Because we are using StringReader, any exception here is a + // Tomcat bug. + getLog().warn(sm.getString("http11Processor.contentEncodingParseFail"), e); + return false; + } + if (tokens.contains("gzip") || tokens.contains("br")) { + return false; + } } // If force mode, always compress (test purposes only) @@ -1342,7 +1352,7 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> { MessageBytes connectionValueMB = headers.getValue(Constants.CONNECTION); if (connectionValueMB != null && !connectionValueMB.isNull()) { Set<String> tokens = new HashSet<String>(); - parseConnectionTokens(headers, tokens); + TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens); if (tokens.contains(Constants.CLOSE)) { keepAlive = false; } else if (tokens.contains(Constants.KEEPALIVE)) { @@ -1758,22 +1768,11 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> { } Set<String> tokens = new HashSet<String>(); - parseConnectionTokens(headers, tokens); + TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens); return tokens.contains(token); } - private static void parseConnectionTokens(MimeHeaders headers, Collection<String> tokens) throws IOException { - Enumeration<String> values = headers.values(Constants.CONNECTION); - while (values.hasMoreElements()) { - String nextHeaderValue = values.nextElement(); - if (nextHeaderValue != null) { - TokenList.parseTokenList(new StringReader(nextHeaderValue), tokens); - } - } - } - - protected abstract boolean prepareSendfile(OutputFilter[] outputFilters); diff --git a/java/org/apache/coyote/http11/LocalStrings.properties b/java/org/apache/coyote/http11/LocalStrings.properties index 7f3eb7e..ad41849 100644 --- a/java/org/apache/coyote/http11/LocalStrings.properties +++ b/java/org/apache/coyote/http11/LocalStrings.properties @@ -16,6 +16,7 @@ http11Processor.upgrade=An internal error has occurred as upgraded connections should only be processed by the dedicated upgrade processor implementations http11processor.comet.notsupported=The Comet protocol is not supported by this connector +http11Processor.contentEncodingParseFail=Failed to parse Content-Encoding header when chekcing to see if compression was already in use http11processor.fallToDebug=\n\ \ Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level. http11processor.filter.error=Error intializing filter [{0}] diff --git a/java/org/apache/tomcat/util/http/parser/TokenList.java b/java/org/apache/tomcat/util/http/parser/TokenList.java index 3837b51..7ba886c 100644 --- a/java/org/apache/tomcat/util/http/parser/TokenList.java +++ b/java/org/apache/tomcat/util/http/parser/TokenList.java @@ -18,7 +18,9 @@ package org.apache.tomcat.util.http.parser; import java.io.IOException; import java.io.Reader; +import java.io.StringReader; import java.util.Collection; +import java.util.Enumeration; import java.util.Locale; import org.apache.tomcat.util.http.parser.HttpParser.SkipResult; @@ -31,12 +33,32 @@ public class TokenList { /** + * Parses an enumeration of header values of the form 1#token, forcing all + * parsed values to lower case. + * + * @param inputs The headers to parse + * @param result The Collection (usually a list of a set) to which the + * parsed tokens should be added + * + * @throws IOException If an I/O error occurs reading the header + */ + public static void parseTokenList(Enumeration<String> inputs, Collection<String> result) throws IOException { + while (inputs.hasMoreElements()) { + String nextHeaderValue = inputs.nextElement(); + if (nextHeaderValue != null) { + TokenList.parseTokenList(new StringReader(nextHeaderValue), result); + } + } + } + + + /** * 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 tokens should be added * * @throws IOException If an I/O error occurs reading the header */ diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index a6a0734..16c7cb4 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -92,6 +92,12 @@ <code>Connection</code> HTTP headers looking for a specific token, be stricter in ensuring that the exact token is present. (markt) </fix> + <fix> + <bug>63829</bug>: Improve the check of the <code>Content-Encoding</code> + header when looking to see if Tomcat is serving pre-compressed content. + Ensure that only a full token is matched and that the match is case + insensitive. (markt) + </fix> </changelog> </subsection> <subsection name="Other"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org