File tomcat-8.0.53-CVE-2019-17569.patch of Package tomcat.37363

Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/http11/AbstractHttp11Processor.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/http11/AbstractHttp11Processor.java
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/http11/AbstractHttp11Processor.java
@@ -19,6 +19,8 @@ package org.apache.coyote.http11;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -50,6 +52,7 @@ import org.apache.tomcat.util.buf.Messag
 import org.apache.tomcat.util.http.FastHttpDateFormat;
 import org.apache.tomcat.util.http.MimeHeaders;
 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;
@@ -1276,7 +1279,7 @@ public abstract class AbstractHttp11Proc
     /**
      * After reading the request headers, we have to setup the request filters.
      */
-    protected void prepareRequest() {
+    protected void prepareRequest() throws IOException{
 
         http11 = true;
         http09 = false;
@@ -1506,19 +1509,16 @@ public abstract class AbstractHttp11Proc
             transferEncodingValueMB = headers.getValue("transfer-encoding");
         }
         if (transferEncodingValueMB != null) {
-            String transferEncodingValue = transferEncodingValueMB.toString();
-            // Parse the comma separated list. "identity" codings are ignored
-            int startPos = 0;
-            int commaPos = transferEncodingValue.indexOf(',');
-            String encodingName = null;
-            while (commaPos != -1) {
-                encodingName = transferEncodingValue.substring(startPos, commaPos);
-                addInputFilter(inputFilters, encodingName);
-                startPos = commaPos + 1;
-                commaPos = transferEncodingValue.indexOf(',', startPos);
+            List<String> encodingNames = new ArrayList<String>();
+            if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
+                for (String encodingName : encodingNames) {
+                    // "identity" codings are ignored
+                    addInputFilter(inputFilters, encodingName);
+                }
+            } else {
+                // Invalid transfer encoding
+                badRequest("http11processor.request.invalidTransferEncoding");
             }
-            encodingName = transferEncodingValue.substring(startPos);
-            addInputFilter(inputFilters, encodingName);
         }
 
         // Parse content-length header
@@ -1554,6 +1554,13 @@ public abstract class AbstractHttp11Proc
         }
     }
 
+    private void badRequest(String errorKey) {
+        response.setStatus(400);
+        setErrorState(ErrorState.CLOSE_CLEAN, null);
+        if (getLog().isDebugEnabled()) {
+            getLog().debug(sm.getString(errorKey));
+        }
+    }
 
     /**
      * Connector implementation specific request preparation. Ideally, this will
Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/http11/LocalStrings.properties
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/http11/LocalStrings.properties
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/http11/LocalStrings.properties
@@ -18,7 +18,8 @@ http11processor.header.parse=Error parsi
 http11processor.neverused=This method should never be used
 http11processor.request.inconsistentHosts=The host specified in the request line is not consistent with the host header
 http11processor.request.invalidScheme=The HTTP request contained an absolute URI with an invalid scheme
-http11processor.request.invalidUri==The HTTP request contained an invalid URI
+http11processor.request.invalidTransferEncoding=The HTTP request contained an invalid Transfer-Encoding header
+http11processor.request.invalidUri=The HTTP request contained an invalid URI
 http11processor.request.invalidUserInfo=The HTTP request contained an absolute URI with an invalid userinfo
 http11processor.request.multipleHosts=The request contained multiple host headers
 http11processor.request.noHostHeader=The HTTP/1.1 request did not provide a host header
Index: apache-tomcat-8.0.53-src/java/org/apache/tomcat/util/http/parser/TokenList.java
===================================================================
--- /dev/null
+++ apache-tomcat-8.0.53-src/java/org/apache/tomcat/util/http/parser/TokenList.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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;
+
+public class TokenList {
+
+    private TokenList() {
+        // Utility class. Hide default constructor.
+    }
+
+
+    /**
+     * 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 collection The Collection (usually a list of a set) to which the
+     *                       parsed tokens should be added
+     *
+     * @return {@code} true if the header values were parsed cleanly, otherwise
+     *         {@code false} (e.g. if a non-token value was encountered)
+     *
+     * @throws IOException If an I/O error occurs reading the header
+     */
+    public static boolean parseTokenList(Enumeration<String> inputs, Collection<String> collection) throws IOException {
+        boolean result = true;
+        while (inputs.hasMoreElements()) {
+            String nextHeaderValue = inputs.nextElement();
+            if (nextHeaderValue != null) {
+                if (!TokenList.parseTokenList(new StringReader(nextHeaderValue), collection)) {
+                    result = false;
+                }
+            }
+        }
+        return 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 collection The Collection (usually a list of a set) to which the
+     *                       parsed tokens should be added
+     *
+     * @return {@code} true if the header was parsed cleanly, otherwise
+     *         {@code false} (e.g. if a non-token value was encountered)
+     *
+     * @throws IOException If an I/O error occurs reading the header
+     */
+    public static boolean parseTokenList(Reader input, Collection<String> collection) throws IOException {
+        boolean invalid = false;
+        boolean valid = false;
+
+        do {
+            String fieldName = HttpParser.readToken(input);
+            if (fieldName == null) {
+                // Invalid field-name, skip to the next one
+                invalid = true;
+                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
+                valid = true;
+                collection.add(fieldName.toLowerCase(Locale.ENGLISH));
+                break;
+            } else if (skipResult == SkipResult.FOUND) {
+                valid = true;
+                collection.add(fieldName.toLowerCase(Locale.ENGLISH));
+                continue;
+            } else {
+                // Not a token - ignore it
+                invalid = true;
+                HttpParser.skipUntil(input, 0, ',');
+                continue;
+            }
+        } while (true);
+
+        // Only return true if at least one valid token was read and no invalid
+        // entries were found
+        return valid && !invalid;
+    }
+}
openSUSE Build Service is sponsored by