From: Graham Leggett Date: Wed, 15 May 2013 15:46:01 +0000 (+0000) Subject: core: Stop ap_finalize_request_protocol() and ap_get_client_block() from silently X-Git-Tag: 2.5.0-alpha~5452 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=324994c36aa38992b80c81f0fde278b59130bad2;p=apache core: Stop ap_finalize_request_protocol() and ap_get_client_block() from silently 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 --- diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 9ce3752617..8fd7b61866 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -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. */ diff --git a/server/protocol.c b/server/protocol.c index 7745c1bdd7..9d63c44d6a 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -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); }