This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 6d478dbe18 Fix issues found by Copilot reviewing the chunked extension
validation
6d478dbe18 is described below
commit 6d478dbe18b7c4bb671c30fedf130309b0dab77c
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 694fd9f55e..2363309738 100644
--- a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
+++ b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
@@ -597,7 +597,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]