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;
 	}