[PATCH] Core: fix content handler and location configuration mismatch.

Piotr Sikora piotr at cloudflare.com
Fri Dec 7 01:14:11 UTC 2012

Core: fix content handler and location configuration mismatch.

When using exclusive content handlers (proxy_pass, etc.) and "if"
pseudo-locations, content handler was always set to the one from the
last "if" pseudo-location that evaluated to true or to the one from
the location block if "if" pseudo-locations didn't provide any.
At the same time, location configuration was updated for each "if"
pseudo-location that evaluated to true, which resulted in content
handler and location configuration mismatch.

For example, following configuration would result in SIGSEGV, because
"proxy_pass" content handler (set in the "if ($pass)" pseudo-location)
would be called with location configuration from the "if ($slow)"
pseudo-location which doesn't contain any upstream configuration.

    location / {
        set $pass  1;
        set $slow  1;

        if ($pass) {

        if ($slow) {
            limit_rate  10k;

This patch fixes this issue by keeping track of and restoring location
configuration from which the content handler originated.

Signed-off-by: Piotr Sikora <piotr at cloudflare.com>
 src/http/ngx_http_core_module.c | 2 ++
 src/http/ngx_http_request.h     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index faecadd..aec951c 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1400,6 +1400,7 @@ ngx_http_core_content_phase(ngx_http_request_t *r,
     ngx_str_t  path;

     if (r->content_handler) {
+        r->loc_conf = r->content_handler_loc_conf;
         r->write_event_handler = ngx_http_request_empty_handler;
         ngx_http_finalize_request(r, r->content_handler(r));
         return NGX_OK;
@@ -1526,6 +1527,7 @@ ngx_http_update_location_config(ngx_http_request_t *r)

     if (clcf->handler) {
         r->content_handler = clcf->handler;
+        r->content_handler_loc_conf = r->loc_conf;

diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index f234840..97c9607 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -358,6 +358,7 @@ struct ngx_http_request_s {
     void                            **main_conf;
     void                            **srv_conf;
     void                            **loc_conf;
+    void                            **content_handler_loc_conf;

     ngx_http_event_handler_pt         read_event_handler;
     ngx_http_event_handler_pt         write_event_handler;

More information about the nginx-devel mailing list