From d1ecb963ed52f7a480817cb0dac0d7106bedbb4f Mon Sep 17 00:00:00 2001 From: Evgeny Kotkov Date: Mon, 10 Oct 2016 09:40:06 +0000 Subject: [PATCH] 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. This patch changes the signature of the existing mod_dav's public API, dav_send_one_response(), because this API is not yet a part of any 2.4.x release. * 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 definition. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1764040 13f79535-47bb-0310-9956-ffa450edef68 --- modules/dav/main/mod_dav.c | 27 ++++++++++++++------------- modules/dav/main/mod_dav.h | 5 +++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c index 33cb61d070..1a1730e53e 100644 --- a/modules/dav/main/mod_dav.c +++ b/modules/dav/main/mod_dav.c @@ -438,30 +438,31 @@ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri) /* 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.] */ 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_response *response, * 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_response *response, 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,14 +491,14 @@ DAV_DECLARE(void) dav_send_one_response(dav_response *response, * 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, 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 *r, int status, 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 *wres, 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); } diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h index dec6c86d22..9e64e0589b 100644 --- a/modules/dav/main/mod_dav.h +++ b/modules/dav/main/mod_dav.h @@ -546,14 +546,15 @@ 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.] */ 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 -- 2.40.0