]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
core: Detect incomplete request and response bodies, log an error and
authorWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 22 Aug 2014 11:41:43 +0000 (11:41 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 22 Aug 2014 11:41:43 +0000 (11:41 +0000)
forward it to the underlying filters.

PR: 55475
Submitted by: Yann Ylavic
Reviewed by: ylavic, wrowe, rpluem
Backports: r1538776

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1619754 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/http/http_filters.c

diff --git a/CHANGES b/CHANGES
index 0a232afd79f309472bee418ca78deba0a21abfb5..46d9ad04cd8443c0309a55f37ef851bf75cfe925 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -50,6 +50,9 @@ Changes with Apache 2.2.28
      and that coincides with the end of stream ("Zlib error flushing inflate
      buffer"). PR 56196. [Christoph Fausak <christoph fausak glueckkanja.com>]
 
+  *) core: Detect incomplete request and response bodies, log an error and
+     forward it to the underlying filters. PR 55475.  [Yann Ylavic]
+
   *) mod_cache, mod_disk_cache: With CacheLock enabled, responses with a Vary 
      header might not get the benefit of the thundering herd protection due to 
      an incorrect internal cache key.  PR 50317. 
index b7c35c62715dbd36e4482476401cdf058d6d2317..0c4b67a05b2a184dc230e4cd15b51052af51d9d4 100644 (file)
@@ -85,6 +85,23 @@ static apr_status_t bail_out_on_error(http_ctx_t *ctx,
     apr_bucket_brigade *bb = ctx->bb;
 
     apr_brigade_cleanup(bb);
+
+    if (f->r->proxyreq == PROXYREQ_RESPONSE) {
+        switch (http_error) {
+        case HTTP_REQUEST_ENTITY_TOO_LARGE:
+            return APR_ENOSPC;
+
+        case HTTP_REQUEST_TIME_OUT:
+            return APR_INCOMPLETE;
+
+        case HTTP_NOT_IMPLEMENTED:
+            return APR_ENOTIMPL;
+
+        default:
+            return APR_EGENERAL;
+        }
+    }
+
     e = ap_bucket_error_create(http_error,
                                NULL, f->r->pool,
                                f->c->bucket_alloc);
@@ -441,11 +458,11 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
             if (rv != APR_SUCCESS || ctx->remaining < 0) {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading first chunk %s ", 
                               (ctx->remaining < 0) ? "(overflow)" : "");
-                ctx->remaining = 0; /* Reset it in case we have to
-                                     * come back here later */
-                if (APR_STATUS_IS_TIMEUP(rv)) { 
+                if (APR_STATUS_IS_TIMEUP(rv) || ctx->remaining > 0) {
                     http_error = HTTP_REQUEST_TIME_OUT;
                 }
+                ctx->remaining = 0; /* Reset it in case we have to
+                                     * come back here later */
                 return bail_out_on_error(ctx, f, http_error);
             }
 
@@ -489,6 +506,9 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
                         return APR_EAGAIN;
                     }
                     /* If we get an error, then leave */
+                    if (rv == APR_EOF) {
+                        return APR_INCOMPLETE;
+                    }
                     if (rv != APR_SUCCESS) {
                         return rv;
                     }
@@ -542,11 +562,11 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
                 if (rv != APR_SUCCESS || ctx->remaining < 0) {
                     ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading chunk %s ", 
                                   (ctx->remaining < 0) ? "(overflow)" : "");
-                    ctx->remaining = 0; /* Reset it in case we have to
-                                         * come back here later */
-                    if (APR_STATUS_IS_TIMEUP(rv)) { 
+                    if (APR_STATUS_IS_TIMEUP(rv) || ctx->remaining > 0) {
                         http_error = HTTP_REQUEST_TIME_OUT;
                     }
+                    ctx->remaining = 0; /* Reset it in case we have to
+                                         * come back here later */
                     return bail_out_on_error(ctx, f, http_error);
                 }
 
@@ -569,6 +589,10 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
 
     rv = ap_get_brigade(f->next, b, mode, block, readbytes);
 
+    if (rv == APR_EOF && ctx->state != BODY_NONE &&
+            ctx->remaining > 0) {
+        return APR_INCOMPLETE;
+    }
     if (rv != APR_SUCCESS) {
         return rv;
     }
@@ -584,8 +608,10 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
         ctx->remaining -= totalread;
         if (ctx->remaining > 0) {
             e = APR_BRIGADE_LAST(b);
-            if (APR_BUCKET_IS_EOS(e))
-                return APR_EOF;
+            if (APR_BUCKET_IS_EOS(e)) {
+                apr_bucket_delete(e);
+                return APR_INCOMPLETE;
+            }
         }
     }