From d7a09e76673caffc395aa9adbe245226e49397bd Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Wed, 25 Oct 2017 11:35:35 +0700 Subject: [PATCH] reject inconsistent final stream offsets --- internal/flowcontrol/stream_flow_controller.go | 5 +++++ .../flowcontrol/stream_flow_controller_test.go | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/internal/flowcontrol/stream_flow_controller.go b/internal/flowcontrol/stream_flow_controller.go index fc4821d98..96e13dc3b 100644 --- a/internal/flowcontrol/stream_flow_controller.go +++ b/internal/flowcontrol/stream_flow_controller.go @@ -52,6 +52,11 @@ func (c *streamFlowController) UpdateHighestReceived(byteOffset protocol.ByteCou c.mutex.Lock() defer c.mutex.Unlock() + // when receiving a final offset, check that this final offset is consistent with a final offset we might have received earlier + if final && c.receivedFinalOffset && byteOffset != c.highestReceived { + return qerr.Error(qerr.StreamDataAfterTermination, fmt.Sprintf("Received inconsistent final offset for stream %d (old: %d, new: %d bytes)", c.streamID, c.highestReceived, byteOffset)) + } + // if we already received a final offset, check that the offset in the STREAM frames is below the final offset if c.receivedFinalOffset && byteOffset > c.highestReceived { return qerr.StreamDataAfterTermination } diff --git a/internal/flowcontrol/stream_flow_controller_test.go b/internal/flowcontrol/stream_flow_controller_test.go index 26a4b1515..0718c6a06 100644 --- a/internal/flowcontrol/stream_flow_controller_test.go +++ b/internal/flowcontrol/stream_flow_controller_test.go @@ -124,6 +124,21 @@ var _ = Describe("Stream Flow controller", func() { err = controller.UpdateHighestReceived(250, false) Expect(err).To(MatchError(qerr.StreamDataAfterTermination)) }) + + It("accepts duplicate final offsets", func() { + err := controller.UpdateHighestReceived(200, true) + Expect(err).ToNot(HaveOccurred()) + err = controller.UpdateHighestReceived(200, true) + Expect(err).ToNot(HaveOccurred()) + Expect(controller.highestReceived).To(Equal(protocol.ByteCount(200))) + }) + + It("errors when receiving inconsistent final offsets", func() { + err := controller.UpdateHighestReceived(200, true) + Expect(err).ToNot(HaveOccurred()) + err = controller.UpdateHighestReceived(201, true) + Expect(err).To(MatchError("StreamDataAfterTermination: Received inconsistent final offset for stream 10 (old: 200, new: 201 bytes)")) + }) }) Context("registering data read", func() {