Commit 9bd73bf6 authored by Justin Erenkrantz's avatar Justin Erenkrantz
Browse files

Correctly return 413 when an invalid chunk size is given on input.

- If get_chunk_size() returns a negative number, that probably implies
  an overflow.  So, create a 413 error and pass it to the output filters.
- Modify ap_discard_request_body() to return OK quickly if we're a subreq
  or our status code implies that we will be dropping the connection.
- Modify ap_die() so that if the new status implies that we will drop
  the connection, that we correctly indicate that we can not keepalive
  this connection.  (Without this, the error is returned, but the connection
  is not closed.)


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95331 13f79535-47bb-0310-9956-ffa450edef68
parent a92d1180
Loading
Loading
Loading
Loading
+5 −0
Changes for CHANGES: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
Changes with Apache 2.0.37
  *) Correctly return 413 when an invalid chunk size is given on
     input.  Also modify ap_discard_request_body to not do anything
     on sub-requests or when the connection will be dropped.
     [Justin Erenkrantz]
  *) Fix the TIME_* SSL var lookups to be threadsafe.  PR 9469.
     [Cliff Woolley]
+33 −0
Changes for modules/http/http_protocol.c: 33 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -852,6 +852,17 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
            apr_brigade_flatten(bb, line, &len);

            ctx->remaining = get_chunk_size(line);
            /* Detect invalid chunk sizes. */
            if (ctx->remaining < 0) {
                apr_brigade_cleanup(bb);
                e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
                                           f->r->connection->pool,
                                           f->r->connection->bucket_alloc);
                APR_BRIGADE_INSERT_TAIL(bb, e);
                e = apr_bucket_eos_create(f->r->connection->bucket_alloc);
                APR_BRIGADE_INSERT_TAIL(bb, e);
                return ap_pass_brigade(f->r->output_filters, bb);
            }
        } 
    }

@@ -890,6 +901,17 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
                apr_brigade_flatten(bb, line, &len);
                ctx->remaining = get_chunk_size(line);

                /* Detect invalid chunk sizes. */
                if (ctx->remaining < 0) {
                    apr_brigade_cleanup(bb);
                    e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE,
                                               NULL, c->pool, c->bucket_alloc);
                    APR_BRIGADE_INSERT_TAIL(bb, e);
                    e = apr_bucket_eos_create(c->bucket_alloc);
                    APR_BRIGADE_INSERT_TAIL(bb, e);
                    return ap_pass_brigade(f->r->output_filters, bb);
                }

                if (!ctx->remaining) {
                    /* Handle trailers by calling ap_get_mime_headers again! */
                    ctx->state = BODY_NONE;
@@ -1777,6 +1799,17 @@ AP_DECLARE(int) ap_discard_request_body(request_rec *r)
{
    int rv;

    /* Sometimes we'll get in a state where the input handling has
     * detected an error where we want to drop the connection, so if
     * that's the case, don't read the data as that is what we're trying
     * to avoid.
     *
     * This function is also a no-op on a subrequest.
     */
    if (r->main || ap_status_drops_connection(r->status)) {
        return OK;
    }

    if (r->read_length == 0) {  /* if not read already */
        if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) {
            return rv;
+9 −6
Changes for modules/http/http_request.c: 9 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -139,13 +139,16 @@ AP_DECLARE(void) ap_die(int type, request_rec *r)
        r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
    }

    /*
     * If we want to keep the connection, be sure that the request body
     * (if any) has been read.
    /* If we don't want to keep the connection, make sure we mark that the
     * connection is not eligible for keepalive.  If we want to keep the
     * connection, be sure that the request body (if any) has been read.
     */
    if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
        && !ap_status_drops_connection(r->status)
        && r->connection && (r->connection->keepalive != -1)) {
    if (ap_status_drops_connection(r->status)) {
        r->connection->keepalive = 0;
    }
    else if ((r->status != HTTP_NOT_MODIFIED) &&
             (r->status != HTTP_NO_CONTENT) &&
             r->connection && (r->connection->keepalive != -1)) {

        (void) ap_discard_request_body(r);
    }