http3: allow io.EOF when parsing a capsule fails on the first byte (#4476)

This commit is contained in:
Marten Seemann
2024-05-03 13:14:18 +02:00
committed by GitHub
parent 0d565fc384
commit 8de22b2468
2 changed files with 24 additions and 4 deletions

View File

@@ -21,13 +21,29 @@ func (r *exactReader) Read(b []byte) (int, error) {
return n, err
}
type countingByteReader struct {
io.ByteReader
Read int
}
func (r *countingByteReader) ReadByte() (byte, error) {
b, err := r.ByteReader.ReadByte()
if err == nil {
r.Read++
}
return b, err
}
// ParseCapsule parses the header of a Capsule.
// It returns an io.LimitedReader that can be used to read the Capsule value.
// The Capsule value must be read entirely (i.e. until the io.EOF) before using r again.
func ParseCapsule(r quicvarint.Reader) (CapsuleType, io.Reader, error) {
ct, err := quicvarint.Read(r)
cbr := countingByteReader{ByteReader: r}
ct, err := quicvarint.Read(&cbr)
if err != nil {
if err == io.EOF {
// If an io.EOF is returned without consuming any bytes, return it unmodified.
// Otherwise, return an io.ErrUnexpectedEOF.
if err == io.EOF && cbr.Read > 0 {
return 0, nil, io.ErrUnexpectedEOF
}
return 0, nil, err

View File

@@ -26,7 +26,7 @@ var _ = Describe("Capsule", func() {
It("writes capsules", func() {
var buf bytes.Buffer
WriteCapsule(&buf, 1337, []byte("foobar"))
Expect(WriteCapsule(&buf, 1337, []byte("foobar"))).To(Succeed())
ct, r, err := ParseCapsule(&buf)
Expect(err).ToNot(HaveOccurred())
@@ -44,7 +44,11 @@ var _ = Describe("Capsule", func() {
for i := range b {
ct, r, err := ParseCapsule(bytes.NewReader(b[:i]))
if err != nil {
Expect(err).To(MatchError(io.ErrUnexpectedEOF))
if i == 0 {
Expect(err).To(MatchError(io.EOF))
} else {
Expect(err).To(MatchError(io.ErrUnexpectedEOF))
}
continue
}
Expect(ct).To(BeEquivalentTo(1337))