A simple SSI file with two #include file directives
will coredump due the fact that we are copying the 
filter chain *pointers* from the main request to 
the subrequest in make_sub_request. When we add
the subreq_core_filter this corrupts the main 
filter chain.

We need to copy the filter chain, not just the 
pointers. Attached is a patch to do this. I will
commit if there are no objections.

There is also at least one remaining bug in 
add_any_filter handle due to the fact that 
r->output_filters and/or r->proto_output_filters
are not getting updated when filters are added.
I'm still looking into that one if no-one beats
me to it.

Allan

Index: include/util_filter.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/util_filter.h,v
retrieving revision 1.67
diff -u -d -b -r1.67 util_filter.h
--- include/util_filter.h       3 Mar 2002 06:04:08 -0000       1.67
+++ include/util_filter.h       6 Mar 2002 18:24:23 -0000
@@ -515,6 +515,18 @@
                                            ...)
         __attribute__((format(printf,3,4)));                                    
 
+/**
+ * Copy the in/out filter chains from one request to another
+ * @param from The request to copy the chains from
+ * @param to   The request to copy the chains to 
+ * @param start_filter The filter from which point the output chain copy starts
+ * @return void
+ * @deffunc void ap_copy_filter_chains(const request_rec *from, request_rec *to, 
+const ap_filter_t *start_filter)
+ */ 
+void ap_copy_filter_chains(const request_rec *from, 
+                           request_rec *to, 
+                           const ap_filter_t *start_filter);
+
 #ifdef __cplusplus
 }
 #endif
Index: server/request.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/request.c,v
retrieving revision 1.102
diff -u -d -b -r1.102 request.c
--- server/request.c    5 Mar 2002 05:24:21 -0000       1.102
+++ server/request.c    6 Mar 2002 18:24:25 -0000
@@ -1492,14 +1492,7 @@
 
     /* start with the same set of output filters */
     if (next_filter) {
-        /* while there are no input filters for a subrequest, we will
-         * try to insert some, so if we don't have valid data, the code
-         * will seg fault.
-         */
-        rnew->input_filters  = r->input_filters;
-        rnew->proto_input_filters  = r->proto_input_filters;
-        rnew->output_filters = next_filter;
-       rnew->proto_output_filters = r->connection->output_filters;
+        ap_copy_filter_chains(r, rnew, next_filter); 
         ap_add_output_filter_handle(ap_subreq_core_filter_handle,
                                     NULL, rnew, rnew->connection); 
     }
Index: server/util_filter.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/util_filter.c,v
retrieving revision 1.85
diff -u -d -b -r1.85 util_filter.c
--- server/util_filter.c        6 Mar 2002 17:29:39 -0000       1.85
+++ server/util_filter.c        6 Mar 2002 18:24:25 -0000
@@ -615,3 +615,96 @@
     va_end(args);
     return rv;
 }
+
+void ap_copy_filter_chains(const request_rec *from, 
+                           request_rec *to, 
+                           const ap_filter_t *start_filter)
+{
+    int connection_done = 0, proto_done = 0;
+    const ap_filter_t *from_filter;
+    ap_filter_t *to_filter, *curr_filter; 
+
+    from_filter = from->connection->output_filters;
+    while (from_filter->next != NULL)
+        from_filter = from_filter->next;
+
+    curr_filter = NULL;
+    while(1) {
+
+        to_filter = apr_palloc(to->pool, sizeof(ap_filter_t));
+        memcpy(to_filter, from_filter, sizeof(ap_filter_t));
+        to_filter->next = curr_filter;
+
+        if (NULL != curr_filter) 
+           curr_filter->prev = to_filter; 
+            
+        curr_filter = to_filter;
+
+        if (!connection_done) {
+            if (from_filter == from->connection->output_filters) {
+                to->connection->output_filters = curr_filter;
+                connection_done = 1;
+            }
+        }
+        else if (!proto_done) {
+            if (from_filter == from->proto_output_filters) {
+                to->proto_output_filters = curr_filter;
+                proto_done = 1;
+            }
+        }
+
+        if (from_filter == start_filter)
+            break;
+
+        from_filter = from_filter->prev;
+        if (NULL == from_filter)
+            break;
+    }
+
+    if (!proto_done)
+        to->proto_output_filters = curr_filter;
+    if (NULL == to->output_filters)
+        to->output_filters = to->proto_output_filters;
+
+    from_filter = from->connection->input_filters;
+    while (from_filter->next != NULL)
+        from_filter = from_filter->next;
+
+    connection_done = proto_done = 0;
+    curr_filter = NULL;
+
+    while(1) {
+
+        to_filter = apr_palloc(to->pool, sizeof(ap_filter_t));
+        memcpy(to_filter, from_filter, sizeof(ap_filter_t));
+        to_filter->next = curr_filter;
+
+        if (NULL != curr_filter) 
+           curr_filter->prev = to_filter; 
+            
+        curr_filter = to_filter;
+
+        if (!connection_done) {
+            if (from_filter == from->connection->input_filters) {
+                to->connection->input_filters = curr_filter;
+                connection_done = 1;
+            }
+        }
+        else if (!proto_done) {
+            if (from_filter == from->proto_input_filters) {
+                to->proto_input_filters = curr_filter;
+                proto_done = 1;
+            }
+        }
+
+        from_filter = from_filter->prev;
+        if (NULL ==from_filter)
+            break;
+    }
+
+    if (!proto_done)
+        to->proto_input_filters = curr_filter;
+    if (NULL == to->input_filters)
+        to->input_filters = to->proto_input_filters;
+}
+

Attachment: filter.diff
Description: Binary data

Reply via email to