reject transport parameters with too large stream counts

This commit is contained in:
Marten Seemann 2019-03-29 09:39:02 +01:00
parent 7b02b87026
commit 51c9c42adc
4 changed files with 32 additions and 13 deletions

View file

@ -197,9 +197,11 @@ func (mr *MockStreamManagerMockRecorder) OpenUniStreamSync() *gomock.Call {
} }
// UpdateLimits mocks base method // UpdateLimits mocks base method
func (m *MockStreamManager) UpdateLimits(arg0 *handshake.TransportParameters) { func (m *MockStreamManager) UpdateLimits(arg0 *handshake.TransportParameters) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "UpdateLimits", arg0) ret := m.ctrl.Call(m, "UpdateLimits", arg0)
ret0, _ := ret[0].(error)
return ret0
} }
// UpdateLimits indicates an expected call of UpdateLimits // UpdateLimits indicates an expected call of UpdateLimits

View file

@ -41,7 +41,7 @@ type streamManager interface {
AcceptStream() (Stream, error) AcceptStream() (Stream, error)
AcceptUniStream() (ReceiveStream, error) AcceptUniStream() (ReceiveStream, error)
DeleteStream(protocol.StreamID) error DeleteStream(protocol.StreamID) error
UpdateLimits(*handshake.TransportParameters) UpdateLimits(*handshake.TransportParameters) error
HandleMaxStreamsFrame(*wire.MaxStreamsFrame) error HandleMaxStreamsFrame(*wire.MaxStreamsFrame) error
CloseWithError(error) CloseWithError(error)
} }
@ -930,7 +930,10 @@ func (s *session) processTransportParameters(data []byte) {
} }
s.logger.Debugf("Received Transport Parameters: %s", params) s.logger.Debugf("Received Transport Parameters: %s", params)
s.peerParams = params s.peerParams = params
s.streamsMap.UpdateLimits(params) if err := s.streamsMap.UpdateLimits(params); err != nil {
s.closeLocal(err)
return
}
s.packer.HandleTransportParameters(params) s.packer.HandleTransportParameters(params)
s.frameParser.SetAckDelayExponent(params.AckDelayExponent) s.frameParser.SetAckDelayExponent(params.AckDelayExponent)
s.connFlowController.UpdateSendWindow(params.InitialMaxData) s.connFlowController.UpdateSendWindow(params.InitialMaxData)

View file

@ -174,10 +174,14 @@ func (m *streamsMap) HandleMaxStreamsFrame(f *wire.MaxStreamsFrame) error {
return nil return nil
} }
func (m *streamsMap) UpdateLimits(p *handshake.TransportParameters) { func (m *streamsMap) UpdateLimits(p *handshake.TransportParameters) error {
if p.MaxBidiStreams > protocol.MaxStreamCount || p.MaxUniStreams > protocol.MaxStreamCount {
return qerr.StreamLimitError
}
// Max{Uni,Bidi}StreamID returns the highest stream ID that the peer is allowed to open. // Max{Uni,Bidi}StreamID returns the highest stream ID that the peer is allowed to open.
m.outgoingBidiStreams.SetMaxStream(protocol.MaxStreamID(protocol.StreamTypeBidi, p.MaxBidiStreams, m.perspective)) m.outgoingBidiStreams.SetMaxStream(protocol.MaxStreamID(protocol.StreamTypeBidi, p.MaxBidiStreams, m.perspective))
m.outgoingUniStreams.SetMaxStream(protocol.MaxStreamID(protocol.StreamTypeUni, p.MaxUniStreams, m.perspective)) m.outgoingUniStreams.SetMaxStream(protocol.MaxStreamID(protocol.StreamTypeUni, p.MaxUniStreams, m.perspective))
return nil
} }
func (m *streamsMap) CloseWithError(err error) { func (m *streamsMap) CloseWithError(err error) {

View file

@ -295,33 +295,43 @@ var _ = Describe("Streams Map", func() {
}) })
Context("updating stream ID limits", func() { Context("updating stream ID limits", func() {
BeforeEach(func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
})
It("processes the parameter for outgoing streams, as a server", func() { It("processes the parameter for outgoing streams, as a server", func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
m.perspective = protocol.PerspectiveServer m.perspective = protocol.PerspectiveServer
_, err := m.OpenStream() _, err := m.OpenStream()
expectTooManyStreamsError(err) expectTooManyStreamsError(err)
m.UpdateLimits(&handshake.TransportParameters{ Expect(m.UpdateLimits(&handshake.TransportParameters{
MaxBidiStreams: 5, MaxBidiStreams: 5,
MaxUniStreams: 5, MaxUniStreams: 5,
}) })).To(Succeed())
Expect(m.outgoingBidiStreams.maxStream).To(Equal(protocol.StreamID(17))) Expect(m.outgoingBidiStreams.maxStream).To(Equal(protocol.StreamID(17)))
Expect(m.outgoingUniStreams.maxStream).To(Equal(protocol.StreamID(19))) Expect(m.outgoingUniStreams.maxStream).To(Equal(protocol.StreamID(19)))
}) })
It("processes the parameter for outgoing streams, as a client", func() { It("processes the parameter for outgoing streams, as a client", func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
m.perspective = protocol.PerspectiveClient m.perspective = protocol.PerspectiveClient
_, err := m.OpenUniStream() _, err := m.OpenUniStream()
expectTooManyStreamsError(err) expectTooManyStreamsError(err)
m.UpdateLimits(&handshake.TransportParameters{ Expect(m.UpdateLimits(&handshake.TransportParameters{
MaxBidiStreams: 5, MaxBidiStreams: 5,
MaxUniStreams: 5, MaxUniStreams: 5,
}) })).To(Succeed())
Expect(m.outgoingBidiStreams.maxStream).To(Equal(protocol.StreamID(16))) Expect(m.outgoingBidiStreams.maxStream).To(Equal(protocol.StreamID(16)))
Expect(m.outgoingUniStreams.maxStream).To(Equal(protocol.StreamID(18))) Expect(m.outgoingUniStreams.maxStream).To(Equal(protocol.StreamID(18)))
}) })
It("rejects parameters with too large unidirectional stream counts", func() {
Expect(m.UpdateLimits(&handshake.TransportParameters{
MaxUniStreams: protocol.MaxStreamCount + 1,
})).To(MatchError(qerr.StreamLimitError))
})
It("rejects parameters with too large unidirectional stream counts", func() {
Expect(m.UpdateLimits(&handshake.TransportParameters{
MaxBidiStreams: protocol.MaxStreamCount + 1,
})).To(MatchError(qerr.StreamLimitError))
})
}) })
Context("handling MAX_STREAMS frames", func() { Context("handling MAX_STREAMS frames", func() {