]> granicus.if.org Git - apache/commitdiff
* core: Detect incomplete body in HTTP input filter and return
authorJim Jagielski <jim@apache.org>
Thu, 20 Feb 2014 19:37:09 +0000 (19:37 +0000)
committerJim Jagielski <jim@apache.org>
Thu, 20 Feb 2014 19:37:09 +0000 (19:37 +0000)
              APR_INCOMPLETE. PR 55475.
     trunk patch: http://svn.apache.org/r1538776
          2.4.x patch: https://people.apache.org/~ylavic/2.4.x-http_filter_incomplete.patch

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

modules/http/http_filters.c

index c72741945372357a1678533c05722f620d4f4b37..564303c1c38857af8f35cbfb9ac24142aff322d8 100644 (file)
@@ -87,6 +87,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);
@@ -394,11 +411,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_INFO, rv, f->r, APLOGNO(01589) "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);
             }
 
@@ -447,6 +464,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;
                     }
@@ -500,11 +520,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_INFO, rv, f->r, APLOGNO(01590) "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);
                 }
 
@@ -532,6 +552,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;
     }
@@ -547,8 +571,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;
+            }
         }
     }