From 97e40e59b7b4ad6aa36f54ce4f1e64d1e98f24cb Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Fri, 3 Jul 2026 15:11:09 +0400 Subject: [PATCH] Script: avoid garbage at the end of the result string If the script result turned out to be shorter than its predicted length, the result string contained uninitialized bytes at the end. The fix is to cut the result string by its actual size. The following locations returned trailing garbage to the client with URI "/1234abcd". map $uri $foo { ~^/(?[0-9]).*$ $bar; } location ~(?[0-9]*)[a-z]*$ { return 200 $1:$foo; } location ~(?[0-9]*)[a-z]*$ { set $qux $1:$foo; return 200 $qux; } --- src/http/modules/ngx_http_rewrite_module.c | 18 ++++++++++--- src/http/ngx_http_script.c | 30 +++++++++++++++++----- src/http/ngx_http_script.h | 6 +++++ src/stream/ngx_stream_script.c | 18 +++++++++---- 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index ff3b68716..eefe4c8c8 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -966,10 +966,11 @@ static char * ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { - ngx_int_t n; - ngx_http_script_compile_t sc; - ngx_http_script_value_code_t *val; - ngx_http_script_complex_value_code_t *complex; + ngx_int_t n; + ngx_http_script_compile_t sc; + ngx_http_script_value_code_t *val; + ngx_http_script_complex_value_code_t *complex; + ngx_http_script_complex_value_end_code_t *complex_end; n = ngx_http_script_variables_count(value); @@ -1016,5 +1017,14 @@ ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, return NGX_CONF_ERROR; } + complex_end = ngx_http_script_add_code(lcf->codes, + sizeof(ngx_http_script_complex_value_end_code_t), + &complex); + if (complex_end == NULL) { + return NGX_CONF_ERROR; + } + + complex_end->code = ngx_http_script_complex_value_end_code; + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index d3af4408d..9c97a5b08 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -103,7 +103,8 @@ ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val, return NGX_ERROR; } - *value = e.buf; + value->data = e.buf.data; + value->len = e.pos - e.buf.data; return NGX_OK; } @@ -620,6 +621,7 @@ u_char * ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, void *code_lengths, size_t len, void *code_values) { + size_t n; ngx_uint_t i; ngx_http_script_code_pt code; ngx_http_script_len_code_pt lcode; @@ -641,21 +643,23 @@ ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, e.request = r; e.flushed = 1; + n = len; + while (*(uintptr_t *) e.ip) { lcode = *(ngx_http_script_len_code_pt *) e.ip; - len += lcode(&e); + n += lcode(&e); } - value->len = len; - value->data = ngx_pnalloc(r->pool, len); + value->len = n; + value->data = ngx_pnalloc(r->pool, n); if (value->data == NULL) { return NULL; } e.ip = code_values; e.pos = value->data; - e.end = value->data + len; + e.end = value->data + n; while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; @@ -666,6 +670,8 @@ ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, return NULL; } + value->len = e.pos + len - value->data; + return e.pos; } @@ -1548,6 +1554,8 @@ ngx_http_script_full_name_code(ngx_http_script_engine_t *e) } e->buf = value; + e->pos = value.data + value.len; + e->end = e->pos; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, "http script fullname: \"%V\"", &value); @@ -1855,8 +1863,18 @@ ngx_http_script_complex_value_code(ngx_http_script_engine_t *e) e->pos = e->buf.data; e->end = e->buf.data + len; +} + + +void +ngx_http_script_complex_value_end_code(ngx_http_script_engine_t *e) +{ + e->ip += sizeof(ngx_http_script_complex_value_end_code_t); + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, + "http script complex value end"); - e->sp->len = e->buf.len; + e->sp->len = e->pos - e->buf.data; e->sp->data = e->buf.data; e->sp++; } diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index b086b266f..4f2fbd16e 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -200,6 +200,11 @@ typedef struct { } ngx_http_script_complex_value_code_t; +typedef struct { + ngx_http_script_code_pt code; +} ngx_http_script_complex_value_end_code_t; + + typedef struct { ngx_http_script_code_pt code; uintptr_t value; @@ -263,6 +268,7 @@ void ngx_http_script_equal_code(ngx_http_script_engine_t *e); void ngx_http_script_not_equal_code(ngx_http_script_engine_t *e); void ngx_http_script_file_code(ngx_http_script_engine_t *e); void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e); +void ngx_http_script_complex_value_end_code(ngx_http_script_engine_t *e); void ngx_http_script_value_code(ngx_http_script_engine_t *e); void ngx_http_script_set_var_code(ngx_http_script_engine_t *e); void ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e); diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c index 2e31102df..559b8b9fb 100644 --- a/src/stream/ngx_stream_script.c +++ b/src/stream/ngx_stream_script.c @@ -104,7 +104,8 @@ ngx_stream_complex_value(ngx_stream_session_t *s, return NGX_ERROR; } - *value = e.buf; + value->data = e.buf.data; + value->len = e.pos - e.buf.data; return NGX_OK; } @@ -496,6 +497,7 @@ u_char * ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value, void *code_lengths, size_t len, void *code_values) { + size_t n; ngx_uint_t i; ngx_stream_script_code_pt code; ngx_stream_script_engine_t e; @@ -517,21 +519,23 @@ ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value, e.session = s; e.flushed = 1; + n = len; + while (*(uintptr_t *) e.ip) { lcode = *(ngx_stream_script_len_code_pt *) e.ip; - len += lcode(&e); + n += lcode(&e); } - value->len = len; - value->data = ngx_pnalloc(s->connection->pool, len); + value->len = n; + value->data = ngx_pnalloc(s->connection->pool, n); if (value->data == NULL) { return NULL; } e.ip = code_values; e.pos = value->data; - e.end = value->data + len; + e.end = value->data + n; while (*(uintptr_t *) e.ip) { code = *(ngx_stream_script_code_pt *) e.ip; @@ -542,6 +546,8 @@ ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value, return NULL; } + value->len = e.pos + len - value->data; + return e.pos; } @@ -1062,6 +1068,8 @@ ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e) } e->buf = value; + e->pos = value.data + value.len; + e->end = e->pos; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, "stream script fullname: \"%V\"", &value); -- 2.47.3