diff --git a/CHANGES b/CHANGES index 159ba3b0a6..fbdb7fc1e5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ Changes with Apache 2.0.37 + *) Fix subreqs that are promoted via fast_redirect from having invalid + frec->r structures. This would cause subtle errors later on in + request processing such as seen in PR 7966. [Justin Erenkrantz] + *) More efficient pool recycling logic for the worker MPM [Brian Pane] *) Modify the worker MPM to not accept() new connections until diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 88e1434511..91bd422928 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -408,6 +408,8 @@ static request_rec *internal_internal_redirect(const char *new_uri, /* XXX: Is this function is so bogus and fragile that we deep-6 it? */ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r) { + ap_filter_t *filters; + /* We need to tell POOL_DEBUG that we're guaranteeing that rr->pool * will exist as long as r->pool. Otherwise we run into troubles because * some values in this request will be allocated in r->pool, and others in @@ -446,6 +448,27 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r) ap_remove_output_filter(r->output_filters); r->output_filters = r->output_filters->next; } + + /* If any filters pointed at the now-defunct rr, we must point them + * at our "new" instance of r. In particular, some of rr's structures + * will now be bogus (say rr->headers_out). If a filter tried to modify + * their f->r structure when it is pointing to rr, the real request_rec + * will not get updated. Fix that here. + */ + filters = r->input_filters; + while (filters) { + if (filters->r == rr) { + filters->r = r; + } + filters = filters->next; + } + filters = r->output_filters; + while (filters) { + if (filters->r == rr) { + filters->r = r; + } + filters = filters->next; + } } AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)