Skip to content

Commit ba7dc46

Browse files
committed
BUG/MINOR: h2/h3: Never insert partial headers/trailers in an HTX message
In HTX, headers and trailers parts must always be complete. It is unexpected to found header blocks without the EOH block or trailer blocks without the EOT block. So, during H2/H3 message parsing, we must take care to remove any HEADER/TRAILER block inserted when an error is encountered. It is mandatory to be sure to properly report parsing error to upper layer.x It is now performed by calling htx_truncat_blk() function on the error path. The tail block is saved before converting any HEADERS/TRAILERS frame to HTX. It is used to remove all inserted block on error. This patch rely on the following one: "MINOR: htx: Add function to truncate all blocks after a specific block" It should be backported with the commit above to all stable versions for the H2 part and as far as 2.8 for h3 one.
1 parent fbdb0a9 commit ba7dc46

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

src/h2.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr,
319319
*/
320320
int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len, int relaxed)
321321
{
322+
struct htx_blk *tailblk = htx_get_tail_blk(htx);
322323
struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
323324
uint32_t fields; /* bit mask of H2_PHDR_FND_* */
324325
uint32_t idx;
@@ -533,6 +534,7 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
533534
return ret;
534535

535536
fail:
537+
htx_truncate_blk(htx, tailblk);
536538
return -1;
537539
}
538540

@@ -637,6 +639,7 @@ static struct htx_sl *h2_prepare_htx_stsline(uint32_t fields, struct ist *phdr,
637639
*/
638640
int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len, char *upgrade_protocol)
639641
{
642+
struct htx_blk *tailblk = htx_get_tail_blk(htx);
640643
struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
641644
uint32_t fields; /* bit mask of H2_PHDR_FND_* */
642645
uint32_t idx;
@@ -793,6 +796,7 @@ int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *m
793796
return ret;
794797

795798
fail:
799+
htx_truncate_blk(htx, tailblk);
796800
return -1;
797801
}
798802

@@ -812,6 +816,7 @@ int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *m
812816
*/
813817
int h2_make_htx_trailers(struct http_hdr *list, struct htx *htx)
814818
{
819+
struct htx_blk *tailblk = htx_get_tail_blk(htx);
815820
const char *ctl;
816821
struct ist v;
817822
uint32_t idx;
@@ -871,5 +876,6 @@ int h2_make_htx_trailers(struct http_hdr *list, struct htx *htx)
871876
return 1;
872877

873878
fail:
879+
htx_truncate_blk(htx, tailblk);
874880
return -1;
875881
}

src/h3.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,7 @@ static ssize_t h3_resp_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
11111111
struct buffer *tmp = get_trash_chunk();
11121112
struct htx *htx = NULL;
11131113
struct htx_sl *sl;
1114+
struct htx_blk *tailblk = NULL;
11141115
struct http_hdr list[global.tune.max_http_hdr * 2];
11151116
unsigned int flags = HTX_SL_F_NONE;
11161117
struct ist status = IST_NULL;
@@ -1161,7 +1162,7 @@ static ssize_t h3_resp_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
11611162
}
11621163
BUG_ON(!b_size(appbuf)); /* TODO */
11631164
htx = htx_from_buf(appbuf);
1164-
1165+
tailblk = htx_get_tail_blk(htx);
11651166
/* Only handle one HEADERS frame at a time. Thus if HTX buffer is too
11661167
* small, it happens solely from a single frame and the only option is
11671168
* to close the stream.
@@ -1351,8 +1352,11 @@ static ssize_t h3_resp_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
13511352
}
13521353

13531354
out:
1354-
if (appbuf)
1355+
if (appbuf) {
1356+
if ((ssize_t)len < 0)
1357+
htx_truncate_blk(htx, tailblk);
13551358
htx_to_buf(htx, appbuf);
1359+
}
13561360

13571361
TRACE_LEAVE(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
13581362
return len;
@@ -1376,6 +1380,7 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf,
13761380
struct buffer *appbuf = NULL;
13771381
struct htx *htx = NULL;
13781382
struct htx_sl *sl;
1383+
struct htx_blk *tailblk = NULL;
13791384
struct http_hdr list[global.tune.max_http_hdr * 2];
13801385
int hdr_idx, ret;
13811386
const char *ctl;
@@ -1406,6 +1411,7 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf,
14061411
}
14071412
BUG_ON(!b_size(appbuf)); /* TODO */
14081413
htx = htx_from_buf(appbuf);
1414+
tailblk = htx_get_tail_blk(htx);
14091415

14101416
if (!h3s->data_len) {
14111417
/* Notify that no body is present. This can only happens if
@@ -1521,8 +1527,11 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf,
15211527

15221528
out:
15231529
/* HTX may be non NULL if error before previous htx_to_buf(). */
1524-
if (appbuf)
1530+
if (appbuf) {
1531+
if ((ssize_t)len < 0)
1532+
htx_truncate_blk(htx, tailblk);
15251533
htx_to_buf(htx, appbuf);
1534+
}
15261535

15271536
TRACE_LEAVE(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
15281537
return len;

0 commit comments

Comments
 (0)