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

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


The following commit(s) were added to refs/heads/11.0.x by this push:
     new 2cb06c34f6 Fix issues found by Copilot reviewing the chunked extension 
validation
2cb06c34f6 is described below

commit 2cb06c34f661ca42f7570bbcc21e99806184bcc5
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Mar 11 16:15:21 2026 +0000

    Fix issues found by Copilot reviewing the chunked extension validation
    
    Name only extensions weren't handled
    Non-blocking reads that ended after CR and before LF then failed
    Exceptions were inconsistent
---
 java/org/apache/coyote/http11/filters/ChunkedInputFilter.java  | 10 +++++++---
 java/org/apache/tomcat/util/http/parser/ChunkExtension.java    |  4 ++++
 test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java   |  2 +-
 .../org/apache/tomcat/util/http/parser/TestChunkExtension.java | 10 ++++++++++
 4 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 
b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
index 62a7251ef9..dde98005da 100644
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -359,13 +359,17 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
             byte chr = readChunk.get(readChunk.position());
 
             if (extensionState != null) {
-                extensionState = ChunkExtension.parse(chr, extensionState);
+                try {
+                    extensionState = ChunkExtension.parse(chr, extensionState);
+                } catch (IOException ioe) {
+                    
throwBadRequestException(sm.getString("chunkedInputFilter.invalidHeader"));
+                }
                 if (extensionState == State.CR) {
+                    extensionState = null;
                     if (!parseCRLF()) {
                         return false;
                     }
                     eol = true;
-                    extensionState = null;
                 } else {
                     // Check the size
                     long extSize = extensionSize.incrementAndGet();
@@ -444,11 +448,11 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
                     return false;
                 }
                 if (extensionState == State.CR) {
+                    extensionState = null;
                     if (!skipCRLF()) {
                         return false;
                     }
                     eol = true;
-                    extensionState = null;
                 } else {
                     // Check the size
                     long extSize = extensionSize.incrementAndGet();
diff --git a/java/org/apache/tomcat/util/http/parser/ChunkExtension.java 
b/java/org/apache/tomcat/util/http/parser/ChunkExtension.java
index 136956b56f..9860f8b725 100644
--- a/java/org/apache/tomcat/util/http/parser/ChunkExtension.java
+++ b/java/org/apache/tomcat/util/http/parser/ChunkExtension.java
@@ -45,6 +45,8 @@ public class ChunkExtension {
                     return State.POST_NAME;
                 } else if (HttpParser.isToken(c)) {
                     return State.NAME;
+                } else if (c == ';') {
+                    return State.PRE_NAME;
                 } else if (c == '=') {
                     return State.EQUALS;
                 } else if (c == '\r') {
@@ -54,6 +56,8 @@ public class ChunkExtension {
             case POST_NAME:
                 if (HttpParser.isWhiteSpace(c)) {
                     return State.POST_NAME;
+                } else if (c == ';') {
+                    return State.PRE_NAME;
                 } else if (c == '=') {
                     return State.EQUALS;
                 } else if (c == '\r') {
diff --git a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java 
b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
index 84cdefa868..bdab74d44a 100644
--- a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
+++ b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
@@ -599,7 +599,7 @@ public class TestNonBlockingAPI extends TomcatBaseTest {
     public void testNonBlockingReadChunkedSplitMaximum() throws Exception {
         // @formatter:off
         String requestBody = new String(
-                "14" + CRLF +
+                "14;a=b;c" + CRLF +
                 "012345678901FINISHED" + CRLF +
                 "0" + CRLF +
                 TRAILER_HEADER_NAME + ": " + TRAILER_HEADER_VALUE + CRLF +
diff --git a/test/org/apache/tomcat/util/http/parser/TestChunkExtension.java 
b/test/org/apache/tomcat/util/http/parser/TestChunkExtension.java
index 8bfd5bdfb9..38d610630e 100644
--- a/test/org/apache/tomcat/util/http/parser/TestChunkExtension.java
+++ b/test/org/apache/tomcat/util/http/parser/TestChunkExtension.java
@@ -76,6 +76,16 @@ public class TestChunkExtension {
         doTest("; abc  \r\n", true);
     }
 
+    @Test
+    public void testTokenOnlyTokenOnly01() {
+        doTest(";abc;abc\r\n", true);
+    }
+
+    @Test
+    public void testTokenOnlyTokenOnly02() {
+        doTest("; abc ; abc \r\n", true);
+    }
+
     @Test
     public void testTokenToken01() {
         doTest(";abc=abc\r\n", true);


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

Reply via email to