From 485da0b0535cc575ed8d4f3bf407e9101dbb80aa Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 8 Oct 2021 08:56:00 +0200 Subject: [PATCH] BUG/MEDIUM: mux_h2: Handle others remaining read0 cases on partial frames We've found others places where the read0 is ignored because of an incomplete frame parsing. This time, it happens during parsing of CONTINUATION frames. When frames are parsed, incomplete frames are properly handled and H2_CF_DEM_SHORT_READ flag is set. It is also true for HEADERS frames. However, for CONTINUATION frames, there is an exception. Besides parsing the current frame, we try to peek header of the next one to merge payload of both frames, the current one and the next one. Idea is to create a sole HEADERS frame before parsing the payload. However, in this case, it is possible to have an incomplete frame too, not the current one but the next one. From the demux point of view, the current frame is complete. We must go to the internal function h2c_decode_headers() to detect an incomplete frame. And this case was not identified and fixed when H2_CF_DEM_SHORT_READ flag was introduced in the commit b5f7b5296 ("BUG/MEDIUM: mux-h2: Handle remaining read0 cases on partial frames") This bug was reported in a comment of the issue #1362. The patch must be backported as far as 2.0. --- src/mux_h2.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mux_h2.c b/src/mux_h2.c index ce56058b15..150a559067 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -2668,8 +2668,12 @@ static struct h2s *h2c_frt_handle_headers(struct h2c *h2c, struct h2s *h2s) if (h2c->st0 >= H2_CS_ERROR) goto out; - if (error == 0) + if (error == 0) { + /* Demux not blocked because of the stream, it is an incomplete frame */ + if (!(h2c->flags &H2_CF_DEM_BLOCK_ANY)) + h2c->flags |= H2_CF_DEM_SHORT_READ; goto out; // missing data + } if (error < 0) { /* Failed to decode this frame (e.g. too large request) @@ -2706,8 +2710,12 @@ static struct h2s *h2c_frt_handle_headers(struct h2c *h2c, struct h2s *h2s) goto out; if (error <= 0) { - if (error == 0) + if (error == 0) { + /* Demux not blocked because of the stream, it is an incomplete frame */ + if (!(h2c->flags &H2_CF_DEM_BLOCK_ANY)) + h2c->flags |= H2_CF_DEM_SHORT_READ; goto out; // missing data + } /* Failed to decode this stream (e.g. too large request) * but the HPACK decompressor is still synchronized. @@ -2825,8 +2833,12 @@ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s) } if (error <= 0) { - if (error == 0) + if (error == 0) { + /* Demux not blocked because of the stream, it is an incomplete frame */ + if (!(h2c->flags &H2_CF_DEM_BLOCK_ANY)) + h2c->flags |= H2_CF_DEM_SHORT_READ; goto fail; // missing data + } /* stream error : send RST_STREAM */ TRACE_ERROR("couldn't decode response HEADERS", H2_EV_RX_FRAME|H2_EV_RX_HDR, h2c->conn, h2s); -- 2.39.5