On Wed, Oct 21, 2015 at 2:29 PM, Ruediger Pluem <[email protected]> wrote:
>
> This looks like there is a stray \n in the input queue that causes httpd to
> think that there is a pipelined request.
I think we should tolerate blank lines in check_pipeline(), like
read_request_line() does (this is also a RFC compliance).
How about the following patch?
Index: modules/http/http_request.c
===================================================================
--- modules/http/http_request.c (revision 1709107)
+++ modules/http/http_request.c (working copy)
@@ -228,24 +228,50 @@ AP_DECLARE(void) ap_die(int type, request_rec *r)
ap_die_r(type, r, r->status);
}
-static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb)
+static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb,
+ int max_blank_lines)
{
+ c->data_in_input_filters = 0;
if (c->keepalive != AP_CONN_CLOSE && !c->aborted) {
apr_status_t rv;
+ int num_blank_lines = 0;
+ char ch, cr = 0;
+ apr_size_t n;
- AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(bb));
- rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE,
- APR_NONBLOCK_READ, 1);
- if (rv != APR_SUCCESS || APR_BRIGADE_EMPTY(bb)) {
- /*
- * Error or empty brigade: There is no data present in the input
- * filter
- */
- c->data_in_input_filters = 0;
+ do {
+ apr_brigade_cleanup(bb);
+ rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE,
+ APR_NONBLOCK_READ, 1);
+ if (rv != APR_SUCCESS || APR_BRIGADE_EMPTY(bb)) {
+ /*
+ * Error or empty brigade: There is no data present
in the input
+ * filter
+ */
+ c->data_in_input_filters = 0;
+ break;
+ }
+
+ n = 0;
+ apr_brigade_flatten(bb, &ch, &n);
+ if (!n) {
+ break;
+ }
+ if (ch == APR_ASCII_LF) {
+ num_blank_lines++;
+ cr = 0;
+ }
+ else if (!cr && ch == APR_ASCII_CR) {
+ cr = 1;
+ }
+ else {
+ c->data_in_input_filters = 1;
+ break;
+ }
+ } while (num_blank_lines < max_blank_lines);
+
+ if (num_blank_lines >= max_blank_lines) {
+ c->keepalive = AP_CONN_CLOSE;
}
- else {
- c->data_in_input_filters = 1;
- }
}
}
@@ -255,7 +281,12 @@ AP_DECLARE(void) ap_process_request_after_handler(
apr_bucket_brigade *bb;
apr_bucket *b;
conn_rec *c = r->connection;
+ int max_blank_lines = r->server->limit_req_fields;
+ if (max_blank_lines <= 0) {
+ max_blank_lines = DEFAULT_LIMIT_REQUEST_FIELDS;
+ }
+
/* Send an EOR bucket through the output filter chain. When
* this bucket is destroyed, the request will be logged and
* its pool will be freed
@@ -279,7 +310,7 @@ AP_DECLARE(void) ap_process_request_after_handler(
* already by the EOR bucket's cleanup function.
*/
- check_pipeline(c, bb);
+ check_pipeline(c, bb, max_blank_lines);
apr_brigade_destroy(bb);
if (c->cs)
c->cs->state = (c->aborted) ? CONN_STATE_LINGER
--
Regards,
Yann.