forked from quic-go/quic-go
reject http3 requests that exceeded the header size limit
This commit is contained in:
@@ -155,6 +155,13 @@ func (s *Server) handleConn(sess quic.Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) maxHeaderBytes() uint64 {
|
||||||
|
if s.Server.MaxHeaderBytes <= 0 {
|
||||||
|
return http.DefaultMaxHeaderBytes
|
||||||
|
}
|
||||||
|
return uint64(s.Server.MaxHeaderBytes)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: improve error handling.
|
// TODO: improve error handling.
|
||||||
// Most (but not all) of the errors occurring here are connection-level erros.
|
// Most (but not all) of the errors occurring here are connection-level erros.
|
||||||
func (s *Server) handleRequest(str quic.Stream, decoder *qpack.Decoder) error {
|
func (s *Server) handleRequest(str quic.Stream, decoder *qpack.Decoder) error {
|
||||||
@@ -168,7 +175,10 @@ func (s *Server) handleRequest(str quic.Stream, decoder *qpack.Decoder) error {
|
|||||||
str.CancelWrite(quic.ErrorCode(errorUnexpectedFrame))
|
str.CancelWrite(quic.ErrorCode(errorUnexpectedFrame))
|
||||||
return errors.New("expected first frame to be a headers frame")
|
return errors.New("expected first frame to be a headers frame")
|
||||||
}
|
}
|
||||||
// TODO: check length
|
if hf.Length > s.maxHeaderBytes() {
|
||||||
|
str.CancelWrite(quic.ErrorCode(errorLimitExceeded))
|
||||||
|
return fmt.Errorf("Headers frame too large: %d bytes (max: %d)", hf.Length, s.maxHeaderBytes())
|
||||||
|
}
|
||||||
headerBlock := make([]byte, hf.Length)
|
headerBlock := make([]byte, hf.Length)
|
||||||
if _, err := io.ReadFull(str, headerBlock); err != nil {
|
if _, err := io.ReadFull(str, headerBlock); err != nil {
|
||||||
str.CancelWrite(quic.ErrorCode(errorIncompleteRequest))
|
str.CancelWrite(quic.ErrorCode(errorIncompleteRequest))
|
||||||
|
|||||||
@@ -181,6 +181,28 @@ var _ = Describe("Server", func() {
|
|||||||
Expect(hfs).To(HaveKeyWithValue(":status", []string{"200"}))
|
Expect(hfs).To(HaveKeyWithValue(":status", []string{"200"}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("errors when the client sends a too large header frame", func() {
|
||||||
|
s.Server.MaxHeaderBytes = 42
|
||||||
|
s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Fail("Handler should not be called.")
|
||||||
|
})
|
||||||
|
|
||||||
|
requestData := encodeRequest(exampleGetRequest)
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
(&dataFrame{Length: 6}).Write(buf) // add a body
|
||||||
|
buf.Write([]byte("foobar"))
|
||||||
|
responseBuf := &bytes.Buffer{}
|
||||||
|
setRequest(append(requestData, buf.Bytes()...))
|
||||||
|
str.EXPECT().Write(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
|
||||||
|
return responseBuf.Write(p)
|
||||||
|
}).AnyTimes()
|
||||||
|
|
||||||
|
str.EXPECT().CancelWrite(quic.ErrorCode(errorLimitExceeded))
|
||||||
|
err := s.handleRequest(str, qpackDecoder)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.Error()).To(ContainSubstring("Headers frame too large"))
|
||||||
|
})
|
||||||
|
|
||||||
It("cancels reading when the body of POST request is not read", func() {
|
It("cancels reading when the body of POST request is not read", func() {
|
||||||
handlerCalled := make(chan struct{})
|
handlerCalled := make(chan struct{})
|
||||||
s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
Reference in New Issue
Block a user