[nginx] Rewrite: added flushing of variables during length calcu...

Maxim Dounin mdounin at mdounin.ru
Sat Jul 25 00:04:55 UTC 2026


details:   http://freenginx.org/hg/nginx/rev/762271b9b20c
branches:  
changeset: 9579:762271b9b20c
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Sun Jul 19 00:57:32 2026 +0300
description:
Rewrite: added flushing of variables during length calculations.

In particular, this fixes issues observed in the following
configuration:

    map $uri $map {
        ~(?<capture>.*) $capture;
    }

    set $temp $capture$map;

Note that this slightly changes meaning of "e->flushed" when used for
rewrite-specific codes, notably for ngx_http_script_complex_value_code()
and ngx_http_script_regex_start_code().  It is now also used to indicate
that relevant code-specific flush arrays should be used.

diffstat:

 src/http/modules/ngx_http_rewrite_module.c |   4 ++++
 src/http/ngx_http_script.c                 |  10 ++++++++++
 src/http/ngx_http_script.h                 |   2 ++
 3 files changed, 16 insertions(+), 0 deletions(-)

diffs (90 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
@@ -171,6 +171,7 @@ ngx_http_rewrite_handler(ngx_http_reques
 
     e->ip = rlcf->codes->elts;
     e->request = r;
+    e->flushed = 1;
     e->quote = 1;
     e->log = rlcf->log;
     e->status = NGX_DECLINED;
@@ -389,6 +390,7 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com
 
     sc.cf = cf;
     sc.source = &value[2];
+    sc.flushes = &regex->flushes;
     sc.lengths = &regex->lengths;
     sc.values = &lcf->codes;
     sc.variables = ngx_http_script_variables_count(&value[2]);
@@ -981,12 +983,14 @@ ngx_http_rewrite_value(ngx_conf_t *cf, n
     }
 
     complex->code = ngx_http_script_complex_value_code;
+    complex->flushes = NULL;
     complex->lengths = NULL;
 
     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
 
     sc.cf = cf;
     sc.source = value;
+    sc.flushes = &complex->flushes;
     sc.lengths = &complex->lengths;
     sc.values = &lcf->codes;
     sc.variables = n;
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
@@ -1154,11 +1154,16 @@ ngx_http_script_regex_start_code(ngx_htt
         }
     }
 
+    if (e->flushed) {
+        ngx_http_script_flush_no_cacheable_variables(e->request, code->flushes);
+    }
+
     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
 
     le.ip = code->lengths->elts;
     le.line = e->line;
     le.request = r;
+    le.flushed = e->flushed;
     le.quote = code->redirect;
     le.is_args = e->is_args;
 
@@ -1771,11 +1776,16 @@ ngx_http_script_complex_value_code(ngx_h
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
                    "http script complex value");
 
+    if (e->flushed) {
+        ngx_http_script_flush_no_cacheable_variables(e->request, code->flushes);
+    }
+
     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
 
     le.ip = code->lengths->elts;
     le.line = e->line;
     le.request = e->request;
+    le.flushed = e->flushed;
     le.quote = e->quote;
     le.is_args = e->is_args;
 
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
@@ -112,6 +112,7 @@ typedef struct {
 typedef struct {
     ngx_http_script_code_pt     code;
     ngx_http_regex_t           *regex;
+    ngx_array_t                *flushes;
     ngx_array_t                *lengths;
     uintptr_t                   size;
     uintptr_t                   status;
@@ -187,6 +188,7 @@ typedef struct {
 
 typedef struct {
     ngx_http_script_code_pt     code;
+    ngx_array_t                *flushes;
     ngx_array_t                *lengths;
 } ngx_http_script_complex_value_code_t;
 


More information about the nginx-devel mailing list