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