@@ -520,6 +520,9 @@ func (h2f *Framer) currentRequest(id uint32) *http.Request {
520
520
// returned error is errFrameTooLarge. Other errors may be of type
521
521
// ConnectionError, StreamError, or anything else from the underlying
522
522
// reader.
523
+ //
524
+ // If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
525
+ // indicates the stream responsible for the error.
523
526
func (h2f * Framer ) ReadFrame () (Frame , error ) {
524
527
h2f .errDetail = nil
525
528
if h2f .lastFrame != nil {
@@ -1555,7 +1558,7 @@ func (fr *Framer) maxHeaderStringLen() int {
1555
1558
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
1556
1559
// merge them into the provided hf and returns a MetaHeadersFrame
1557
1560
// with the decoded hpack values.
1558
- func (h2f * Framer ) readMetaFrame (hf * HeadersFrame , dumps []* dump.Dumper ) (* MetaHeadersFrame , error ) {
1561
+ func (h2f * Framer ) readMetaFrame (hf * HeadersFrame , dumps []* dump.Dumper ) (Frame , error ) {
1559
1562
if h2f .AllowIllegalReads {
1560
1563
return nil , errors .New ("illegal use of AllowIllegalReads with ReadMetaHeaders" )
1561
1564
}
@@ -1598,6 +1601,7 @@ func (h2f *Framer) readMetaFrame(hf *HeadersFrame, dumps []*dump.Dumper) (*MetaH
1598
1601
if size > remainSize {
1599
1602
hdec .SetEmitEnabled (false )
1600
1603
mh .Truncated = true
1604
+ remainSize = 0
1601
1605
return
1602
1606
}
1603
1607
remainSize -= size
@@ -1621,8 +1625,38 @@ func (h2f *Framer) readMetaFrame(hf *HeadersFrame, dumps []*dump.Dumper) (*MetaH
1621
1625
var hc headersOrContinuation = hf
1622
1626
for {
1623
1627
frag := hc .HeaderBlockFragment ()
1628
+
1629
+ // Avoid parsing large amounts of headers that we will then discard.
1630
+ // If the sender exceeds the max header list size by too much,
1631
+ // skip parsing the fragment and close the connection.
1632
+ //
1633
+ // "Too much" is either any CONTINUATION frame after we've already
1634
+ // exceeded the max header list size (in which case remainSize is 0),
1635
+ // or a frame whose encoded size is more than twice the remaining
1636
+ // header list bytes we're willing to accept.
1637
+ if int64 (len (frag )) > int64 (2 * remainSize ) {
1638
+ if VerboseLogs {
1639
+ log .Printf ("http2: header list too large" )
1640
+ }
1641
+ // It would be nice to send a RST_STREAM before sending the GOAWAY,
1642
+ // but the structure of the server's frame writer makes this difficult.
1643
+ return mh , ConnectionError (ErrCodeProtocol )
1644
+ }
1645
+
1646
+ // Also close the connection after any CONTINUATION frame following an
1647
+ // invalid header, since we stop tracking the size of the headers after
1648
+ // an invalid one.
1649
+ if invalid != nil {
1650
+ if VerboseLogs {
1651
+ log .Printf ("http2: invalid header: %v" , invalid )
1652
+ }
1653
+ // It would be nice to send a RST_STREAM before sending the GOAWAY,
1654
+ // but the structure of the server's frame writer makes this difficult.
1655
+ return mh , ConnectionError (ErrCodeProtocol )
1656
+ }
1657
+
1624
1658
if _ , err := hdec .Write (frag ); err != nil {
1625
- return nil , ConnectionError (ErrCodeCompression )
1659
+ return mh , ConnectionError (ErrCodeCompression )
1626
1660
}
1627
1661
1628
1662
if hc .HeadersEnded () {
@@ -1639,7 +1673,7 @@ func (h2f *Framer) readMetaFrame(hf *HeadersFrame, dumps []*dump.Dumper) (*MetaH
1639
1673
mh .HeadersFrame .invalidate ()
1640
1674
1641
1675
if err := hdec .Close (); err != nil {
1642
- return nil , ConnectionError (ErrCodeCompression )
1676
+ return mh , ConnectionError (ErrCodeCompression )
1643
1677
}
1644
1678
if invalid != nil {
1645
1679
h2f .errDetail = invalid
0 commit comments