]> git.kaiwu.me - nginx.git/commitdiff
FastCGI: support for multibyte parameter name lengths.
authorVadim Zhestikov <v.zhestikov@f5.com>
Wed, 19 Aug 2026 19:41:08 +0000 (12:41 -0700)
committerVadimZhestikov <108960056+VadimZhestikov@users.noreply.github.com>
Thu, 20 Aug 2026 02:24:25 +0000 (19:24 -0700)
The name length of a configured parameter was truncated to one byte
before the per-parameter length field was written, so that a
fastcgi_param name of 128 bytes or longer was encoded with a wrong
length while the name itself was copied in full.  The resulting request
was malformed, and upstream servers responded by closing the connection.

While long names are barely used in practice, it is easy to support
them.  The length is now properly encoded up to the allowed length.

src/http/modules/ngx_http_fastcgi_module.c

index 96e0b3b5de9774da2a3d0ccf2734e3453b722047..7e8953ab15e9b28b0d967c72292a1c396a3bc991 100644 (file)
@@ -915,7 +915,8 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
                 continue;
             }
 
-            params_len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
+            params_len += ((key_len > 127) ? 4 : 1) + key_len
+                          + ((val_len > 127) ? 4 : 1) + val_len;
         }
 
         len += params_len;
@@ -1083,7 +1084,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
         while (*(uintptr_t *) le.ip) {
 
             lcode = *(ngx_http_script_len_code_pt *) le.ip;
-            key_len = (u_char) lcode(&le);
+            key_len = lcode(&le);
 
             lcode = *(ngx_http_script_len_code_pt *) le.ip;
             skip_empty = lcode(&le);
@@ -1107,13 +1108,23 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
                 continue;
             }
 
-            if (ngx_http_script_check_length(&e, 1 + ((val_len > 127) ? 4 : 1))
+            if (ngx_http_script_check_length(&e,
+                                             ((key_len > 127) ? 4 : 1)
+                                             + ((val_len > 127) ? 4 : 1))
                 != NGX_OK)
             {
                 return NGX_ERROR;
             }
 
-            *e.pos++ = (u_char) key_len;
+            if (key_len > 127) {
+                *e.pos++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
+                *e.pos++ = (u_char) ((key_len >> 16) & 0xff);
+                *e.pos++ = (u_char) ((key_len >> 8) & 0xff);
+                *e.pos++ = (u_char) (key_len & 0xff);
+
+            } else {
+                *e.pos++ = (u_char) key_len;
+            }
 
             if (val_len > 127) {
                 *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);