BUG/MEDIUM: h2/htx: never leave a trailers block alone with no EOM block

If when receiving an H2 response we fail to add an EOM block after too
large a trailers block, we must not leave the trailers block alone as it
violates the internal assumptions by not being followed by an EOM, even
when an error is reported. We must then make sure the error will safely
be reported to upper layers and that no attempt will be made to forward
partial blocks.

This must be backported to 1.9.
This commit is contained in:
Willy Tarreau 2019-05-07 11:17:32 +02:00
parent fb07b3f825
commit 2135f91d18
1 changed files with 10 additions and 2 deletions

View File

@ -3567,12 +3567,20 @@ static int h2c_decode_headers(struct h2c *h2c, struct buffer *rxbuf, uint32_t *f
if ((h2c->dff & H2_F_HEADERS_END_STREAM) || (msgf & H2_MSGF_RSP_1XX)) {
/* Mark the end of message, either using EOM in HTX or with the
* trailing CRLF after the end of trailers. Note that DATA_CHNK
* is not set during headers with END_STREAM.
* is not set during headers with END_STREAM. For HTX trailers,
* we must not leave an HTX trailers block not followed by an
* EOM block, the two must be atomic. Thus if we fail to emit
* the EOM block we must remove the TLR block we've just added.
*/
if (htx) {
if (!htx_add_endof(htx, HTX_BLK_EOM))
if (!htx_add_endof(htx, HTX_BLK_EOM)) {
struct htx_blk *tail = htx_get_tail_blk(htx);
if (tail && htx_get_blk_type(tail) == HTX_BLK_TLR)
htx_remove_blk(htx, tail);
goto fail;
}
}
else if (*flags & H2_SF_DATA_CHNK) {
if (!b_putblk(rxbuf, "\r\n", 2))
goto fail;