This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new 2f94cc4 Allow for relaxed validation of path and query characters in
HTTP/2
2f94cc4 is described below
commit 2f94cc4dab70cea1f161bd97657031b48b695bcb
Author: Mark Thomas <[email protected]>
AuthorDate: Sat Jan 8 16:37:52 2022 +0000
Allow for relaxed validation of path and query characters in HTTP/2
Follow-up to https://bz.apache.org/bugzilla/show_bug.cgi?id=65785
---
java/org/apache/coyote/http2/StreamProcessor.java | 9 ++++-
.../apache/coyote/http2/TestStreamProcessor.java | 45 ++++++++++++++++++++++
2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java
b/java/org/apache/coyote/http2/StreamProcessor.java
index 11a7196..5f84524 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -31,6 +31,7 @@ import org.apache.coyote.ErrorState;
import org.apache.coyote.Request;
import org.apache.coyote.RequestGroupInfo;
import org.apache.coyote.Response;
+import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.coyote.http11.filters.GzipOutputFilter;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -426,6 +427,10 @@ class StreamProcessor extends AbstractProcessor {
* The checks performed below are based on the checks in Http11InputBuffer.
*/
private boolean validateRequest() {
+ HttpParser httpParser = new HttpParser(
+ ((AbstractHttp11Protocol<?>)
handler.getProtocol().getHttp11Protocol()).getRelaxedPathChars(),
+ ((AbstractHttp11Protocol<?>)
handler.getProtocol().getHttp11Protocol()).getRelaxedQueryChars());
+
// Method name must be a token
String method = request.method().toString();
if (!HttpParser.isToken(method)) {
@@ -436,7 +441,7 @@ class StreamProcessor extends AbstractProcessor {
// (other checks such as valid %nn happen later)
ByteChunk bc = request.requestURI().getByteChunk();
for (int i = bc.getStart(); i < bc.getEnd(); i++) {
- if (HttpParser.isNotRequestTarget(bc.getBuffer()[i])) {
+ if (httpParser.isNotRequestTargetRelaxed(bc.getBuffer()[i])) {
return false;
}
}
@@ -446,7 +451,7 @@ class StreamProcessor extends AbstractProcessor {
String qs = request.queryString().toString();
if (qs != null) {
for (char c : qs.toCharArray()) {
- if (!HttpParser.isQuery(c)) {
+ if (!httpParser.isQueryRelaxed(c)) {
return false;
}
}
diff --git a/test/org/apache/coyote/http2/TestStreamProcessor.java
b/test/org/apache/coyote/http2/TestStreamProcessor.java
index 997b99c..97bf548 100644
--- a/test/org/apache/coyote/http2/TestStreamProcessor.java
+++ b/test/org/apache/coyote/http2/TestStreamProcessor.java
@@ -347,6 +347,51 @@ public class TestStreamProcessor extends Http2TestBase {
}
+ @Test
+ public void testValidateRequestQueryStringRelaxed() throws Exception {
+ enableHttp2();
+
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir = new File("test/webapp");
+ Context ctxt = tomcat.addWebapp(null, "", appDir.getAbsolutePath());
+
+ Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
+ ctxt.addServletMappingDecoded("/simple", "simple");
+
+ tomcat.getConnector().setProperty("relaxedQueryChars", "[]");
+
+ tomcat.start();
+
+ openClientConnection();
+ doHttpUpgrade();
+ sendClientPreface();
+ validateHttp2InitialResponse();
+
+ byte[] frameHeader = new byte[9];
+ ByteBuffer headersPayload = ByteBuffer.allocate(128);
+
+ List<Header> headers = new ArrayList<>(4);
+ headers.add(new Header(":method", "GET"));
+ headers.add(new Header(":scheme", "http"));
+ headers.add(new Header(":path", "/index.html?foo=[]"));
+ headers.add(new Header(":authority", "localhost:" + getPort()));
+
+ buildGetRequest(frameHeader, headersPayload, null, headers, 3);
+
+ writeFrame(frameHeader, headersPayload);
+
+ parser.readFrame(true);
+
+ StringBuilder expected = new StringBuilder();
+ expected.append("3-HeadersStart\n");
+ expected.append("3-Header-[:status]-[200]\n");
+
+ // The status code is the most important thing to test
+ Assert.assertTrue(output.getTrace().startsWith(expected.toString()));
+ }
+
+
private static final class AsyncComplete extends HttpServlet {
private static final long serialVersionUID = 1L;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]