|
|
- commit 9a408abbb8559df5718bc696bd9c3934c6500d63
- Author: Willy Tarreau <w@1wt.eu>
- Date: Fri Aug 23 08:11:36 2019 +0200
-
- BUG/MEDIUM: mux-h1: do not truncate trailing 0CRLF on buffer boundary
-
- The H1 message parser calls the various message block parsers with an
- offset indicating where in the buffer to start from, and only consumes
- the data at the end of the parsing. The headers and trailers parsers
- have a condition detecting if a headers or trailers block is too large
- to fit into the buffer. This is detected by an incomplete block while
- the buffer is full. Unfortunately it doesn't take into account the fact
- that the block may be parsed after other blocks that are still present
- in the buffer, resulting in aborting some transfers early as reported
- in issue #231. This typically happens if a trailers block is incomplete
- at the end of a buffer full of data, which typically happens with data
- sizes multiple of the buffer size minus less than the trailers block
- size. It also happens with the CRLF that follows the 0-sized chunk of
- any transfer-encoded contents is itself on such a boundary since this
- CRLF is technically part of the trailers block. This can be reproduced
- by asking a server to retrieve exactly 31532 or 31533 bytes of static
- data using chunked encoding with curl, which reports:
-
- transfer closed with outstanding read data remaining
-
- This issue was revealed in 2.0 and does not affect 1.9 because in 1.9
- the trailers block was processed at once as part of the data block
- processing, and would simply give up and wait for the rest of the data
- to arrive.
-
- It's interesting to note that the headers block parsing is also affected
- by this issue but in practice it has a much more limited impact since a
- headers block is normally only parsed at the beginning of a buffer. The
- only case where it seems to matter is when dealing with a response buffer
- full of 100-continue header blocks followed by a regular header block,
- which will then be rejected for the same reason.
-
- This fix must be backported to 2.0 and partially to 1.9 (the headers
- block part).
-
- (cherry picked from commit 347f464d4e5a8a2bf3acd2411a6c8228e605e7f6)
- Signed-off-by: Willy Tarreau <w@1wt.eu>
-
- diff --git a/src/mux_h1.c b/src/mux_h1.c
- index fa694c41..01f225a2 100644
- --- a/src/mux_h1.c
- +++ b/src/mux_h1.c
- @@ -995,10 +995,11 @@ static size_t h1_process_headers(struct h1s *h1s, struct h1m *h1m, struct htx *h
- ret = h1_headers_to_hdr_list(b_peek(buf, *ofs), b_tail(buf),
- hdrs, sizeof(hdrs)/sizeof(hdrs[0]), h1m, &h1sl);
- if (ret <= 0) {
- - /* Incomplete or invalid message. If the buffer is full, it's an
- - * error because headers are too large to be handled by the
- - * parser. */
- - if (ret < 0 || (!ret && !buf_room_for_htx_data(buf)))
- + /* Incomplete or invalid message. If the input buffer only
- + * contains headers and is full, which is detected by it being
- + * full and the offset to be zero, it's an error because
- + * headers are too large to be handled by the parser. */
- + if (ret < 0 || (!ret && !*ofs && !buf_room_for_htx_data(buf)))
- goto error;
- goto end;
- }
- @@ -1339,10 +1340,11 @@ static size_t h1_process_trailers(struct h1s *h1s, struct h1m *h1m, struct htx *
- ret = h1_headers_to_hdr_list(b_peek(buf, *ofs), b_tail(buf),
- hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &tlr_h1m, NULL);
- if (ret <= 0) {
- - /* Incomplete or invalid trailers. If the buffer is full, it's
- - * an error because traliers are too large to be handled by the
- - * parser. */
- - if (ret < 0 || (!ret && !buf_room_for_htx_data(buf)))
- + /* Incomplete or invalid trailers. If the input buffer only
- + * contains trailers and is full, which is detected by it being
- + * full and the offset to be zero, it's an error because
- + * trailers are too large to be handled by the parser. */
- + if (ret < 0 || (!ret && !*ofs && !buf_room_for_htx_data(buf)))
- goto error;
- goto end;
- }
|