Pull in security fix
2d13015 http2: cap the size of the server's canonical header cache
and
0a0e4e1 http2: Fix handling of expect continue
04296fa http2: prioritize RST_STREAM frames in random write scheduler
Fixes #50058
Fixes CVE-2021-44716
Change-Id: Ia40a2e52fa240e54a83b5ec7d8116cb6639ecbb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/370579
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
require (
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
- golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9
+ golang.org/x/net v0.0.0-20211209124913-491a49abca63
)
require (
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI=
-golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
+golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
sc.canonHeader = make(map[string]string)
}
cv = CanonicalHeaderKey(v)
- sc.canonHeader[v] = cv
+ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
+ // entries in the canonHeader cache. This should be larger than the number
+ // of unique, uncommon header keys likely to be sent by the peer, while not
+ // so high as to permit unreaasonable memory usage if the peer sends an unbounded
+ // number of unique header keys.
+ const maxCachedCanonicalHeaders = 32
+ if len(sc.canonHeader) < maxCachedCanonicalHeaders {
+ sc.canonHeader[v] = cv
+ }
return cv
}
}
continueTimeout := cc.t.expectContinueTimeout()
- if continueTimeout != 0 &&
- !httpguts.HeaderValuesContainsToken(
- req.Header["Expect"],
- "100-continue") {
- continueTimeout = 0
- cs.on100 = make(chan struct{}, 1)
+ if continueTimeout != 0 {
+ if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") {
+ continueTimeout = 0
+ } else {
+ cs.on100 = make(chan struct{}, 1)
+ }
}
// Past this point (where we send request headers), it is possible for
// Pop dequeues the next frame to write. Returns false if no frames can
// be written. Frames with a given wr.StreamID() are Pop'd in the same
- // order they are Push'd. No frames should be discarded except by CloseStream.
+ // order they are Push'd, except RST_STREAM frames. No frames should be
+ // discarded except by CloseStream.
Pop() (wr http2FrameWriteRequest, ok bool)
}
// stream is the stream on which this frame will be written.
// nil for non-stream frames like PING and SETTINGS.
+ // nil for RST_STREAM streams, which use the StreamError.StreamID field instead.
stream *http2stream
// done, if non-nil, must be a buffered channel with space for
}
func (ws *http2randomWriteScheduler) Push(wr http2FrameWriteRequest) {
- id := wr.StreamID()
- if id == 0 {
+ if wr.isControl() {
ws.zero.push(wr)
return
}
+ id := wr.StreamID()
q, ok := ws.sq[id]
if !ok {
q = ws.queuePool.get()
}
func (ws *http2randomWriteScheduler) Pop() (http2FrameWriteRequest, bool) {
- // Control frames first.
+ // Control and RST_STREAM frames first.
if !ws.zero.empty() {
return ws.zero.shift(), true
}
// An RCode is a DNS response status code.
type RCode uint16
+// Header.RCode values.
const (
- // Message.Rcode
- RCodeSuccess RCode = 0
- RCodeFormatError RCode = 1
- RCodeServerFailure RCode = 2
- RCodeNameError RCode = 3
- RCodeNotImplemented RCode = 4
- RCodeRefused RCode = 5
+ RCodeSuccess RCode = 0 // NoError
+ RCodeFormatError RCode = 1 // FormErr
+ RCodeServerFailure RCode = 2 // ServFail
+ RCodeNameError RCode = 3 // NXDomain
+ RCodeNotImplemented RCode = 4 // NotImp
+ RCodeRefused RCode = 5 // Refused
)
var rCodeNames = map[RCode]string{
//
// The DNS message is appended to the provided initial buffer buf (which may be
// nil) as it is built. The final message is returned by the (*Builder).Finish
-// method, which may return the same underlying array if there was sufficient
-// capacity in the slice.
+// method, which includes buf[:len(buf)] and may return the same underlying
+// array if there was sufficient capacity in the slice.
func NewBuilder(buf []byte, h Header) Builder {
if buf == nil {
buf = make([]byte, 0, packStartingCap)
// SetEDNS0 configures h for EDNS(0).
//
-// The provided extRCode must be an extedned RCode.
+// The provided extRCode must be an extended RCode.
func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error {
h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2
h.Type = TypeOPT
// A Name is a non-encoded domain name. It is used instead of strings to avoid
// allocations.
type Name struct {
- Data [nameLen]byte
+ Data [nameLen]byte // 255 bytes
Length uint8
}
golang.org/x/crypto/hkdf
golang.org/x/crypto/internal/poly1305
golang.org/x/crypto/internal/subtle
-# golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9
+# golang.org/x/net v0.0.0-20211209124913-491a49abca63
## explicit; go 1.17
golang.org/x/net/dns/dnsmessage
golang.org/x/net/http/httpguts