httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joe Orton <jor...@redhat.com>
Subject [PATCH] PR 17629 and all that
Date Tue, 08 Jun 2010 12:37:37 GMT
https://issues.apache.org/bugzilla/show_bug.cgi?id=17629

Here's an attempt at fixing the dreaded PR 17629.  This is a bug in the 
handling of the output filter chain at the point where an internal 
redirect is applied to a subrequest.  Complications:

a) a subrequest's filter chain may start at an arbitrary point in 
r->main's filter chain

 -- for an SSI include, the output from the include must continue from 
 the next filter along from the INCLUDES filter

b) that point where the filter chains join cannot be lost by the 
subrequest doing an internal redirect

 -- obvious breakage as per the PR is losing the DEFLATE filter for 
 the output of the redirect from the subreq

c) the subrequest's filter chain cannot be preserved as-is, since it may 
contain filters which should not be applied to the destination URI

The approach I've used is to distinguish inherited filters from 
subreq-specific filters by seeing what f->r points to, and nuking all 
but the inherited filters.  Here's the patch - test case in the test 
suite:

Index: modules/http/http_request.c
===================================================================
--- modules/http/http_request.c	(revision 952555)
+++ modules/http/http_request.c	(working copy)
@@ -460,17 +460,47 @@
     new->proto_output_filters  = r->proto_output_filters;
     new->proto_input_filters   = r->proto_input_filters;
 
-    new->output_filters  = new->proto_output_filters;
     new->input_filters   = new->proto_input_filters;
 
     if (new->main) {
-        /* Add back the subrequest filter, which we lost when
-         * we set output_filters to include only the protocol
-         * output filters from the original request.
-         */
-        ap_add_output_filter_handle(ap_subreq_core_filter_handle,
-                                    NULL, new, new->connection);
+        ap_filter_t *f, *nextf;
+
+        /* If this is a subrequest, the filter chain may contain a
+         * mixture of filters specific to the old request (r), and
+         * some inherited from r->main.  Here, inherit that filter
+         * chain, and remove all those which are specific to the old
+         * request; ensuring the subreq filter is left in place. */
+        new->output_filters = r->output_filters;
+
+        f = new->output_filters;
+        do {
+            nextf = f->next;
+
+            if (f->r == r && f->frec != ap_subreq_core_filter_handle) {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                              "dropping filter '%s' in internal redirect from %s to %s",
+                              f->frec->name, r->unparsed_uri, new_uri);
+
+                /* To remove the filter, first set f->r to the *new*
+                 * request_rec, so that ->output_filters on 'new' is
+                 * changed (if necessary) when removing the filter. */
+                f->r = new;
+                ap_remove_output_filter(f);
+            }
+
+            f = nextf;
+
+            /* Stop at the protocol filters.  If a protocol filter has
+             * been newly installed for this resource, better leave it
+             * in place, though it's probably a misconfiguration or
+             * filter bug to get into this state. */
+        } while (f && f != new->proto_output_filters);
     }
+    else {
+        /* If this is not a subrequest, clear out all
+         * resource-specific filters. */
+        new->output_filters  = new->proto_output_filters;
+    }
 
     update_r_in_filters(new->input_filters, r, new);
     update_r_in_filters(new->output_filters, r, new);

Mime
View raw message