]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: proto-htx: Return an error if all headers cannot be received at once
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 21 Jan 2019 10:24:38 +0000 (11:24 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 23 Jan 2019 10:27:34 +0000 (11:27 +0100)
When an HTX stream is waiting for a request or a response, it reports an error
(400 for the request or 502 for the response) if a parsing error is reported by
the mux (HTX_FL_PARSING_ERROR). The mux-h1 uses this error, among other things,
when the headers are too big to be analyzed at once. But the mux-h2 doesn't. So
the stream must also report an error if the multiplexer is unable to emit all
headers at once. The multiplexers must always emit all the headers at once
otherwise it is an error.

There are 2 ways to detect this error:

  * The end-of-headers marker was not received yet _AND_ the HTX message is not
    empty.

  * The end-of-headers marker was not received yet _AND_ the multiplexer have
    some data to emit but it is waiting for more space in the channel's buffer.

Note the mux-h2 is buggy for now when HTX is enabled. It does not respect the
reserve. So there is no way to hit this bug.

This patch must be backported to 1.9.

src/proto_htx.c

index 9fa82065396296606a2b8285b0a481e826c3ba37..9e285f216a592db8879405d202192bff38cefeea 100644 (file)
@@ -126,9 +126,12 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
         */
        if (unlikely(htx_is_empty(htx) || htx_get_tail_type(htx) < HTX_BLK_EOH)) {
                /*
-                * First catch invalid request
+                * First catch invalid request because of a parsing error or
+                * because only part of headers have been transfered.
+                * Multiplexers have the responsibility to emit all headers at
+                * once.
                 */
-               if (htx->flags & HTX_FL_PARSING_ERROR) {
+               if ((htx->flags & HTX_FL_PARSING_ERROR) || htx_is_not_empty(htx) || (s->si[0].flags & SI_FL_RXBLK_ROOM)) {
                        stream_inc_http_req_ctr(s);
                        stream_inc_http_err_ctr(s);
                        proxy_inc_fe_req_ctr(sess->fe);
@@ -1086,7 +1089,7 @@ int htx_wait_for_request_body(struct stream *s, struct channel *req, int an_bit)
         * been received or if the buffer is full.
         */
        if (htx_get_tail_type(htx) >= HTX_BLK_EOD ||
-           htx_used_space(htx) + global.tune.maxrewrite >= htx->size)
+           channel_htx_full(req, htx, global.tune.maxrewrite))
                goto http_end;
 
  missing_data:
@@ -1457,9 +1460,14 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
         */
        if (unlikely(co_data(rep) || htx_is_empty(htx) || htx_get_tail_type(htx) < HTX_BLK_EOH)) {
                /*
-                * First catch invalid response
+                * First catch invalid response because of a parsing error or
+                * because only part of headers have been transfered.
+                * Multiplexers have the responsibility to emit all headers at
+                * once. We must be sure to have forwarded all outgoing data
+                * first.
                 */
-               if (htx->flags & HTX_FL_PARSING_ERROR)
+               if (!co_data(rep) &&
+                   ((htx->flags & HTX_FL_PARSING_ERROR) || htx_is_not_empty(htx) || (s->si[1].flags & SI_FL_RXBLK_ROOM)))
                        goto return_bad_res;
 
                /* 1: have we encountered a read error ? */