changeset 8102:49e7db44b57c

SSI: handling of subrequests from other modules (ticket #1263). As the SSI parser always uses the context from the main request for storing variables and blocks, that context should always exist for subrequests using SSI, even though the main request does not necessarily have SSI enabled. However, `ngx_http_get_module_ctx(r->main, ...)` is getting NULL in such cases, resulting in the worker crashing SIGSEGV when accessing its attributes. This patch links the first initialized context to the main request, and upgrades it only when main context is initialized.
author Ciel Zhao <i@ciel.dev>
date Mon, 21 Nov 2022 17:01:34 +0300
parents 42bc158a47ec
children b809f53d3f5b
files src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_ssi_filter_module.h
diffstat 2 files changed, 29 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -329,7 +329,7 @@ static ngx_http_variable_t  ngx_http_ssi
 static ngx_int_t
 ngx_http_ssi_header_filter(ngx_http_request_t *r)
 {
-    ngx_http_ssi_ctx_t       *ctx;
+    ngx_http_ssi_ctx_t       *ctx, *mctx;
     ngx_http_ssi_loc_conf_t  *slcf;
 
     slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
@@ -341,6 +341,8 @@ ngx_http_ssi_header_filter(ngx_http_requ
         return ngx_http_next_header_filter(r);
     }
 
+    mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
     if (ctx == NULL) {
         return NGX_ERROR;
@@ -367,6 +369,26 @@ ngx_http_ssi_header_filter(ngx_http_requ
     r->filter_need_in_memory = 1;
 
     if (r == r->main) {
+
+        if (mctx) {
+
+            /*
+             * if there was a shared context previously used as main,
+             * copy variables and blocks
+             */
+
+            ctx->variables = mctx->variables;
+            ctx->blocks = mctx->blocks;
+
+#if (NGX_PCRE)
+            ctx->ncaptures = mctx->ncaptures;
+            ctx->captures = mctx->captures;
+            ctx->captures_data = mctx->captures_data;
+#endif
+
+            mctx->shared = 0;
+        }
+
         ngx_http_clear_content_length(r);
         ngx_http_clear_accept_ranges(r);
 
@@ -379,6 +401,10 @@ ngx_http_ssi_header_filter(ngx_http_requ
         } else {
             ngx_http_weak_etag(r);
         }
+
+    } else if (mctx == NULL) {
+        ngx_http_set_ctx(r->main, ctx, ngx_http_ssi_filter_module);
+        ctx->shared = 1;
     }
 
     return ngx_http_next_header_filter(r);
@@ -405,6 +431,7 @@ ngx_http_ssi_body_filter(ngx_http_reques
     ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
 
     if (ctx == NULL
+        || (ctx->shared && r == r->main)
         || (in == NULL
             && ctx->buf == NULL
             && ctx->in == NULL
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -71,6 +71,7 @@ typedef struct {
     u_char                   *captures_data;
 #endif
 
+    unsigned                  shared:1;
     unsigned                  conditional:2;
     unsigned                  encoding:2;
     unsigned                  block:1;