1 commit 96b88f2e605e76f2a472cf9fa83398ff242d47bb
2 Author: Christopher Faulet <cfaulet@haproxy.com>
3 Date: Mon Sep 23 15:28:20 2019 +0200
5 BUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame
7 As stated in the RFC7540#5.1, an endpoint that receives any frame other than
8 PRIORITY after receiving a RST_STREAM MUST treat that as a stream error of type
9 STREAM_CLOSED. However, frames carrying compression state must still be
10 processed before being dropped to keep the HPACK decoder synchronized. This had
11 to be the purpose of the commit 8d9ac3ed8b ("BUG/MEDIUM: mux-h2: do not abort
12 HEADERS frame before decoding them"). But, the test on the frame type was
15 This bug is major because desynchronizing the HPACK decoder leads to mixup
16 indexed headers in messages. From the time an HEADERS frame is received and
17 ignored for a closed stream, wrong headers may be sent to the following streams.
19 This patch may fix several bugs reported on github (#116, #290, #292). It must
20 be backported to 2.0 and 1.9.
22 (cherry picked from commit 6884aa3eb00d1a5eb6f9c81a3a00288c13652938)
23 Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
25 diff --git a/src/mux_h2.c b/src/mux_h2.c
26 index e6bfd03d..eb773a26 100644
29 @@ -2106,6 +2106,9 @@ static struct h2s *h2c_frt_handle_headers(struct h2c *h2c, struct h2s *h2s)
31 static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s)
33 + struct buffer rxbuf = BUF_NULL;
34 + unsigned long long body_len = 0;
38 if (!b_size(&h2c->dbuf))
39 @@ -2114,7 +2117,18 @@ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s)
40 if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
41 return NULL; // incomplete frame
43 - error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len);
44 + if (h2s->st != H2_SS_CLOSED) {
45 + error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len);
48 + /* the connection was already killed by an RST, let's consume
49 + * the data and send another RST.
51 + error = h2c_decode_headers(h2c, &rxbuf, &flags, &body_len);
52 + h2s_error(h2s, H2_ERR_STREAM_CLOSED);
53 + h2c->st0 = H2_CS_FRAME_E;
57 /* unrecoverable error ? */
58 if (h2c->st0 >= H2_CS_ERROR)
59 @@ -2150,6 +2164,15 @@ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s)
65 + /* make the demux send an RST for the current stream. We may only
66 + * do this if we're certain that the HEADERS frame was properly
67 + * decompressed so that the HPACK decoder is still kept up to date.
69 + h2_release_buf(h2c, &rxbuf);
70 + h2c->st0 = H2_CS_FRAME_E;
74 /* processes a DATA frame. Returns > 0 on success or zero on missing data.
75 @@ -2459,7 +2482,7 @@ static void h2_process_demux(struct h2c *h2c)
79 - if (h2s->flags & H2_SF_RST_RCVD && h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK) {
80 + if (h2s->flags & H2_SF_RST_RCVD && !(h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK)) {
81 /* RFC7540#5.1:closed: an endpoint that
82 * receives any frame other than PRIORITY after
83 * receiving a RST_STREAM MUST treat that as a