From 6ae731d074b015be859c3d4ddcaddbaf0dfad8ed Mon Sep 17 00:00:00 2001 From: Vadim Zhestikov Date: Wed, 19 Aug 2026 12:41:08 -0700 Subject: [PATCH] FastCGI: support for multibyte parameter name lengths. 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 | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 96e0b3b5d..7e8953ab1 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -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);