diff --git a/src/h3.c b/src/h3.c index e10dea69c..4e5d52f5b 100644 --- a/src/h3.c +++ b/src/h3.c @@ -641,7 +641,7 @@ static ssize_t h3_req_headers_to_htx(struct qcs *qcs, const struct buffer *buf, /* TODO support trailer parsing in this function */ /* TODO support buffer wrapping */ - BUG_ON(b_head(buf) + len >= b_wrap(buf)); + BUG_ON(b_head(buf) + len > b_wrap(buf)); ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp, list, sizeof(list) / sizeof(list[0])); if (ret < 0) { @@ -1142,7 +1142,7 @@ static ssize_t h3_resp_headers_to_htx(struct qcs *qcs, const struct buffer *buf, TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs); /* TODO support buffer wrapping */ - BUG_ON(b_head(buf) + len >= b_wrap(buf)); + BUG_ON(b_head(buf) + len > b_wrap(buf)); ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp, list, sizeof(list) / sizeof(list[0])); if (ret < 0) { @@ -1391,7 +1391,7 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf, TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs); /* TODO support buffer wrapping */ - BUG_ON(b_head(buf) + len >= b_wrap(buf)); + BUG_ON(b_head(buf) + len > b_wrap(buf)); ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp, list, sizeof(list) / sizeof(list[0])); if (ret < 0) { @@ -1818,10 +1818,11 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin) flen = h3s->demux_frame_len; ftype = h3s->demux_frame_type; - /* Do not demux incomplete frames except H3 DATA which can be - * fragmented in multiple HTX blocks. + /* Current HTTP/3 parser can currently only parse fully + * received and aligned frames. The only exception is for DATA + * frames as they can frequently be larger than bufsize. */ - if (flen > b_data(b) && ftype != H3_FT_DATA) { + if (ftype != H3_FT_DATA) { /* Reject frames bigger than bufsize. * * TODO HEADERS should in complement be limited with H3 @@ -1834,7 +1835,20 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin) qcc_report_glitch(qcs->qcc, 1); goto err; } - break; + + /* TODO extend parser to support the realignment of a frame. */ + if (b_head(b) + b_data(b) > b_wrap(b)) { + TRACE_ERROR("cannot parse unaligned data frame", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); + qcc_set_error(qcs->qcc, H3_ERR_EXCESSIVE_LOAD, 1); + qcc_report_glitch(qcs->qcc, 1); + goto err; + } + + /* Only parse full HTTP/3 frames. */ + if (flen > b_data(b)) { + TRACE_PROTO("pause parsing on incomplete payload", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); + break; + } } last_stream_frame = (fin && flen == b_data(b));