]> granicus.if.org Git - apache/commitdiff
core: Stop ap_finalize_request_protocol() and ap_get_client_block() from silently
authorGraham Leggett <minfrin@apache.org>
Wed, 15 May 2013 15:46:01 +0000 (15:46 +0000)
committerGraham Leggett <minfrin@apache.org>
Wed, 15 May 2013 15:46:01 +0000 (15:46 +0000)
swallowing errors from the filter stack, create error buckets and return them
appropriately.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1482918 13f79535-47bb-0310-9956-ffa450edef68

modules/http/http_filters.c
server/protocol.c

index 9ce3752617ef5fa3ce03895ec21a083d168d60d7..8fd7b61866bbe2dd50062cf60e93878a1bf30531 100644 (file)
@@ -203,7 +203,6 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
     http_ctx_t *ctx = f->ctx;
     apr_status_t rv;
     apr_off_t totalread;
-    int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
     apr_bucket_brigade *bb;
 
     /* just get out of the way of things we don't want. */
@@ -360,7 +359,6 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
                     ctx->remaining = get_chunk_size(ctx->chunk_ln);
                     if (ctx->remaining == INVALID_CHAR) {
                         rv = APR_EGENERAL;
-                        http_error = HTTP_BAD_REQUEST;
                     }
                 }
             }
@@ -370,6 +368,9 @@ 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)" : "");
+                if (ctx->remaining < 0) {
+                    rv = APR_ENOSPC;
+                }
                 ctx->remaining = 0; /* Reset it in case we have to
                                      * come back here later */
                 return rv;
@@ -462,7 +463,6 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
                             ctx->remaining = get_chunk_size(ctx->chunk_ln);
                             if (ctx->remaining == INVALID_CHAR) {
                                 rv = APR_EGENERAL;
-                                http_error = HTTP_BAD_REQUEST;
                             }
                         }
                     }
@@ -473,6 +473,9 @@ 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)" : "");
+                    if (ctx->remaining < 0) {
+                        rv = APR_ENOSPC;
+                    }
                     ctx->remaining = 0; /* Reset it in case we have to
                                          * come back here later */
                     return rv;
@@ -1410,6 +1413,9 @@ AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status)
     case AP_FILTER_ERROR: {
         return AP_FILTER_ERROR;
     }
+    case APR_EGENERAL: {
+        return HTTP_BAD_REQUEST;
+    }
     case APR_ENOSPC: {
         return HTTP_REQUEST_ENTITY_TOO_LARGE;
     }
@@ -1637,6 +1643,28 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer,
      * not be used.
      */
     if (rv != APR_SUCCESS) {
+        apr_bucket *e;
+
+        /* work around our silent swallowing of error messages by mapping
+         * error codes at this point, and sending an error bucket back
+         * upstream.
+         */
+        apr_brigade_cleanup(bb);
+
+        e = ap_bucket_error_create(
+                ap_map_http_request_error(rv, HTTP_BAD_REQUEST), NULL, r->pool,
+                r->connection->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb, e);
+
+        e = apr_bucket_eos_create(r->connection->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb, e);
+
+        rv = ap_pass_brigade(r->output_filters, bb);
+        if (APR_SUCCESS != rv) {
+            ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r, APLOGNO()
+                          "Error while writing error response");
+        }
+
         /* if we actually fail here, we want to just return and
          * stop trying to read data from the client.
          */
index 7745c1bdd7638553cf00648f07dac218f172be4a..9d63c44d6abcc3b1f011ebb0f135231998ffd6b5 100644 (file)
@@ -1282,6 +1282,21 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew,
     rnew->main = (request_rec *) r;
 }
 
+static void error_output_stream(request_rec *r, int status)
+{
+    conn_rec *c = r->connection;
+    apr_bucket_brigade *bb;
+    apr_bucket *b;
+
+    bb = apr_brigade_create(r->pool, c->bucket_alloc);
+    b = ap_bucket_error_create(status, NULL, r->pool,
+            r->connection->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+    b = apr_bucket_eos_create(c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+    ap_pass_brigade(r->output_filters, bb);
+}
+
 static void end_output_stream(request_rec *r)
 {
     conn_rec *c = r->connection;
@@ -1309,9 +1324,12 @@ AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub)
  */
 AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
 {
-    (void) ap_discard_request_body(r);
+    int status = ap_discard_request_body(r);
 
     /* tell the filter chain there is no more content coming */
+    if (status) {
+        error_output_stream(r, status);
+    }
     if (!r->eos_sent) {
         end_output_stream(r);
     }