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;
+}
+
filter.diff
Description: Binary data
