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 50aff94  Process HTTP/0.9 requests with extra request line data as 
HTTP/1.1
50aff94 is described below

commit 50aff94ae8058a4672d195d354cb7e7fc5f8ae9e
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Mar 24 09:50:02 2020 +0000

    Process HTTP/0.9 requests with extra request line data as HTTP/1.1
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=64240
---
 .../apache/coyote/http11/Http11InputBuffer.java    | 16 +++--
 .../coyote/http11/TestHttp11InputBufferCRLF.java   | 73 +++++++++++++++++++---
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 80 insertions(+), 14 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java 
b/java/org/apache/coyote/http11/Http11InputBuffer.java
index aa962c6..eecac4f 100644
--- a/java/org/apache/coyote/http11/Http11InputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java
@@ -485,9 +485,10 @@ public class Http11InputBuffer implements InputBuffer, 
ApplicationBufferHandler
                     // HTTP/0.9 style request
                     // Stop this processing loop
                     space = true;
+                    // Set blank protocol (indicates HTTP/0.9)
+                    request.protocol().setString("");
                     // Skip the protocol processing
-                    parsingRequestLinePhase = 6;
-                    parsingRequestLineEol = true;
+                    parsingRequestLinePhase = 7;
                     if (prevChr == Constants.CR) {
                         end = pos - 1;
                     } else {
@@ -518,7 +519,9 @@ public class Http11InputBuffer implements InputBuffer, 
ApplicationBufferHandler
                 request.requestURI().setBytes(byteBuffer.array(), 
parsingRequestLineStart,
                         end - parsingRequestLineStart);
             }
-            if (!parsingRequestLineEol) {
+            // HTTP/0.9 processing jumps to stage 7.
+            // Don't want to overwrite that here.
+            if (parsingRequestLinePhase == 4) {
                 parsingRequestLinePhase = 5;
             }
         }
@@ -571,9 +574,12 @@ public class Http11InputBuffer implements InputBuffer, 
ApplicationBufferHandler
             if ((end - parsingRequestLineStart) > 0) {
                 request.protocol().setBytes(byteBuffer.array(), 
parsingRequestLineStart,
                         end - parsingRequestLineStart);
-            } else {
-                request.protocol().setString("");
+                parsingRequestLinePhase = 7;
             }
+            // If no protocol is found, the ISE below will be triggered.
+        }
+        if (parsingRequestLinePhase == 7) {
+            // Parsing is complete. Return and clean-up.
             parsingRequestLine = false;
             parsingRequestLinePhase = 0;
             parsingRequestLineEol = false;
diff --git a/test/org/apache/coyote/http11/TestHttp11InputBufferCRLF.java 
b/test/org/apache/coyote/http11/TestHttp11InputBufferCRLF.java
index 82315f5..ee033a1 100644
--- a/test/org/apache/coyote/http11/TestHttp11InputBufferCRLF.java
+++ b/test/org/apache/coyote/http11/TestHttp11InputBufferCRLF.java
@@ -45,32 +45,74 @@ public class TestHttp11InputBufferCRLF extends 
TomcatBaseTest {
 
         // Requests to exercise code that allows HT in place of SP
         parameterSets.add(new Object[] { Boolean.FALSE, new String[] {
-                "GET\thttp://localhost:8080/test\tHTTP/1.1"; + CRLF +
+                "GET\t/test\tHTTP/1.1" + CRLF +
                 "Host: localhost:8080" + CRLF +
-                "Connection: close" + CRLF +
-                CRLF } } );
+               "Connection: close" + CRLF +
+                CRLF }, Boolean.TRUE } );
 
         // Requests to simulate package boundaries
         // HTTP/0.9 request
         addRequestWithSplits("GET /test" + CRLF, Boolean.TRUE, parameterSets);
 
+        // HTTP/0.9 request with space
+        // Either malformed but acceptable HTTP/0.9 or invalid HTTP/1.1
+        // Tomcat opts for invalid HTTP/1.1
+        addRequestWithSplits("GET /test " + CRLF, Boolean.FALSE, 
Boolean.FALSE, parameterSets);
+
         // HTTP/0.9 request (no optional CR)
         addRequestWithSplits("GET /test" + LF, Boolean.TRUE, parameterSets);
 
+        // HTTP/0.9 request with space (no optional CR)
+        // Either malformed but acceptable HTTP/0.9 or invalid HTTP/1.1
+        // Tomcat opts for invalid HTTP/1.1
+        addRequestWithSplits("GET /test " + LF, Boolean.FALSE, Boolean.FALSE, 
parameterSets);
+
         // Standard HTTP/1.1 request
-        addRequestWithSplits("GET http://localhost:8080/test HTTP/1.1" + CRLF +
+        addRequestWithSplits("GET /test HTTP/1.1" + CRLF +
+                "Host: localhost:8080" + CRLF +
+                "Connection: close" + CRLF +
+                CRLF,
+                Boolean.FALSE, parameterSets);
+
+        // Invalid HTTP/1.1 request
+        addRequestWithSplits("GET /te<st HTTP/1.1" + CRLF +
+                "Host: localhost:8080" + CRLF +
+                "Connection: close" + CRLF +
+                CRLF,
+                Boolean.FALSE, Boolean.FALSE, parameterSets);
+
+        // Standard HTTP/1.1 request with a query string
+        addRequestWithSplits("GET /test?a=b HTTP/1.1" + CRLF +
                 "Host: localhost:8080" + CRLF +
                 "Connection: close" + CRLF +
                 CRLF,
                 Boolean.FALSE, parameterSets);
 
+        // Standard HTTP/1.1 request with a query string that includes ?
+        addRequestWithSplits("GET /test?a=?b HTTP/1.1" + CRLF +
+                "Host: localhost:8080" + CRLF +
+                "Connection: close" + CRLF +
+                CRLF,
+                Boolean.FALSE, parameterSets);
+
+        // Standard HTTP/1.1 request with an invalid query string
+        addRequestWithSplits("GET /test?a=<b HTTP/1.1" + CRLF +
+                "Host: localhost:8080" + CRLF +
+                "Connection: close" + CRLF +
+                CRLF,
+                Boolean.FALSE, Boolean.FALSE, parameterSets);
+
         return parameterSets;
     }
 
 
     private static void addRequestWithSplits(String request, Boolean isHttp09, 
List<Object[]> parameterSets) {
+        addRequestWithSplits(request, isHttp09, Boolean.TRUE, parameterSets);
+    }
+
+    private static void addRequestWithSplits(String request, Boolean isHttp09, 
Boolean valid, List<Object[]> parameterSets) {
         // Add as a single String
-        parameterSets.add(new Object[] { isHttp09, new String[] { request } } 
);
+        parameterSets.add(new Object[] { isHttp09, new String[] { request }, 
valid });
 
         // Add with all CRLF split between the CR and LF
         List<String> parts = new ArrayList<>();
@@ -82,14 +124,14 @@ public class TestHttp11InputBufferCRLF extends 
TomcatBaseTest {
             pos = request.indexOf("\n", lastPos + 1);
         }
         parts.add(request.substring(lastPos));
-        parameterSets.add(new Object[] { isHttp09, parts.toArray(new 
String[0]) });
+        parameterSets.add(new Object[] { isHttp09, parts.toArray(new 
String[0]), valid });
 
         // Add with a split between each character
         List<String> chars = new ArrayList<>();
         for (char c : request.toCharArray()) {
             chars.add(Character.toString(c));
         }
-        parameterSets.add(new Object[] { isHttp09, chars.toArray(new 
String[0]) });
+        parameterSets.add(new Object[] { isHttp09, chars.toArray(new 
String[0]), valid });
     }
 
     @Parameter(0)
@@ -98,13 +140,26 @@ public class TestHttp11InputBufferCRLF extends 
TomcatBaseTest {
     @Parameter(1)
     public String[] request;
 
+    @Parameter(2)
+    public boolean valid;
+
+
     @Test
     public void testBug54947() {
 
         Client client = new Client(request, isHttp09);
 
-        client.doRequest();
-        Assert.assertTrue(client.isResponseBodyOK());
+        Exception e = client.doRequest();
+
+        if (valid) {
+            Assert.assertTrue(client.isResponseBodyOK());
+        } else if (e == null){
+            Assert.assertTrue(client.isResponse400());
+        } else {
+            // The invalid request was detected before the entire request had
+            // been sent to Tomcat reset the connection when the client tried 
to
+            // continue sending the invalid request.
+        }
     }
 
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index e49f464..7f7b48e 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -75,6 +75,11 @@
         <code>URIEncoding</code> is not a superset of US-ASCII as required by
         RFC7230. (markt)
       </add>
+      <fix>
+        <bug>64240</bug>: Ensure that HTTP/0.9 requests that contain additional
+        data on the request line after the URI are treated consistently. Such
+        requests will now always be treated as HTTP/1.1. (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to