httpd-38014

Version:

2.2.0

Bug link:

https://issues.apache.org/bugzilla/show_bug.cgi?id=38014

Symptom (Failure):

Wrong result. In keep-alive connections, when the client’s http request contains the header: “Expect: 100-continue”, then httpd returns wrong result (printing “HTTP/1.1 100 Continue” at the bottom of the webpage result).

How it is diagnosed:

Source analysis. We could not reproduce the failure.

Root Cause:

If client send "Expect: 100-Continue" request, it causes ap_http_filter to prepare "HTTP/1.1 100 Continue" and appends to a brigade. The issue is that httpd may already have started sending the headers/response. In this case, “100 Continue” is sent after the response.

In the fix "100 Continue" line is added only if eos_sent is 0 and send_bytes is 0. Unfortunately there is no field in request_rec, I found which states that response status is already sent.

They should have checked whether the actual response have been sent or not. Only send “HTTP/1.1 100 Continue” when the actual response has not been sent!

apr_status_t ap_proxy_http_process_response(... ...) {

   if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) {              

        do {

         rv = ap_get_brigade(rp->input_filters, bb,       <-- call filter

                              AP_MODE_READBYTES, mode,

                              conf->io_buffer_size);

        if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS <-- send data packet

                      || c->aborted) {

                      /* Ack! Phbtt! Die! User aborted! */

                    backend->close = 1;  /* this causes socket close below */

                      finish = TRUE;

                  }    

}

--- modules/http/http_filters.c        (revision 512953)

+++ modules/http/http_filters.c        (working copy)

@@ -185,7 +185,8 @@

   

        if ((ctx->state == BODY_CHUNK ||

            (ctx->state == BODY_LENGTH && ctx->remaining > 0)) &&

-            f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1)) {

+            f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1) &&

+            !(f->r->eos_sent || f->r->bytes_sent)) {

                // Send the: “HTTP/1.1 100 Continue

           tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",

                             ap_get_status_line(100), CRLF CRLF, NULL);

           bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); 

           e = apr_bucket_pool_create(tmp, strlen(tmp), f->r->pool,

                                      f->c->bucket_alloc);

           APR_BRIGADE_INSERT_HEAD(bb, e);

           e = apr_bucket_flush_create(f->c->bucket_alloc);

           APR_BRIGADE_INSERT_TAIL(bb, e);

           ap_pass_brigade(f->c->output_filters, bb);<-- send 100 continue

}

ap_pass_brigade (){

next->frec->filter_func.out_func(next, bb);    

}

In the buggy execution, when the client’s request is a keep-alive, where the response has already been sent, ‘f->r->eos_sent’ and ‘f->r->bytes_sent’ cannot be both 0 at the same time!

In this case, simply they should not send the “HTTP/1.1 100 continue”!

Is there any log message?:

No.

Can Errlog anticipate the error msg?

No..