forked from quic-go/quic-go
http3: reject pseudo header fields in trailers (#4639)
* http3: reject pseudo header fields in trailers As defined in section 4.3 of RFC 9114. * http3: improve allocs for trailer map * http3: rename connection.parseTrailer to decodeTrailers
This commit is contained in:
@@ -116,7 +116,7 @@ func (c *connection) openRequestStream(
|
||||
qstr := newStateTrackingStream(str, c, datagrams)
|
||||
rsp := &http.Response{}
|
||||
hstr := newStream(qstr, c, datagrams, func(r io.Reader, l uint64) error {
|
||||
hdr, err := c.parseTrailer(r, l, maxHeaderBytes)
|
||||
hdr, err := c.decodeTrailers(r, l, maxHeaderBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func (c *connection) openRequestStream(
|
||||
return newRequestStream(hstr, requestWriter, reqDone, c.decoder, disableCompression, maxHeaderBytes, rsp), nil
|
||||
}
|
||||
|
||||
func (c *connection) parseTrailer(r io.Reader, l, maxHeaderBytes uint64) (http.Header, error) {
|
||||
func (c *connection) decodeTrailers(r io.Reader, l, maxHeaderBytes uint64) (http.Header, error) {
|
||||
if l > maxHeaderBytes {
|
||||
return nil, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", l, maxHeaderBytes)
|
||||
}
|
||||
@@ -139,11 +139,7 @@ func (c *connection) parseTrailer(r io.Reader, l, maxHeaderBytes uint64) (http.H
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h := http.Header{}
|
||||
for _, field := range fields {
|
||||
h.Add(field.Name, field.Value)
|
||||
}
|
||||
return h, nil
|
||||
return parseTrailers(fields)
|
||||
}
|
||||
|
||||
func (c *connection) acceptStream(ctx context.Context) (quic.Stream, *datagrammer, error) {
|
||||
|
||||
@@ -101,6 +101,17 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
||||
return hdr, nil
|
||||
}
|
||||
|
||||
func parseTrailers(headers []qpack.HeaderField) (http.Header, error) {
|
||||
h := make(http.Header, len(headers))
|
||||
for _, field := range headers {
|
||||
if field.IsPseudo() {
|
||||
return nil, fmt.Errorf("http3: received pseudo header in trailer: %s", field.Name)
|
||||
}
|
||||
h.Add(field.Name, field.Value)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func requestFromHeaders(headerFields []qpack.HeaderField) (*http.Request, error) {
|
||||
hdr, err := parseHeaders(headerFields, true)
|
||||
if err != nil {
|
||||
|
||||
@@ -358,4 +358,21 @@ var _ = Describe("Response", func() {
|
||||
err := updateResponseFromHeaders(&http.Response{}, headers)
|
||||
Expect(err).To(MatchError("invalid response pseudo header: :method"))
|
||||
})
|
||||
|
||||
It("parses trailers", func() {
|
||||
headers := []qpack.HeaderField{
|
||||
{Name: "content-length", Value: "42"},
|
||||
}
|
||||
hdr, err := parseTrailers(headers)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(hdr.Get("Content-Length")).To(Equal("42"))
|
||||
})
|
||||
|
||||
It("parses trailers", func() {
|
||||
headers := []qpack.HeaderField{
|
||||
{Name: ":status", Value: "200"},
|
||||
}
|
||||
_, err := parseTrailers(headers)
|
||||
Expect(err).To(MatchError("http3: received pseudo header in trailer: :status"))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user