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 8d67f71613b24ef16ad4205e6294a17774481f8b
Author: opencode <[email protected]>
AuthorDate: Wed Oct 14 19:15:09 2026 +0200

    Replace obs-fold with a single SP when parsing headers
    
    The header parser's line folding (obs-fold) handling peeked the first
    byte of the continuation line and copied that raw byte into the
    compacted header value. Since an obs-fold may start with HTAB, a TAB
    could end up in the value, e.g. a header sent as "X: abcd CRLF TAB
    efgh" was stored as "abcd\tefgh".
    
    RFC 9112 section 5.2 requires a server that receives an obs-fold to
    either reject the message or replace each obs-fold with one or more SP
    octets. The parser now always inserts a single space at the fold point
    instead of copying the peeked byte. Whitespace beyond the first byte of
    the continuation line was and is skipped by the value-start state, so
    the stored value for the HTAB case changes from a TAB to a space while
    the SP case is unchanged. This also removes a divergence between what
    Tomcat sees and what a spec-compliant intermediary would forward for
    the same message.
    
    The existing test for folded headers (bz 48839) asserted the legacy
    behaviour with a tab in the value and was updated to expect the single
    space mandated by the specification. A new test pins the SP
    continuation case.
---
 .../tomcat/util/http/parser/HttpHeaderParser.java  |  7 ++-
 .../coyote/http11/TestHttp11InputBuffer.java       | 69 +++++++++++++++++++++-
 2 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java 
b/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java
index 2e7be33c3e..0eb653909b 100644
--- a/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java
+++ b/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java
@@ -255,9 +255,10 @@ public class HttpHeaderParser {
                     headerParsePos = HeaderParsePosition.HEADER_START;
                     break;
                 } else {
-                    // Copying one extra space in the buffer (since there must
-                    // be at least one space inserted between the lines)
-                    source.getHeaderByteBuffer().put(headerData.realPos, peek);
+                    // Replace the line folding with a single space as required
+                    // by RFC 9112 section 5.2. Any further whitespace at the
+                    // start of the continuation line is skipped below.
+                    source.getHeaderByteBuffer().put(headerData.realPos, SP);
                     headerData.realPos++;
                     headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
                 }
diff --git a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java 
b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
index e33a30cd38..ff389db779 100644
--- a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
+++ b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
@@ -103,7 +103,9 @@ public class TestHttp11InputBuffer extends TomcatBaseTest {
             if (getResponseBody() == null) {
                 return false;
             }
-            if (!getResponseBody().contains("abcd\tefgh")) {
+            // The line folding (CRLF + HTAB) is replaced with a single SP as
+            // required by RFC 9110 section 5.2
+            if (!getResponseBody().contains("abcd efgh")) {
                 return false;
             }
             return true;
@@ -133,6 +135,71 @@ public class TestHttp11InputBuffer extends TomcatBaseTest {
     }
 
 
+    /**
+     * Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=48839 with 
a space rather than a tab starting the
+     * continuation line. Both fold forms must result in a single space in the 
parsed value (RFC 9112 section 5.2).
+     */
+    @Test
+    public void testObsFoldWithSpaceContinuation() {
+
+        ObsFoldClient client = new ObsFoldClient();
+
+        client.doRequest();
+        Assert.assertTrue(client.isResponse200());
+        Assert.assertTrue(client.getResponseBody(), 
client.getResponseBody().contains("abcd efgh"));
+    }
+
+
+    /**
+     * Obs-fold test client. Uses a SP continuation line.
+     */
+    private class ObsFoldClient extends SimpleHttpClient {
+
+        private Exception doRequest() {
+
+            Tomcat tomcat = getTomcatInstance();
+
+            Context root = tomcat.addContext("", TEMP_DIR);
+            Tomcat.addServlet(root, "ObsFold", new Bug48839Servlet());
+            root.addServletMapping("/test", "ObsFold");
+
+            try {
+                tomcat.start();
+                setPort(tomcat.getConnector().getLocalPort());
+
+                // Open connection
+                connect();
+
+                String[] request = new String[1];
+                // @formatter:off
+                request[0] =
+                        "GET http://localhost:8080/test HTTP/1.1" + CRLF +
+                        "Host: localhost:8080" + CRLF +
+                        "X-Bug48839: abcd" + CRLF +
+                        " efgh" + CRLF +
+                        "Connection: close" + CRLF +
+                        CRLF;
+                // @formatter:on
+
+                setRequest(request);
+                processRequest(); // blocks until response has been read
+
+                // Close the connection
+                disconnect();
+            } catch (Exception e) {
+                return e;
+            }
+            return null;
+        }
+
+        @Override
+        public boolean isResponseBodyOK() {
+            return getResponseBody() != null && 
getResponseBody().contains("abcd efgh");
+        }
+
+    }
+
+
     @Test
     public void testBug51557Valid() {
 


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

Reply via email to