forked from quic-go/quic-go
http3: reject duplicate pseudo headers (#4993)
This commit is contained in:
@@ -56,23 +56,33 @@ func parseHeaders(headers []qpack.HeaderField, isRequest bool) (header, error) {
|
|||||||
return header{}, fmt.Errorf("received pseudo header %s after a regular header field", h.Name)
|
return header{}, fmt.Errorf("received pseudo header %s after a regular header field", h.Name)
|
||||||
}
|
}
|
||||||
var isResponsePseudoHeader bool // pseudo headers are either valid for requests or for responses
|
var isResponsePseudoHeader bool // pseudo headers are either valid for requests or for responses
|
||||||
|
var isDuplicatePseudoHeader bool // pseudo headers are allowed to appear exactly once
|
||||||
switch h.Name {
|
switch h.Name {
|
||||||
case ":path":
|
case ":path":
|
||||||
|
isDuplicatePseudoHeader = hdr.Path != ""
|
||||||
hdr.Path = h.Value
|
hdr.Path = h.Value
|
||||||
case ":method":
|
case ":method":
|
||||||
|
isDuplicatePseudoHeader = hdr.Method != ""
|
||||||
hdr.Method = h.Value
|
hdr.Method = h.Value
|
||||||
case ":authority":
|
case ":authority":
|
||||||
|
isDuplicatePseudoHeader = hdr.Authority != ""
|
||||||
hdr.Authority = h.Value
|
hdr.Authority = h.Value
|
||||||
case ":protocol":
|
case ":protocol":
|
||||||
|
isDuplicatePseudoHeader = hdr.Protocol != ""
|
||||||
hdr.Protocol = h.Value
|
hdr.Protocol = h.Value
|
||||||
case ":scheme":
|
case ":scheme":
|
||||||
|
isDuplicatePseudoHeader = hdr.Scheme != ""
|
||||||
hdr.Scheme = h.Value
|
hdr.Scheme = h.Value
|
||||||
case ":status":
|
case ":status":
|
||||||
|
isDuplicatePseudoHeader = hdr.Status != ""
|
||||||
hdr.Status = h.Value
|
hdr.Status = h.Value
|
||||||
isResponsePseudoHeader = true
|
isResponsePseudoHeader = true
|
||||||
default:
|
default:
|
||||||
return header{}, fmt.Errorf("unknown pseudo header: %s", h.Name)
|
return header{}, fmt.Errorf("unknown pseudo header: %s", h.Name)
|
||||||
}
|
}
|
||||||
|
if isDuplicatePseudoHeader {
|
||||||
|
return header{}, fmt.Errorf("duplicate pseudo header: %s", h.Name)
|
||||||
|
}
|
||||||
if isRequest && isResponsePseudoHeader {
|
if isRequest && isResponsePseudoHeader {
|
||||||
return header{}, fmt.Errorf("invalid request pseudo header: %s", h.Name)
|
return header{}, fmt.Errorf("invalid request pseudo header: %s", h.Name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,18 @@ var _ = Describe("Request", func() {
|
|||||||
Expect(err).To(MatchError(":protocol must be empty"))
|
Expect(err).To(MatchError(":protocol must be empty"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("errors with duplicate pseudo header in request", func() {
|
||||||
|
headers := []qpack.HeaderField{
|
||||||
|
{Name: ":path", Value: "/foo"},
|
||||||
|
{Name: ":authority", Value: "quic.clemente.io"},
|
||||||
|
{Name: ":method", Value: "GET"},
|
||||||
|
{Name: ":scheme", Value: "https"},
|
||||||
|
{Name: ":method", Value: "POST"},
|
||||||
|
}
|
||||||
|
_, err := requestFromHeaders(headers)
|
||||||
|
Expect(err).To(MatchError("duplicate pseudo header: :method"))
|
||||||
|
})
|
||||||
|
|
||||||
Context("regular HTTP CONNECT", func() {
|
Context("regular HTTP CONNECT", func() {
|
||||||
It("handles CONNECT method", func() {
|
It("handles CONNECT method", func() {
|
||||||
headers := []qpack.HeaderField{
|
headers := []qpack.HeaderField{
|
||||||
@@ -432,4 +444,13 @@ var _ = Describe("Response", func() {
|
|||||||
_, err := parseTrailers(headers)
|
_, err := parseTrailers(headers)
|
||||||
Expect(err).To(MatchError("http3: received pseudo header in trailer: :status"))
|
Expect(err).To(MatchError("http3: received pseudo header in trailer: :status"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("errors with duplicate status header in response", func() {
|
||||||
|
headers := []qpack.HeaderField{
|
||||||
|
{Name: ":status", Value: "200"},
|
||||||
|
{Name: ":status", Value: "400"},
|
||||||
|
}
|
||||||
|
err := updateResponseFromHeaders(&http.Response{}, headers)
|
||||||
|
Expect(err).To(MatchError("duplicate pseudo header: :status"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user