[nginx] Fixed named captures to don't redefine get handler.
Maxim Dounin
mdounin at mdounin.ru
Mon Jun 8 14:56:05 UTC 2026
details: http://freenginx.org/hg/nginx/rev/623210753d47
branches:
changeset: 9553:623210753d47
user: Maxim Dounin <mdounin at mdounin.ru>
date: Mon Jun 08 17:53:50 2026 +0300
description:
Fixed named captures to don't redefine get handler.
Previously, named captures unconditionally changed v->get_handler to
ngx_http_variable_not_found(), so merely defining a regular expression
with a named captures was enough to hide an existing variable. For
example, in the following configuration the $foo variable was always
empty in requests to "/":
map $uri $foo {
default "a value from map";
}
location / {
return 200 "value: $foo";
}
location ~ /re/(?<foo>.*) {
return 200 "value: $foo";
}
Similarly, for variables within an existing prefix, such as for
$http_foo, using a regular expression with a named captures was enough
to hide the original prefix variable. For example, in the following
configuration the $http_foo variable was always empty in requests to "/",
even if the "Foo" header was present in requests:
location / {
return 200 "value: $http_foo";
}
location ~ /re/(?<http_foo>.*) {
return 200 "value: $http_foo";
}
The fix is to avoid changing v->get_handler if it's already present, and
to use the NGX_HTTP_VAR_WEAK flag to avoid redefining get handler for
prefix variables, similarly to what the "set" directive does.
diffstat:
src/http/ngx_http_variables.c | 7 +++++--
src/stream/ngx_stream_variables.c | 7 +++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diffs (48 lines):
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -2589,7 +2589,8 @@ ngx_http_regex_compile(ngx_conf_t *cf, n
name.data = &p[2];
name.len = ngx_strlen(name.data);
- v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
+ v = ngx_http_add_variable(cf, &name,
+ NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_WEAK);
if (v == NULL) {
return NULL;
}
@@ -2599,7 +2600,9 @@ ngx_http_regex_compile(ngx_conf_t *cf, n
return NULL;
}
- v->get_handler = ngx_http_variable_not_found;
+ if (v->get_handler == NULL) {
+ v->get_handler = ngx_http_variable_not_found;
+ }
p += size;
}
diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c
--- a/src/stream/ngx_stream_variables.c
+++ b/src/stream/ngx_stream_variables.c
@@ -1072,7 +1072,8 @@ ngx_stream_regex_compile(ngx_conf_t *cf,
name.data = &p[2];
name.len = ngx_strlen(name.data);
- v = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE);
+ v = ngx_stream_add_variable(cf, &name,
+ NGX_STREAM_VAR_CHANGEABLE|NGX_STREAM_VAR_WEAK);
if (v == NULL) {
return NULL;
}
@@ -1082,7 +1083,9 @@ ngx_stream_regex_compile(ngx_conf_t *cf,
return NULL;
}
- v->get_handler = ngx_stream_variable_not_found;
+ if (v->get_handler == NULL) {
+ v->get_handler = ngx_stream_variable_not_found;
+ }
p += size;
}
More information about the nginx-devel
mailing list