forked from quic-go/quic-go
fix dequeuing logic for tiny CRYPTO frames (#5104)
For very small sizes, cryptoStream.PopCryptoStream could have returned CRYPTO frames larger than the requested size. Instead, it should return a nil frame.
This commit is contained in:
@@ -826,7 +826,9 @@ func (s *connection) handleHandshakeComplete(now time.Time) error {
|
||||
if ticket != nil { // may be nil if session tickets are disabled via tls.Config.SessionTicketsDisabled
|
||||
s.oneRTTStream.Write(ticket)
|
||||
for s.oneRTTStream.HasData() {
|
||||
s.queueControlFrame(s.oneRTTStream.PopCryptoFrame(protocol.MaxPostHandshakeCryptoFrameSize))
|
||||
if cf := s.oneRTTStream.PopCryptoFrame(protocol.MaxPostHandshakeCryptoFrameSize); cf != nil {
|
||||
s.queueControlFrame(cf)
|
||||
}
|
||||
}
|
||||
}
|
||||
token, err := s.tokenGenerator.NewToken(s.conn.RemoteAddr())
|
||||
|
||||
@@ -76,6 +76,9 @@ func (s *cryptoStream) HasData() bool {
|
||||
func (s *cryptoStream) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame {
|
||||
f := &wire.CryptoFrame{Offset: s.writeOffset}
|
||||
n := min(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf)))
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
f.Data = s.writeBuf[:n]
|
||||
s.writeBuf = s.writeBuf[n:]
|
||||
s.writeOffset += n
|
||||
|
||||
@@ -91,11 +91,17 @@ func TestCryptoStreamWrite(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, str.HasData())
|
||||
|
||||
f := str.PopCryptoFrame(expectedCryptoFrameLen(0) + 3)
|
||||
require.Equal(t, &wire.CryptoFrame{Data: []byte("foo")}, f)
|
||||
for i := range expectedCryptoFrameLen(0) {
|
||||
require.Nil(t, str.PopCryptoFrame(i))
|
||||
}
|
||||
|
||||
f := str.PopCryptoFrame(expectedCryptoFrameLen(0) + 1)
|
||||
require.Equal(t, &wire.CryptoFrame{Data: []byte("f")}, f)
|
||||
require.True(t, str.HasData())
|
||||
f = str.PopCryptoFrame(expectedCryptoFrameLen(1) + 3)
|
||||
// the three write calls were coalesced into a single frame
|
||||
require.Equal(t, &wire.CryptoFrame{Offset: 1, Data: []byte("oob")}, f)
|
||||
f = str.PopCryptoFrame(protocol.MaxByteCount)
|
||||
// the two write calls were coalesced into a single frame
|
||||
require.Equal(t, &wire.CryptoFrame{Offset: 3, Data: []byte("barbaz")}, f)
|
||||
require.Equal(t, &wire.CryptoFrame{Offset: 4, Data: []byte("arbaz")}, f)
|
||||
require.False(t, str.HasData())
|
||||
}
|
||||
|
||||
@@ -561,9 +561,10 @@ func (p *packetPacker) maybeGetCryptoPacket(
|
||||
maxPacketSize -= frameLen
|
||||
}
|
||||
} else if s.HasData() {
|
||||
cf := s.PopCryptoFrame(maxPacketSize)
|
||||
pl.frames = append(pl.frames, ackhandler.Frame{Frame: cf, Handler: handler})
|
||||
pl.length += cf.Length(v)
|
||||
if cf := s.PopCryptoFrame(maxPacketSize); cf != nil {
|
||||
pl.frames = append(pl.frames, ackhandler.Frame{Frame: cf, Handler: handler})
|
||||
pl.length += cf.Length(v)
|
||||
}
|
||||
}
|
||||
return hdr, pl
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user