HTTP/3 trailers are decoded in function h3_trailers_to_htx(). If this
fails due to a lack of space, a negative value is returned, resulting in
a connection closed with INTERNAL_ERROR. This is incorrect as it could
have occurred because of data not yet consumed in HTX output buffer.
One solution would be to temporarily block demux when such situation is
encountered. However, it is not easily implementable now since the
introduction of http_trailers_to_htx() which is shared with HTTP/2
parser. A value HTTP_PRS_TOO_MANY can be caused either due to a
transient lack of space. However, it is also used to report a number of
decoded trailers exceeding tune.http.maxhdr configuration which is a
fatal error.
HTTP/2 parser does not have the same problem as it only starts decoding
of trailers when output HTX buffer is empty. This is largely due to the
fact that HPACK decoding cannot be rolled back after a transient error
as it can have side effects related to dynamic table decoding. HTTP/3 is
not concerned as QPACK dynamic table capability is not implemented.
Thus, apply the same approach in HTTP/3: trailers decoding will be
started only after HTX output buffer is emptied. Flag QC_SF_DEM_FULL is
set to temporarily block demux if needed and 0 is returned from
h3_trailers_to_htx(). Decoding will be retried after a successful read
from the stream layer.
This solution is in fact already used for HEADERS when dealing with
intermediaries HTTP responses. Its impact is minimal given that trailers
usage in H3 is rare. Also, it will simplify a future QPACK dynamic table
implementation.
This must be backported up to 2.8.
BUG_ON(!b_size(appbuf)); /* TODO */
htx = htx_from_buf(appbuf);
data_ofs = htx->data;
+ /* Do not decode trailers if there is remaining data left, for similar
+ * reasons as h3_resp_headers_to_htx().
+ */
+ if (!htx_is_empty(htx)) {
+ qcs->flags |= QC_SF_DEM_FULL;
+ len = 0;
+ goto out;
+ }
if (!h3s->data_len) {
/* Notify that no body is present. This can only happens if