QUIC TXP: Fix handling of FIN stream chunks

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19897)
This commit is contained in:
Hugo Landau 2022-12-13 12:27:43 +00:00
parent e8043229ea
commit cf06f34727

View File

@ -1157,6 +1157,11 @@ static int try_len(size_t space_left, size_t orig_len,
*hdr_len = base_hdr_len + lenbytes; *hdr_len = base_hdr_len + lenbytes;
if (orig_len == 0 && space_left >= *hdr_len) {
*payload_len = 0;
return 1;
}
n = orig_len; n = orig_len;
if (n > maxn_) if (n > maxn_)
n = maxn_; n = maxn_;
@ -1167,10 +1172,11 @@ static int try_len(size_t space_left, size_t orig_len,
return n > 0; return n > 0;
} }
static void determine_len(size_t space_left, size_t orig_len, static int determine_len(size_t space_left, size_t orig_len,
size_t base_hdr_len, size_t base_hdr_len,
uint64_t *hlen, uint64_t *len) uint64_t *hlen, uint64_t *len)
{ {
int ok = 0;
size_t chosen_payload_len = 0; size_t chosen_payload_len = 0;
size_t chosen_hdr_len = 0; size_t chosen_hdr_len = 0;
size_t payload_len[4], hdr_len[4]; size_t payload_len[4], hdr_len[4];
@ -1193,10 +1199,12 @@ static void determine_len(size_t space_left, size_t orig_len,
if (valid[i] && payload_len[i] >= chosen_payload_len) { if (valid[i] && payload_len[i] >= chosen_payload_len) {
chosen_payload_len = payload_len[i]; chosen_payload_len = payload_len[i];
chosen_hdr_len = hdr_len[i]; chosen_hdr_len = hdr_len[i];
ok = 1;
} }
*hlen = chosen_hdr_len; *hlen = chosen_hdr_len;
*len = chosen_payload_len; *len = chosen_payload_len;
return ok;
} }
/* /*
@ -1229,8 +1237,7 @@ static int determine_crypto_len(struct tx_helper *h,
--base_hdr_len; --base_hdr_len;
determine_len(space_left, orig_len, base_hdr_len, hlen, len); return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
return 1;
} }
static int determine_stream_len(struct tx_helper *h, static int determine_stream_len(struct tx_helper *h,
@ -1256,8 +1263,7 @@ static int determine_stream_len(struct tx_helper *h,
if (shdr->has_explicit_len) if (shdr->has_explicit_len)
--base_hdr_len; --base_hdr_len;
determine_len(space_left, orig_len, base_hdr_len, hlen, len); return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
return 1;
} }
static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp, static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp,
@ -1297,10 +1303,8 @@ static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp,
/* Find best fit (header length, payload length) combination. */ /* Find best fit (header length, payload length) combination. */
if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes, if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes,
&chdr.len) &chdr.len))
|| hdr_bytes == 0 || chdr.len == 0) {
return 1; /* can't fit anything */ return 1; /* can't fit anything */
}
/* /*
* Truncate IOVs to match our chosen length. * Truncate IOVs to match our chosen length.
@ -1457,15 +1461,15 @@ static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
for (i = 0;; ++i) { for (i = 0;; ++i) {
space_left = tx_helper_get_space_left(h); space_left = tx_helper_get_space_left(h);
if (space_left < MIN_FRAME_SIZE_STREAM) { if (!chunks[i % 2].valid) {
*packet_full = 1; /* Out of chunks; we're done. */
*stream_drained = 1;
rc = 1; rc = 1;
goto err; goto err;
} }
if (!chunks[i % 2].valid) { if (space_left < MIN_FRAME_SIZE_STREAM) {
/* Out of chunks; we're done. */ *packet_full = 1;
*stream_drained = 1;
rc = 1; rc = 1;
goto err; goto err;
} }
@ -1493,8 +1497,7 @@ static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
shdr->has_explicit_len = 0; shdr->has_explicit_len = 0;
hdr_len_implicit = payload_len_implicit = 0; hdr_len_implicit = payload_len_implicit = 0;
if (!determine_stream_len(h, shdr, space_left, if (!determine_stream_len(h, shdr, space_left,
&hdr_len_implicit, &payload_len_implicit) &hdr_len_implicit, &payload_len_implicit)) {
|| hdr_len_implicit == 0 || payload_len_implicit == 0) {
*packet_full = 1; *packet_full = 1;
rc = 1; rc = 1;
goto err; /* can't fit anything */ goto err; /* can't fit anything */
@ -1534,8 +1537,7 @@ static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
shdr->has_explicit_len = 1; shdr->has_explicit_len = 1;
hdr_len_explicit = payload_len_explicit = 0; hdr_len_explicit = payload_len_explicit = 0;
if (!determine_stream_len(h, shdr, space_left, if (!determine_stream_len(h, shdr, space_left,
&hdr_len_explicit, &payload_len_explicit) &hdr_len_explicit, &payload_len_explicit)) {
|| hdr_len_explicit == 0 || payload_len_explicit == 0) {
*packet_full = 1; *packet_full = 1;
rc = 1; rc = 1;
goto err; /* can't fit anything */ goto err; /* can't fit anything */
@ -1547,6 +1549,10 @@ static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
shdr->len = payload_len_implicit; shdr->len = payload_len_implicit;
} }
/* If this is a FIN, don't keep filling the packet with more FINs. */
if (shdr->is_fin)
chunks[(i + 1) % 2].valid = 0;
/* Truncate IOVs to match our chosen length. */ /* Truncate IOVs to match our chosen length. */
ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov, ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov,
chunks[i % 2].num_stream_iovec); chunks[i % 2].num_stream_iovec);