summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2016-12-12 21:31:44 +0100
committerYann Ylavic <ylavic@apache.org>2016-12-12 21:31:44 +0100
commit366a562546a3ebb70a2be088665e93eb319cec8e (patch)
tree7129c22ed80043337c810e881ccfa93cbcbc9887
parentFollow up to r1773761: we need to check both ap_send_error_response() and int... (diff)
downloadapache2-366a562546a3ebb70a2be088665e93eb319cec8e.tar.xz
apache2-366a562546a3ebb70a2be088665e93eb319cec8e.zip
Follow up to r1773761: improved recursion detection.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1773865 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--modules/http/http_filters.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 65607df739..cdf793971a 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -687,6 +687,20 @@ static APR_INLINE int check_headers(request_rec *r)
apr_table_do(check_header, &ctx, r->err_headers_out, NULL);
}
+static int check_headers_recursion(request_rec *r)
+{
+ request_rec *rr;
+ for (rr = r; rr; rr = rr->prev) {
+ void *dying = NULL;
+ apr_pool_userdata_get(&dying, "check_headers_recursion", rr->pool);
+ if (dying) {
+ return 1;
+ }
+ }
+ apr_pool_userdata_setn("true", "check_headers_recursion", NULL, r->pool);
+ return 0;
+}
+
typedef struct header_struct {
apr_pool_t *pool;
apr_bucket_brigade *bb;
@@ -1192,7 +1206,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
header_filter_ctx *ctx = f->ctx;
const char *ctype;
ap_bucket_error *eb = NULL;
- void *dying = NULL;
int eos = 0;
AP_DEBUG_ASSERT(!r->main);
@@ -1208,7 +1221,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
}
}
else if (!ctx->headers_error && !check_headers(r)) {
- apr_pool_userdata_get(&dying, "http_header_filter_dying", r->pool);
ctx->headers_error = 1;
}
for (e = APR_BRIGADE_FIRST(b);
@@ -1249,14 +1261,13 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
apr_table_clear(r->headers_out);
apr_table_clear(r->err_headers_out);
- /* Don't try ErrorDocument if we are (internal-)redirect-ed or dying
- * already, otherwise we can end up in infinite recursion, better fall
- * through with 500, minimal headers and an empty body (EOS only).
+ /* Don't recall ap_die() if we come back here (from its own internal
+ * redirect or error response), otherwise we can end up in infinite
+ * recursion; better fall through with 500, minimal headers and an
+ * empty body (EOS only).
*/
- if (ap_is_initial_req(r) && !dying) {
+ if (!check_headers_recursion(r)) {
apr_brigade_cleanup(b);
- apr_pool_userdata_setn("true", "http_header_filter_dying",
- apr_pool_cleanup_null, r->pool);
ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
return AP_FILTER_ERROR;
}