]> git.kaiwu.me - nginx.git/commitdiff
HTTP/2: fixed INITIAL_WINDOW_SIZE with saved state
authorZhidao HONG <z.hong@f5.com>
Mon, 1 Jun 2026 08:41:33 +0000 (08:41 +0000)
committerhongzhidao <hongzhidao@gmail.com>
Tue, 14 Jul 2026 12:38:57 +0000 (20:38 +0800)
The window size change was previously kept in a local variable while
processing SETTINGS parameters.  If parsing was suspended after
SETTINGS_INITIAL_WINDOW_SIZE, the value was lost on resume and was
acknowledged without being applied.

Store the initial window size change in the HTTP/2 state until the
SETTINGS frame is fully processed.

src/http/v2/ngx_http_v2.c
src/http/v2/ngx_http_v2.h

index 69cb0ae09a6629cc032e8cca7d7b8e0532971f76..f8f87672557490d21378f7864444bea1bb2357ab 100644 (file)
@@ -2181,6 +2181,8 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
         return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
     }
 
+    h2c->state.window_delta = 0;
+
     return ngx_http_v2_state_settings_params(h2c, pos, end);
 }
 
@@ -2189,12 +2191,9 @@ static u_char *
 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
     u_char *end)
 {
-    ssize_t                   window_delta;
     ngx_uint_t                id, value;
     ngx_http_v2_out_frame_t  *frame;
 
-    window_delta = 0;
-
     while (h2c->state.length) {
         if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
             return ngx_http_v2_state_save(h2c, pos, end,
@@ -2222,7 +2221,8 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
                                                   NGX_HTTP_V2_FLOW_CTRL_ERROR);
             }
 
-            window_delta = value - h2c->init_window;
+            h2c->state.window_delta = (ssize_t) value
+                                      - (ssize_t) h2c->init_window;
             break;
 
         case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING:
@@ -2275,13 +2275,16 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
 
     ngx_http_v2_queue_ordered_frame(h2c, frame);
 
-    if (window_delta) {
-        h2c->init_window += window_delta;
+    if (h2c->state.window_delta) {
+        h2c->init_window += h2c->state.window_delta;
 
-        if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
+        if (ngx_http_v2_adjust_windows(h2c, h2c->state.window_delta) != NGX_OK)
+        {
             return ngx_http_v2_connection_error(h2c,
                                                 NGX_HTTP_V2_INTERNAL_ERROR);
         }
+
+        h2c->state.window_delta = 0;
     }
 
     return ngx_http_v2_state_complete(h2c, pos, end);
index 9605c8a23d5d645ebbabcd543363c39fee128b9e..beb77a5c1db9eed659fe8719a0fe93e68ca144ad 100644 (file)
@@ -80,6 +80,7 @@ typedef struct {
     ngx_uint_t                       sid;
     size_t                           length;
     size_t                           padding;
+    ssize_t                          window_delta;
     unsigned                         flags:8;
 
     unsigned                         incomplete:1;