[nginx] Rewrite: removed optimized length calculations.
Maxim Dounin
mdounin at mdounin.ru
Tue Jun 2 16:11:50 UTC 2026
details: http://freenginx.org/hg/nginx/rev/dbf061c1f4f2
branches: stable-1.30
changeset: 9547:dbf061c1f4f2
user: Maxim Dounin <mdounin at mdounin.ru>
date: Tue May 26 03:18:34 2026 +0300
description:
Rewrite: removed optimized length calculations.
Previously, ngx_http_script_regex_start_code() tried to use optimized
buffer length calculations when possible, without length codes
evaluation. Originally the code assumed that allocating space for all
the captures and escaping required for full URI is enough if variables
are not used. In 641:5e8fb59c18c1 (0.3.42) this was further refined to
require that duplicate captures are not used.
However, length calculations can be wrong when nested captures are used,
since the same URI character can appear in multiple captures and might
require escaping in all of them, leading to a buffer overflow, for
example (CVE-2026-9256):
rewrite ^/((.*)) /?c=$1&d=$2;
While it is possible to preserve and further refine optimized length
calculations, it is believed that a better solution would be to remove
them altogether, and this is what this change does.
See also:
https://github.com/nginx/nginx/commit/ca4f92a27464ae6c2082245e4f67048c633aa032
diffstat:
src/http/modules/ngx_http_rewrite_module.c | 4 --
src/http/ngx_http_script.c | 47 +++++++----------------------
src/http/ngx_http_script.h | 2 -
3 files changed, 12 insertions(+), 41 deletions(-)
diffs (108 lines):
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -405,10 +405,6 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com
regex->size = sc.size;
regex->args = sc.args;
- if (sc.variables == 0 && !sc.dup_capture) {
- regex->lengths = NULL;
- }
-
regex_end = ngx_http_script_add_code(lcf->codes,
sizeof(ngx_http_script_regex_end_code_t),
®ex);
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -483,12 +483,6 @@ ngx_http_script_compile(ngx_http_script_
n = sc->source->data[i] - '0';
- if (sc->captures_mask & ((ngx_uint_t) 1 << n)) {
- sc->dup_capture = 1;
- }
-
- sc->captures_mask |= (ngx_uint_t) 1 << n;
-
if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
return NGX_ERROR;
}
@@ -1039,7 +1033,6 @@ ngx_http_script_regex_start_code(ngx_htt
{
size_t len;
ngx_int_t rc;
- ngx_uint_t n;
ngx_http_request_t *r;
ngx_http_script_engine_t le;
ngx_http_script_len_code_pt lcode;
@@ -1140,38 +1133,22 @@ ngx_http_script_regex_start_code(ngx_htt
}
}
- if (code->lengths == NULL) {
- e->buf.len = code->size;
+ ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- if (code->uri) {
- if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
- e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
- NGX_ESCAPE_ARGS);
- }
- }
-
- for (n = 2; n < r->ncaptures; n += 2) {
- e->buf.len += r->captures[n + 1] - r->captures[n];
- }
+ le.ip = code->lengths->elts;
+ le.line = e->line;
+ le.request = r;
+ le.quote = code->redirect;
+ le.is_args = e->is_args;
- } else {
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- le.ip = code->lengths->elts;
- le.line = e->line;
- le.request = r;
- le.quote = code->redirect;
- le.is_args = e->is_args;
+ len = 0;
- len = 0;
+ while (*(uintptr_t *) le.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ len += lcode(&le);
+ }
- while (*(uintptr_t *) le.ip) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- len += lcode(&le);
- }
-
- e->buf.len = len;
- }
+ e->buf.len = len;
if (code->add_args && r->args.len) {
e->buf.len += r->args.len + 1;
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -46,7 +46,6 @@ typedef struct {
ngx_uint_t variables;
ngx_uint_t ncaptures;
- ngx_uint_t captures_mask;
ngx_uint_t size;
void *main;
@@ -58,7 +57,6 @@ typedef struct {
unsigned conf_prefix:1;
unsigned root_prefix:1;
- unsigned dup_capture:1;
unsigned args:1;
} ngx_http_script_compile_t;
More information about the nginx-devel
mailing list