[PATCH 10 of 10] HTTP: just one empty line now accepted when parsing request line

Maxim Dounin mdounin at mdounin.ru
Fri Mar 15 18:14:24 UTC 2024


# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1710526261 -10800
#      Fri Mar 15 21:11:01 2024 +0300
# Node ID 3c67054eeb098757aaf59a45b3dcf38228a1552b
# Parent  9580cb3029058154973dd7b28c9da709c5bc3e31
HTTP: just one empty line now accepted when parsing request line.

This ensures that multiple CRLFs cannot be used as a DoS vector, and also
in line with RFC 9112 ("SHOULD ignore at least one empty line").  Further,
bare CRs are no longer accepted.

diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -106,6 +106,8 @@ ngx_http_parse_request_line(ngx_http_req
     u_char  c, ch, *p, *m;
     enum {
         sw_start = 0,
+        sw_newline,
+        sw_method_start,
         sw_method,
         sw_spaces_before_uri,
         sw_schema,
@@ -143,7 +145,13 @@ ngx_http_parse_request_line(ngx_http_req
         case sw_start:
             r->request_start = p;
 
-            if (ch == CR || ch == LF) {
+            if (ch == CR) {
+                state = sw_newline;
+                break;
+            }
+
+            if (ch == LF) {
+                state = sw_method_start;
                 break;
             }
 
@@ -154,6 +162,25 @@ ngx_http_parse_request_line(ngx_http_req
             state = sw_method;
             break;
 
+        case sw_newline:
+
+            if (ch == LF) {
+                state = sw_method_start;
+                break;
+            }
+
+            return NGX_HTTP_PARSE_INVALID_REQUEST;
+
+        case sw_method_start:
+            r->request_start = p;
+
+            if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+
+            state = sw_method;
+            break;
+
         case sw_method:
             if (ch == ' ') {
                 r->method_end = p - 1;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1623,16 +1623,6 @@ ngx_http_alloc_large_header_buffer(ngx_h
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http alloc large header buffer");
 
-    if (request_line && r->state == 0) {
-
-        /* the client fills up the buffer with "\r\n" */
-
-        r->header_in->pos = r->header_in->start;
-        r->header_in->last = r->header_in->start;
-
-        return NGX_OK;
-    }
-
     old = request_line ? r->request_start : r->header_name_start;
 
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);




More information about the nginx-devel mailing list