You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2023/05/02 15:48:20 UTC
[tomcat] branch 9.0.x updated: Zero length HTTP header names are not valid (not valid tokens)
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 327c0d7747 Zero length HTTP header names are not valid (not valid tokens)
327c0d7747 is described below
commit 327c0d77470e40ede3853fb452a78b4144258c19
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue May 2 16:47:25 2023 +0100
Zero length HTTP header names are not valid (not valid tokens)
---
.../apache/coyote/http11/Http11InputBuffer.java | 18 ++++++---
.../apache/coyote/http11/LocalStrings.properties | 1 +
.../coyote/http11/TestHttp11InputBuffer.java | 44 ++++++++++++++++++++++
webapps/docs/changelog.xml | 4 ++
4 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java b/java/org/apache/coyote/http11/Http11InputBuffer.java
index 3c784e7540..b7517459fd 100644
--- a/java/org/apache/coyote/http11/Http11InputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java
@@ -50,8 +50,8 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler
private static final StringManager sm = StringManager.getManager(Http11InputBuffer.class);
- private static final byte[] CLIENT_PREFACE_START = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
- .getBytes(StandardCharsets.ISO_8859_1);
+ private static final byte[] CLIENT_PREFACE_START =
+ "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1);
/**
* Associated Coyote request.
@@ -883,6 +883,11 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler
int pos = byteBuffer.position();
chr = byteBuffer.get();
if (chr == Constants.COLON) {
+ if (headerData.start == pos) {
+ // Zero length header name - not valid.
+ // skipLine() will handle the error
+ return skipLine(false);
+ }
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
headerData.headerValue = headers.addValue(byteBuffer.array(), headerData.start, pos - headerData.start);
pos = byteBuffer.position();
@@ -1064,12 +1069,13 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler
}
}
if (rejectThisHeader || log.isDebugEnabled()) {
- String message = sm.getString("iib.invalidheader", HeaderUtil.toPrintableString(byteBuffer.array(),
- headerData.lineStart, headerData.lastSignificantChar - headerData.lineStart + 1));
if (rejectThisHeader) {
- throw new IllegalArgumentException(message);
+ throw new IllegalArgumentException(
+ sm.getString("iib.invalidheader.reject", HeaderUtil.toPrintableString(byteBuffer.array(),
+ headerData.lineStart, headerData.lastSignificantChar - headerData.lineStart + 1)));
}
- log.debug(message);
+ log.debug(sm.getString("iib.invalidheader", HeaderUtil.toPrintableString(byteBuffer.array(),
+ headerData.lineStart, headerData.lastSignificantChar - headerData.lineStart + 1)));
}
headerParsePos = HeaderParsePosition.HEADER_START;
diff --git a/java/org/apache/coyote/http11/LocalStrings.properties b/java/org/apache/coyote/http11/LocalStrings.properties
index 3e49897b51..9e4d2ec86a 100644
--- a/java/org/apache/coyote/http11/LocalStrings.properties
+++ b/java/org/apache/coyote/http11/LocalStrings.properties
@@ -47,6 +47,7 @@ iib.invalidHttpProtocol=Invalid character found in the HTTP protocol [{0}]
iib.invalidPhase=Invalid request line parse phase [{0}]
iib.invalidRequestTarget=Invalid character found in the request target [{0}]. The valid characters are defined in RFC 7230 and RFC 3986
iib.invalidheader=The HTTP header line [{0}] does not conform to RFC 7230 and has been ignored.
+iib.invalidheader.reject=The HTTP header line [{0}] does not conform to RFC 7230. The request has been rejected.
iib.invalidmethod=Invalid character found in method name [{0}]. HTTP method names must be tokens
iib.parseheaders.ise.error=Unexpected state: headers already parsed. Buffer not recycled?
iib.readtimeout=Timeout attempting to read data from the socket
diff --git a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
index 564e5001d5..1c5c985c63 100644
--- a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
+++ b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java
@@ -732,4 +732,48 @@ public class TestHttp11InputBuffer extends TomcatBaseTest {
return true;
}
}
+
+
+ private static final class Client extends SimpleHttpClient {
+
+ Client(int port) {
+ setPort(port);
+ }
+
+ @Override
+ public boolean isResponseBodyOK() {
+ return getResponseBody().contains("test - data");
+ }
+ }
+
+
+ @Test
+ public void testInvalidHeader02() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ // This setting means the connection will be closed at the end of the
+ // request
+ Assert.assertTrue(tomcat.getConnector().setProperty("maxKeepAliveRequests", "1"));
+
+ // No file system docBase required
+ Context ctx = tomcat.addContext("", null);
+
+ // Add servlet
+ Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
+ ctx.addServletMappingDecoded("/foo", "TesterServlet");
+
+ tomcat.start();
+
+ String request = "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF + "Host: localhost" + SimpleHttpClient.CRLF + ":b" +
+ SimpleHttpClient.CRLF + "X-Dummy:b" + SimpleHttpClient.CRLF + SimpleHttpClient.CRLF;
+
+ Client client = new Client(tomcat.getConnector().getLocalPort());
+ client.setRequest(new String[] { request });
+
+ client.connect(10000, 600000);
+ client.processRequest();
+
+ // Expected response is a 400 response.
+ Assert.assertTrue(client.getResponseLine(), client.isResponse400());
+ }
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 68dfdb3651..9aa8d48cd0 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -142,6 +142,10 @@
Add support for a new character set, <code>gb18030-2022</code> -
introduced in Java 21, to the character set caching mechanism. (markt)
</add>
+ <fix>
+ Fix an edge case in HTTP header parsing and ensure that HTTP headers
+ without names are treated as invalid. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org