[PATCH 3 of 3] HTTP/3: kept the skipped frame length separate from data length

Maxim Dounin mdounin at mdounin.ru
Tue Oct 27 05:41:56 UTC 2026


# HG changeset patch
# User Vadim Zhestikov <v.zhestikov at f5.com>
# Date 1793074233 -10800
#      Tue Oct 27 07:10:33 2026 +0300
# Node ID 75d4162de2b359af3163b932599f40d2ebb80cf3
# Parent  19f937a6a6bf0c24dacfce1068d4153656b9f995
HTTP/3: kept the skipped frame length separate from data length.

ngx_http_v3_parse_data() stored the remaining length of a skipped
(unknown) frame in st->length -- the same field the request body
filter uses for the number of DATA payload bytes to pass on as
request body.  When an unknown frame was split across parser
invocations, the skip was interrupted with st->length holding the
skip remainder; on the next buffer the body filter, which calls
the parser only while st->length == 0, treated that remainder as
request body.

When proxying, this could result in sending unframed bytes, potentially
allowing for bypass of client_max_body_size, which is enforced only on
the DATA path, or an injection.

The fix is to keep unknown frame payload in a separate st->skip counter.

Reported by Hansol Lee of GOTROOT.

Obtained from:
https://github.com/nginx/nginx/commit/1c173a2d8767730e678c27446138d7ae5dd6fd64

diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c
--- a/src/http/v3/ngx_http_v3_parse.c
+++ b/src/http/v3/ngx_http_v3_parse.c
@@ -1831,6 +1831,8 @@ ngx_http_v3_parse_data(ngx_connection_t 
                            st->type, st->length);
 
             if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) {
+                st->skip = st->length;
+                st->length = 0;
                 st->state = sw_skip;
                 break;
             }
@@ -1840,7 +1842,7 @@ ngx_http_v3_parse_data(ngx_connection_t 
 
         case sw_skip:
 
-            rc = ngx_http_v3_parse_skip(b, &st->length);
+            rc = ngx_http_v3_parse_skip(b, &st->skip);
             if (rc != NGX_DONE) {
                 return rc;
             }
diff --git a/src/http/v3/ngx_http_v3_parse.h b/src/http/v3/ngx_http_v3_parse.h
--- a/src/http/v3/ngx_http_v3_parse.h
+++ b/src/http/v3/ngx_http_v3_parse.h
@@ -121,6 +121,7 @@ typedef struct {
     ngx_uint_t                      state;
     ngx_uint_t                      type;
     ngx_uint_t                      length;
+    ngx_uint_t                      skip;
     ngx_http_v3_parse_varlen_int_t  vlint;
 } ngx_http_v3_parse_data_t;
 



More information about the nginx-devel mailing list