From ac20389f3c816d990aba21720f1492b69ac5cb44 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Wed, 3 Apr 2024 12:12:23 +0000
Subject: [PATCH] header validation after content-* are eval'ed

backport r1916770 from trunk
Submitted By: ylavic




git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1916778 13f79535-47bb-0310-9956-ffa450edef68
---
 modules/http/http_filters.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

Index: apache2-2.4.29/modules/http/http_filters.c
===================================================================
--- apache2-2.4.29.orig/modules/http/http_filters.c
+++ apache2-2.4.29/modules/http/http_filters.c
@@ -1337,6 +1337,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
          */
         apr_table_clear(r->headers_out);
         apr_table_clear(r->err_headers_out);
+        r->content_type = r->content_encoding = NULL;
+        r->content_languages = NULL;
+        r->clength = r->chunked = 0;
         apr_brigade_cleanup(b);
 
         /* Don't recall ap_die() if we come back here (from its own internal
@@ -1353,8 +1356,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
         APR_BRIGADE_INSERT_TAIL(b, e);
         e = apr_bucket_eos_create(c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(b, e);
-        r->content_type = r->content_encoding = NULL;
-        r->content_languages = NULL;
         ap_set_content_length(r, 0);
         recursive_error = 1;
     }
@@ -1381,6 +1382,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
     if (!apr_is_empty_table(r->err_headers_out)) {
         r->headers_out = apr_table_overlay(r->pool, r->err_headers_out,
                                            r->headers_out);
+        apr_table_clear(r->err_headers_out);
     }
 
     /*
@@ -1400,6 +1402,17 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
         fixup_vary(r);
     }
 
+
+    /*
+     * Control cachability for non-cacheable responses if not already set by
+     * some other part of the server configuration.
+     */
+    if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {
+        char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
+        ap_recent_rfc822_date(date, r->request_time);
+        apr_table_addn(r->headers_out, "Expires", date);
+    }
+
     /*
      * Now remove any ETag response header field if earlier processing
      * says so (such as a 'FileETag None' directive).
@@ -1412,6 +1425,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
     basic_http_header_check(r, &protocol);
     ap_set_keepalive(r);
 
+    /* 204/304 responses don't have content related headers */
     if (AP_STATUS_IS_HEADER_ONLY(r->status)) {
         apr_table_unset(r->headers_out, "Transfer-Encoding");
         apr_table_unset(r->headers_out, "Content-Length");
@@ -1454,16 +1468,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
         apr_table_setn(r->headers_out, "Content-Language", field);
     }
 
-    /*
-     * Control cachability for non-cacheable responses if not already set by
-     * some other part of the server configuration.
-     */
-    if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {
-        char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
-        ap_recent_rfc822_date(date, r->request_time);
-        apr_table_addn(r->headers_out, "Expires", date);
-    }
-
     /* This is a hack, but I can't find anyway around it.  The idea is that
      * we don't want to send out 0 Content-Lengths if it is a head request.
      * This happens when modules try to outsmart the server, and return
