diff options
author | Yann Ylavic <ylavic@apache.org> | 2015-10-22 23:19:52 +0200 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2015-10-22 23:19:52 +0200 |
commit | 2590be058730f7f101b335ce0c4a3893c4651f87 (patch) | |
tree | a82b38e6a2bd82ee43ced634264c7828165482b4 /modules/http | |
parent | core: Limit to ten the number of tolerated empty lines between request, (diff) | |
download | apache2-2590be058730f7f101b335ce0c4a3893c4651f87.tar.xz apache2-2590be058730f7f101b335ce0c4a3893c4651f87.zip |
core: follow up to r1710095.
Simplify logic in check_pipeline(), and log unexpected errors.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1710105 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http')
-rw-r--r-- | modules/http/http_request.c | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 1e524e0850..07f1d0c3e1 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -234,20 +234,25 @@ static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb) if (c->keepalive != AP_CONN_CLOSE && !c->aborted) { apr_status_t rv; int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES; - char buf[2], cr = 0; - apr_size_t len; + ap_input_mode_t mode = AP_MODE_SPECULATIVE; + apr_size_t len, cr = 0; + char buf[2]; do { - const apr_size_t n = (cr) ? 2 : 1; - apr_brigade_cleanup(bb); - rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE, - APR_NONBLOCK_READ, n); + rv = ap_get_brigade(c->input_filters, bb, mode, + APR_NONBLOCK_READ, cr + 1); if (rv != APR_SUCCESS || APR_BRIGADE_EMPTY(bb)) { /* * Error or empty brigade: There is no data present in the input * filter */ + if (mode == AP_MODE_READBYTES) { + /* Unexpected error, stop with this connection */ + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(02967) + "Can't consume pipelined empty lines"); + c->keepalive = AP_CONN_CLOSE; + } return; } @@ -257,29 +262,48 @@ static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb) * pending response(s) until the next/real request comes in or the * keepalive timeout expires. */ - len = n; + len = cr + 1; rv = apr_brigade_flatten(bb, buf, &len); - if (rv != APR_SUCCESS || len != n) { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, - "check pipeline can't fetch CRLF " - "(%" APR_SIZE_T_FMT "/%" APR_SIZE_T_FMT ")", - len, n); - c->data_in_input_filters = 1; + if (rv != APR_SUCCESS || len != cr + 1) { + int level; + if (mode == AP_MODE_READBYTES) { + /* Unexpected error, stop with this connection */ + c->keepalive = AP_CONN_CLOSE; + level = APLOG_ERR; + } + else { + /* Let outside (non-speculative/blocking) read determine + * where this possible failure comes from (metadata, + * morphed EOF socket => empty bucket? debug only here). + */ + c->data_in_input_filters = 1; + level = APLOG_DEBUG; + } + ap_log_cerror(APLOG_MARK, level, rv, c, APLOGNO(02968) + "Can't check pipelined data"); return; } + + if (mode == AP_MODE_READBYTES) { + mode = AP_MODE_SPECULATIVE; + cr = 0; + continue; + } + if (cr) { AP_DEBUG_ASSERT(len == 2 && buf[0] == APR_ASCII_CR); if (buf[1] != APR_ASCII_LF) { return; } + mode = AP_MODE_READBYTES; num_blank_lines--; - cr = 0; } else { if (buf[0] == APR_ASCII_CR) { cr = 1; } else if (buf[0] == APR_ASCII_LF) { + mode = AP_MODE_READBYTES; num_blank_lines--; } else { @@ -287,23 +311,6 @@ static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb) return; } } - if (!cr) { - /* Consume this [CR]LF, then next */ - apr_brigade_cleanup(bb); - rv = ap_get_brigade(c->input_filters, bb, AP_MODE_READBYTES, - APR_NONBLOCK_READ, n); - if (rv == APR_SUCCESS) { - rv = apr_brigade_flatten(bb, buf, &len); - } - if (rv != APR_SUCCESS || len != n) { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, - "check pipeline can't read CRLF " - "(%" APR_SIZE_T_FMT "/%" APR_SIZE_T_FMT ")", - len, n); - c->data_in_input_filters = 1; - return; - } - } } while (num_blank_lines >= 0); /* Don't recycle this (abused) connection */ |