This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 3ce7bcc Allow for relaxed validation of path and query characters in HTTP/2 3ce7bcc is described below commit 3ce7bccc8c5ec555b3301bcdac01298ecd971605 Author: Mark Thomas <ma...@apache.org> 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/Http2Protocol.java | 3 +- java/org/apache/coyote/http2/StreamProcessor.java | 7 +++- .../apache/coyote/http2/TestStreamProcessor.java | 45 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Protocol.java b/java/org/apache/coyote/http2/Http2Protocol.java index 8b7718d..7bdc6cb 100644 --- a/java/org/apache/coyote/http2/Http2Protocol.java +++ b/java/org/apache/coyote/http2/Http2Protocol.java @@ -21,7 +21,6 @@ import java.util.Enumeration; import javax.management.ObjectName; -import org.apache.coyote.AbstractProtocol; import org.apache.coyote.Adapter; import org.apache.coyote.ContinueResponseTiming; import org.apache.coyote.Processor; @@ -342,7 +341,7 @@ public class Http2Protocol implements UpgradeProtocol { } - public AbstractProtocol<?> getHttp11Protocol() { + public AbstractHttp11Protocol<?> getHttp11Protocol() { return this.http11Protocol; } diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index c1a943a..68621cb 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -466,6 +466,9 @@ class StreamProcessor extends AbstractProcessor { * The checks performed below are based on the checks in Http11InputBuffer. */ private boolean validateRequest() { + HttpParser httpParser = new HttpParser(handler.getProtocol().getHttp11Protocol().getRelaxedPathChars(), + handler.getProtocol().getHttp11Protocol().getRelaxedQueryChars()); + // Method name must be a token String method = request.method().toString(); if (!HttpParser.isToken(method)) { @@ -476,7 +479,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; } } @@ -486,7 +489,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 2fd8c94..b7480ed 100644 --- a/test/org/apache/coyote/http2/TestStreamProcessor.java +++ b/test/org/apache/coyote/http2/TestStreamProcessor.java @@ -346,6 +346,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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org