mirror of
https://github.com/nginx/nginx.git
synced 2026-08-04 14:58:20 +00:00
QUIC: always validate stream final size
As per RFC 9000, Section 4.5: Once a final size for a stream is known, it cannot change. If a RESET_STREAM or STREAM frame is received indicating a change in the final size for the stream, an endpoint SHOULD respond with an error of type FINAL_SIZE_ERROR. A receiver SHOULD treat receipt of data at or beyond the final size as an error of type FINAL_SIZE_ERROR, even after a stream is closed. Previously, the stream final size was validated only after other checks that could return earlier and skip validation: the receive state check and, for STREAM frames, the check for data below the current receive offset. As a result, a STREAM or RESET_STREAM frame carrying a final size error was silently ignored once the receiving part of the stream had reached a state in which the frame would otherwise be discarded, or when a STREAM frame did not advance the receive offset. Now the final size is validated first, so a FINAL_SIZE_ERROR is generated in these cases as well.
This commit is contained in:
parent
e3548e3056
commit
269cdf7806
1 changed files with 23 additions and 26 deletions
|
|
@ -1260,6 +1260,19 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (qs->recv_final_size != (uint64_t) -1
|
||||
&& (qs->recv_final_size < last
|
||||
|| (qs->recv_final_size > last && f->fin)))
|
||||
{
|
||||
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_last > last && f->fin) {
|
||||
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_state != NGX_QUIC_STREAM_RECV_RECV
|
||||
&& qs->recv_state != NGX_QUIC_STREAM_RECV_SIZE_KNOWN)
|
||||
{
|
||||
|
|
@ -1270,27 +1283,11 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_final_size != (uint64_t) -1 && last > qs->recv_final_size) {
|
||||
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (last < qs->recv_offset) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (f->fin) {
|
||||
if (qs->recv_final_size != (uint64_t) -1 && qs->recv_final_size != last)
|
||||
{
|
||||
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_last > last) {
|
||||
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qs->recv_final_size = last;
|
||||
qs->recv_state = NGX_QUIC_STREAM_RECV_SIZE_KNOWN;
|
||||
}
|
||||
|
|
@ -1475,16 +1472,6 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (qs->recv_state == NGX_QUIC_STREAM_RECV_RESET_RECVD
|
||||
|| qs->recv_state == NGX_QUIC_STREAM_RECV_RESET_READ)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ngx_quic_control_flow(qs, f->final_size) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_final_size != (uint64_t) -1
|
||||
&& qs->recv_final_size != f->final_size)
|
||||
{
|
||||
|
|
@ -1497,6 +1484,16 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qs->recv_state == NGX_QUIC_STREAM_RECV_RESET_RECVD
|
||||
|| qs->recv_state == NGX_QUIC_STREAM_RECV_RESET_READ)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ngx_quic_control_flow(qs, f->final_size) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qs->recv_final_size = f->final_size;
|
||||
qs->recv_state = NGX_QUIC_STREAM_RECV_RESET_RECVD;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue