mod_dav: Fix a potential cause of unbounded memory usage or incorrect behavior in a routine that sends 's to the output filters. The dav_send_one_response() function accepts the current head of the output filter list as an argument, but the actual head can change between calls to ap_pass_brigade(). This can happen with self-removing filters, e.g., with the filter from mod_headers or mod_deflate. Consequently, executing an already removed filter can either cause unwanted memory usage or incorrect behavior. * modules/dav/main/mod_dav.c (dav_send_one_response): Accept a request_rec instead of an ap_filter_t. Write the response to r->output_filters. (dav_send_multistatus, dav_stream_response): Update these calling sites of dav_send_one_response(). * modules/dav/main/mod_dav.h (dav_send_one_response): Adjust function definition. Index: modules/dav/main/mod_dav.c =================================================================== --- modules/dav/main/mod_dav.c (revision 1757382) +++ modules/dav/main/mod_dav.c (working copy) @@ -438,7 +438,8 @@ static const char *dav_xml_escape_uri(apr_pool_t * /* Write a complete RESPONSE object out as a xml element. Data is sent into brigade BB, which is auto-flushed into - OUTPUT filter stack. Use POOL for any temporary allocations. + the output filter stack for request R. Use POOL for any temporary + allocations. [Presumably the tag has already been written; this routine is shared by dav_send_multistatus and dav_stream_response.] @@ -445,23 +446,23 @@ static const char *dav_xml_escape_uri(apr_pool_t * */ DAV_DECLARE(void) dav_send_one_response(dav_response *response, apr_bucket_brigade *bb, - ap_filter_t *output, + request_rec *r, apr_pool_t *pool) { apr_text *t = NULL; if (response->propresult.xmlns == NULL) { - ap_fputs(output, bb, ""); + ap_fputs(r->output_filters, bb, ""); } else { - ap_fputs(output, bb, "output_filters, bb, "propresult.xmlns; t; t = t->next) { - ap_fputs(output, bb, t->text); + ap_fputs(r->output_filters, bb, t->text); } - ap_fputc(output, bb, '>'); + ap_fputc(r->output_filters, bb, '>'); } - ap_fputstrs(output, bb, + ap_fputstrs(r->output_filters, bb, DEBUG_CR "", dav_xml_escape_uri(pool, response->href), "" DEBUG_CR, @@ -472,7 +473,7 @@ DAV_DECLARE(void) dav_send_one_response(dav_respon * default to 500 Internal Server Error if first->status * is not a known (or valid) status code. */ - ap_fputstrs(output, bb, + ap_fputstrs(r->output_filters, bb, "HTTP/1.1 ", ap_get_status_line(response->status), "" DEBUG_CR, @@ -481,7 +482,7 @@ DAV_DECLARE(void) dav_send_one_response(dav_respon else { /* assume this includes and is quoted properly */ for (t = response->propresult.propstats; t; t = t->next) { - ap_fputs(output, bb, t->text); + ap_fputs(r->output_filters, bb, t->text); } } @@ -490,7 +491,7 @@ DAV_DECLARE(void) dav_send_one_response(dav_respon * We supply the description, so we know it doesn't have to * have any escaping/encoding applied to it. */ - ap_fputstrs(output, bb, + ap_fputstrs(r->output_filters, bb, "", response->desc, "" DEBUG_CR, @@ -497,7 +498,7 @@ DAV_DECLARE(void) dav_send_one_response(dav_respon NULL); } - ap_fputs(output, bb, "" DEBUG_CR); + ap_fputs(r->output_filters, bb, "" DEBUG_CR); } @@ -559,7 +560,7 @@ DAV_DECLARE(void) dav_send_multistatus(request_rec for (; first != NULL; first = first->next) { apr_pool_clear(subpool); - dav_send_one_response(first, bb, r->output_filters, subpool); + dav_send_one_response(first, bb, r, subpool); } apr_pool_destroy(subpool); @@ -1189,7 +1190,7 @@ static void dav_stream_response(dav_walk_resource resp.propresult = *propstats; } - dav_send_one_response(&resp, ctx->bb, ctx->r->output_filters, pool); + dav_send_one_response(&resp, ctx->bb, ctx->r, pool); } Index: modules/dav/main/mod_dav.h =================================================================== --- modules/dav/main/mod_dav.h (revision 1757382) +++ modules/dav/main/mod_dav.h (working copy) @@ -546,7 +546,8 @@ typedef enum { /* Write a complete RESPONSE object out as a xml * element. Data is sent into brigade BB, which is auto-flushed into - * OUTPUT filter stack. Use POOL for any temporary allocations. + * the output filter stack for request R. Use POOL for any temporary + * allocations. * * [Presumably the tag has already been written; this * routine is shared by dav_send_multistatus and dav_stream_response.] @@ -553,7 +554,7 @@ typedef enum { */ DAV_DECLARE(void) dav_send_one_response(dav_response *response, apr_bucket_brigade *bb, - ap_filter_t *output, + request_rec *r, apr_pool_t *pool); /* Factorized helper function: prep request_rec R for a multistatus