]> git.kaiwu.me - nginx.git/commitdiff
QUIC: make sure stream data size is lower than final size.
authorRoman Arutyunyan <arut@nginx.com>
Tue, 25 May 2021 13:41:59 +0000 (16:41 +0300)
committerRoman Arutyunyan <arut@nginx.com>
Tue, 25 May 2021 13:41:59 +0000 (16:41 +0300)
As per quic-transport 34, FINAL_SIZE_ERROR is generated if an endpoint received
a STREAM frame or a RESET_STREAM frame containing a final size that was lower
than the size of stream data that was already received.

src/event/quic/ngx_event_quic.h
src/event/quic/ngx_event_quic_streams.c

index 83e72a6f38a61ec9846f3971db44cd8be7648895..230c2c46f5ed32cbd12608fed49e02c129cd11b9 100644 (file)
@@ -79,6 +79,7 @@ struct ngx_quic_stream_s {
     uint64_t                   send_max_data;
     uint64_t                   recv_max_data;
     uint64_t                   recv_offset;
+    uint64_t                   recv_last;
     uint64_t                   final_size;
     ngx_chain_t               *in;
     ngx_uint_t                 cancelable;  /* unsigned  cancelable:1; */
index 816da61d5102afad24cda79d2d4ef0bf2803349f..d639381929139a2d3eded731b97a4cc6b9a10ed4 100644 (file)
@@ -857,6 +857,8 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
             qs->final_size = last;
         }
 
+        qs->recv_last = last;
+
         if (f->offset == 0) {
             sc->read->ready = 1;
         }
@@ -884,6 +886,10 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
         return NGX_OK;
     }
 
+    if (qs->recv_last < last) {
+        qs->recv_last = last;
+    }
+
     if (f->offset < qs->recv_offset) {
         ngx_quic_trim_bufs(frame->data, qs->recv_offset - f->offset);
         f->offset = qs->recv_offset;
@@ -899,6 +905,11 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
             return NGX_ERROR;
         }
 
+        if (qs->recv_last > last) {
+            qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
+            return NGX_ERROR;
+        }
+
         qs->connection->read->pending_eof = 1;
         qs->final_size = last;
     }
@@ -1129,6 +1140,11 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
         return NGX_ERROR;
     }
 
+    if (qs->recv_last > f->final_size) {
+        qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
+        return NGX_ERROR;
+    }
+
     qs->final_size = f->final_size;
 
     rev = qs->connection->read;