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

rmaucher pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 7774a01d9ccaf1d3d45b6061c5c9490403427801
Author: opencode <[email protected]>
AuthorDate: Wed Oct 7 16:48:49 2026 +0200

    Ignore malformed Accept-Encoding q-values in DefaultServlet precompressed 
handling
    
    Double.parseDouble() of the q-value in getBestPrecompressedResource()
    was unprotected, so a client header such as Accept-Encoding: br;q=abc
    triggered a NumberFormatException and the request failed with a 500
    whenever a precompressed variant of the requested resource existed.
    Skip a preference with an unparsable q-value instead, consistent with
    treating it as not expressed.
---
 .../apache/catalina/servlets/DefaultServlet.java   |  7 ++-
 .../catalina/servlets/TestDefaultServlet.java      | 65 ++++++++++++++++++++++
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java 
b/java/org/apache/catalina/servlets/DefaultServlet.java
index 4e9b38b7bc..5a30cf9514 100644
--- a/java/org/apache/catalina/servlets/DefaultServlet.java
+++ b/java/org/apache/catalina/servlets/DefaultServlet.java
@@ -1502,7 +1502,12 @@ public class DefaultServlet extends HttpServlet {
                     if (equalsIdx == -1) {
                         continue;
                     }
-                    quality = 
Double.parseDouble(preference.substring(equalsIdx + 1).trim());
+                    try {
+                        quality = 
Double.parseDouble(preference.substring(equalsIdx + 1).trim());
+                    } catch (NumberFormatException nfe) {
+                        // Invalid q-value: ignore this preference
+                        continue;
+                    }
                 }
                 if (quality >= bestResourceQuality) {
                     String encoding = preference;
diff --git a/test/org/apache/catalina/servlets/TestDefaultServlet.java 
b/test/org/apache/catalina/servlets/TestDefaultServlet.java
index 6f9701ce1b..8bc83645b8 100644
--- a/test/org/apache/catalina/servlets/TestDefaultServlet.java
+++ b/test/org/apache/catalina/servlets/TestDefaultServlet.java
@@ -381,6 +381,71 @@ public class TestDefaultServlet extends TomcatBaseTest {
         Assert.assertTrue(responseHeaders.contains("vary: accept-encoding"));
     }
 
+    /*
+     * Verify that a malformed q-value in Accept-Encoding does not fail the
+     * request and only causes the affected preference to be ignored.
+     */
+    @Test
+    public void testMalformedPrecompressedQValue() throws Exception {
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+
+        long gzSize = new File(appDir, "index.html.gz").length();
+        long indexSize = new File(appDir, "index.html").length();
+
+        // app dir is relative to server home
+        Context ctxt = tomcat.addContext("", appDir.getAbsolutePath());
+        Wrapper defaultServlet = Tomcat.addServlet(ctxt, "default",
+                DefaultServlet.class.getName());
+        defaultServlet.addInitParameter("precompressed", "br=.br,gzip=.gz");
+        defaultServlet.addInitParameter("fileEncoding", "ISO-8859-1");
+
+        ctxt.addServletMapping("/", "default");
+        ctxt.addMimeMapping("html", "text/html");
+
+        tomcat.start();
+
+        TestCompressedClient client = new TestCompressedClient(getPort());
+
+        client.reset();
+        // @formatter:off
+        client.setRequest(new String[] {
+                "GET /index.html HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Connection: Close" + CRLF +
+                    "Accept-Encoding: br;q=abc" + CRLF +
+                    CRLF
+                });
+        // @formatter:on
+        client.connect();
+        client.processRequest();
+        Assert.assertTrue(client.isResponse200());
+        List<String> responseHeaders = client.getResponseHeaders();
+        Assert.assertFalse(responseHeaders.contains("Content-Encoding"));
+        Assert.assertTrue(responseHeaders.contains("Content-Length: " + 
indexSize));
+        Assert.assertTrue(responseHeaders.contains("vary: accept-encoding"));
+
+        client.reset();
+        // @formatter:off
+        client.setRequest(new String[] {
+                "GET /index.html HTTP/1.1" + CRLF +
+                    "Host: localhost" + CRLF +
+                    "Connection: Close" + CRLF +
+                    "Accept-Encoding: br;q=abc,gzip" + CRLF +
+                    CRLF
+                });
+        // @formatter:on
+        client.connect();
+        client.processRequest();
+        Assert.assertTrue(client.isResponse200());
+        responseHeaders = client.getResponseHeaders();
+        Assert.assertTrue(responseHeaders.contains("Content-Encoding: gzip"));
+        Assert.assertTrue(responseHeaders.contains("Content-Length: " + 
gzSize));
+        Assert.assertTrue(responseHeaders.contains("vary: accept-encoding"));
+    }
+
     /*
      * Verify preferring of brotli in default configuration for actual Firefox 
and Chrome requests.
      */


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to