Commit 932f1cda authored by Yann Ylavic's avatar Yann Ylavic
Browse files

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
parent f27caa6f
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -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;
        }