app-containers/containerd: Update spdystream to v0.5.1

Patch generated by setting spdystream version to 0.5.1 in go.mod and
running `go mod tidy && go mod vendor && make vendor`.

BUG=b/502611924
TEST=presubmit
RELEASE_NOTE=Updated spdystream to v0.5.1 for containerd. This fixed CVE-2026-35469.

cos-patch: security-high
Change-Id: I430ed66bde209ab1b83683039a22d1ce29eb939a
Reviewed-on: https://cos-review.googlesource.com/c/cos/overlays/board-overlays/+/144194
Reviewed-by: Robert Kolchmeyer <rkolchmeyer@google.com>
Tested-by: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
Main-Branch-Verified: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
diff --git a/project-lakitu/app-containers/containerd/containerd-1.7.27-r2.ebuild b/project-lakitu/app-containers/containerd/containerd-1.7.27-r3.ebuild
similarity index 100%
rename from project-lakitu/app-containers/containerd/containerd-1.7.27-r2.ebuild
rename to project-lakitu/app-containers/containerd/containerd-1.7.27-r3.ebuild
diff --git a/project-lakitu/app-containers/containerd/containerd-1.7.27.ebuild b/project-lakitu/app-containers/containerd/containerd-1.7.27.ebuild
index 100cf48..c609144 100644
--- a/project-lakitu/app-containers/containerd/containerd-1.7.27.ebuild
+++ b/project-lakitu/app-containers/containerd/containerd-1.7.27.ebuild
@@ -65,6 +65,7 @@
 	"${FILESDIR}"/1.4.0-customize-containerd-service.patch
 	"${FILESDIR}"/1.7.27-CVE-2024-25621.patch
 	"${FILESDIR}"/1.7.27-CVE-2025-64329.patch
+	"${FILESDIR}"/1.7.27-update-github.com-moby-spdystream-v0.5.1.patch
 )
 
 src_prepare() {
diff --git a/project-lakitu/app-containers/containerd/files/1.7.27-update-github.com-moby-spdystream-v0.5.1.patch b/project-lakitu/app-containers/containerd/files/1.7.27-update-github.com-moby-spdystream-v0.5.1.patch
new file mode 100644
index 0000000..dd69048
--- /dev/null
+++ b/project-lakitu/app-containers/containerd/files/1.7.27-update-github.com-moby-spdystream-v0.5.1.patch
@@ -0,0 +1,756 @@
+From 8c26a76cbfa26764683df6ff23205ac68e310da3 Mon Sep 17 00:00:00 2001
+From: Kevin Berry <kpberry@google.com>
+Date: Wed, 15 Apr 2026 00:14:02 +0000
+Subject: [PATCH] update github.com/moby/spdystream v0.5.1
+
+Patch generated by setting spdystream version to 0.5.1 in go.mod and
+running `go mod tidy && go mod vendor`.
+---
+ go.mod                                        |  2 +-
+ go.sum                                        |  4 +-
+ integration/client/go.sum                     |  1 +
+ vendor/github.com/moby/spdystream/NOTICE      | 12 +++
+ .../github.com/moby/spdystream/connection.go  | 72 ++++++++++++-----
+ .../github.com/moby/spdystream/spdy/LICENSE   | 27 +++++++
+ .../github.com/moby/spdystream/spdy/PATENTS   | 22 +++++
+ .../moby/spdystream/spdy/dictionary.go        | 16 ----
+ .../moby/spdystream/spdy/options.go           | 25 ++++++
+ .../github.com/moby/spdystream/spdy/read.go   | 58 ++++++++-----
+ .../github.com/moby/spdystream/spdy/types.go  | 49 +++++++----
+ .../github.com/moby/spdystream/spdy/write.go  | 81 ++++++++++++-------
+ vendor/github.com/moby/spdystream/stream.go   |  2 +
+ vendor/modules.txt                            |  2 +-
+ 14 files changed, 265 insertions(+), 108 deletions(-)
+ create mode 100644 vendor/github.com/moby/spdystream/spdy/LICENSE
+ create mode 100644 vendor/github.com/moby/spdystream/spdy/PATENTS
+ create mode 100644 vendor/github.com/moby/spdystream/spdy/options.go
+
+diff --git a/go.mod b/go.mod
+index a7bb372ad..32090b08b 100644
+--- a/go.mod
++++ b/go.mod
+@@ -114,7 +114,7 @@ require (
+ 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ 	github.com/miekg/pkcs11 v1.1.1 // indirect
+ 	github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
+-	github.com/moby/spdystream v0.2.0 // indirect
++	github.com/moby/spdystream v0.5.1 // indirect
+ 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ 	github.com/modern-go/reflect2 v1.0.2 // indirect
+ 	github.com/pkg/errors v0.9.1 // indirect
+diff --git a/go.sum b/go.sum
+index a80a1f3fc..324faae86 100644
+--- a/go.sum
++++ b/go.sum
+@@ -512,8 +512,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
+ github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
+ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
+ github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
+-github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
+-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
++github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y=
++github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
+ github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+ github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
+ github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
+diff --git a/integration/client/go.sum b/integration/client/go.sum
+index e68d82b86..08ffb2ea6 100644
+--- a/integration/client/go.sum
++++ b/integration/client/go.sum
+@@ -1835,6 +1835,7 @@ github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34
+ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
+ github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
+ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
++github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
+ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+ github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
+ github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
+diff --git a/vendor/github.com/moby/spdystream/NOTICE b/vendor/github.com/moby/spdystream/NOTICE
+index b9b11c9ab..24e2e2aa3 100644
+--- a/vendor/github.com/moby/spdystream/NOTICE
++++ b/vendor/github.com/moby/spdystream/NOTICE
+@@ -3,3 +3,15 @@ Copyright 2014-2021 Docker Inc.
+ 
+ This product includes software developed at
+ Docker Inc. (https://www.docker.com/).
++
++SPDY implementation (spdy/)
++
++The spdy directory contains code derived from the Go project (golang.org/x/net).
++
++Copyright 2009-2013 The Go Authors.
++Licensed under the BSD 3-Clause License.
++
++Modifications Copyright 2014-2021 Docker Inc.
++
++The BSD license text and Go patent grant are included in
++spdy/LICENSE and spdy/PATENTS.
+diff --git a/vendor/github.com/moby/spdystream/connection.go b/vendor/github.com/moby/spdystream/connection.go
+index d906bb05c..69ce4777e 100644
+--- a/vendor/github.com/moby/spdystream/connection.go
++++ b/vendor/github.com/moby/spdystream/connection.go
+@@ -208,9 +208,10 @@ type Connection struct {
+ 	nextStreamId     spdy.StreamId
+ 	receivedStreamId spdy.StreamId
+ 
+-	pingIdLock sync.Mutex
+-	pingId     uint32
+-	pingChans  map[uint32]chan error
++	// pingLock protects pingChans and pingId
++	pingLock  sync.Mutex
++	pingId    uint32
++	pingChans map[uint32]chan error
+ 
+ 	shutdownLock sync.Mutex
+ 	shutdownChan chan error
+@@ -223,7 +224,13 @@ type Connection struct {
+ // NewConnection creates a new spdy connection from an existing
+ // network connection.
+ func NewConnection(conn net.Conn, server bool) (*Connection, error) {
+-	framer, framerErr := spdy.NewFramer(conn, conn)
++	return NewConnectionWithOptions(conn, server)
++}
++
++// NewConnectionWithOptions creates a new spdy connection and applies frame
++// parsing limits via options.
++func NewConnectionWithOptions(conn net.Conn, server bool, opts ...spdy.FramerOption) (*Connection, error) {
++	framer, framerErr := spdy.NewFramerWithOptions(conn, conn, opts...)
+ 	if framerErr != nil {
+ 		return nil, framerErr
+ 	}
+@@ -274,16 +281,20 @@ func NewConnection(conn net.Conn, server bool) (*Connection, error) {
+ // returns the response time
+ func (s *Connection) Ping() (time.Duration, error) {
+ 	pid := s.pingId
+-	s.pingIdLock.Lock()
++	s.pingLock.Lock()
+ 	if s.pingId > 0x7ffffffe {
+ 		s.pingId = s.pingId - 0x7ffffffe
+ 	} else {
+ 		s.pingId = s.pingId + 2
+ 	}
+-	s.pingIdLock.Unlock()
+ 	pingChan := make(chan error)
+ 	s.pingChans[pid] = pingChan
+-	defer delete(s.pingChans, pid)
++	s.pingLock.Unlock()
++	defer func() {
++		s.pingLock.Lock()
++		delete(s.pingChans, pid)
++		s.pingLock.Unlock()
++	}()
+ 
+ 	frame := &spdy.PingFrame{Id: pid}
+ 	startTime := time.Now()
+@@ -345,6 +356,9 @@ Loop:
+ 			} else {
+ 				debugMessage("(%p) EOF received", s)
+ 			}
++			if spdyErr, ok := err.(*spdy.Error); ok && spdyErr.Err == spdy.InvalidControlFrame {
++				_ = s.conn.Close()
++			}
+ 			break
+ 		}
+ 		var priority uint8
+@@ -612,10 +626,14 @@ func (s *Connection) handleDataFrame(frame *spdy.DataFrame) error {
+ }
+ 
+ func (s *Connection) handlePingFrame(frame *spdy.PingFrame) error {
+-	if s.pingId&0x01 != frame.Id&0x01 {
++	s.pingLock.Lock()
++	pingId := s.pingId
++	pingChan, pingOk := s.pingChans[frame.Id]
++	s.pingLock.Unlock()
++
++	if pingId&0x01 != frame.Id&0x01 {
+ 		return s.framer.WriteFrame(frame)
+ 	}
+-	pingChan, pingOk := s.pingChans[frame.Id]
+ 	if pingOk {
+ 		close(pingChan)
+ 	}
+@@ -703,7 +721,9 @@ func (s *Connection) shutdown(closeTimeout time.Duration) {
+ 
+ 	var timeout <-chan time.Time
+ 	if closeTimeout > time.Duration(0) {
+-		timeout = time.After(closeTimeout)
++		timer := time.NewTimer(closeTimeout)
++		defer timer.Stop()
++		timeout = timer.C
+ 	}
+ 	streamsClosed := make(chan bool)
+ 
+@@ -730,17 +750,23 @@ func (s *Connection) shutdown(closeTimeout time.Duration) {
+ 	}
+ 
+ 	if err != nil {
+-		duration := 10 * time.Minute
+-		time.AfterFunc(duration, func() {
+-			select {
+-			case err, ok := <-s.shutdownChan:
+-				if ok {
+-					debugMessage("Unhandled close error after %s: %s", duration, err)
+-				}
+-			default:
+-			}
+-		})
+-		s.shutdownChan <- err
++		// default to 1 second
++		duration := time.Second
++		// if a closeTimeout was given, use that, clipped to 1s-10m
++		if closeTimeout > time.Second {
++			duration = closeTimeout
++		}
++		if duration > 10*time.Minute {
++			duration = 10 * time.Minute
++		}
++		timer := time.NewTimer(duration)
++		defer timer.Stop()
++		select {
++		case s.shutdownChan <- err:
++			// error was handled
++		case <-timer.C:
++			debugMessage("Unhandled close error after %s: %s", duration, err)
++		}
+ 	}
+ 	close(s.shutdownChan)
+ }
+@@ -799,7 +825,9 @@ func (s *Connection) CloseWait() error {
+ func (s *Connection) Wait(waitTimeout time.Duration) error {
+ 	var timeout <-chan time.Time
+ 	if waitTimeout > time.Duration(0) {
+-		timeout = time.After(waitTimeout)
++		timer := time.NewTimer(waitTimeout)
++		defer timer.Stop()
++		timeout = timer.C
+ 	}
+ 
+ 	select {
+diff --git a/vendor/github.com/moby/spdystream/spdy/LICENSE b/vendor/github.com/moby/spdystream/spdy/LICENSE
+new file mode 100644
+index 000000000..6a66aea5e
+--- /dev/null
++++ b/vendor/github.com/moby/spdystream/spdy/LICENSE
+@@ -0,0 +1,27 @@
++Copyright (c) 2009 The Go Authors. All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are
++met:
++
++   * Redistributions of source code must retain the above copyright
++notice, this list of conditions and the following disclaimer.
++   * Redistributions in binary form must reproduce the above
++copyright notice, this list of conditions and the following disclaimer
++in the documentation and/or other materials provided with the
++distribution.
++   * Neither the name of Google Inc. nor the names of its
++contributors may be used to endorse or promote products derived from
++this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+diff --git a/vendor/github.com/moby/spdystream/spdy/PATENTS b/vendor/github.com/moby/spdystream/spdy/PATENTS
+new file mode 100644
+index 000000000..733099041
+--- /dev/null
++++ b/vendor/github.com/moby/spdystream/spdy/PATENTS
+@@ -0,0 +1,22 @@
++Additional IP Rights Grant (Patents)
++
++"This implementation" means the copyrightable works distributed by
++Google as part of the Go project.
++
++Google hereby grants to You a perpetual, worldwide, non-exclusive,
++no-charge, royalty-free, irrevocable (except as stated in this section)
++patent license to make, have made, use, offer to sell, sell, import,
++transfer and otherwise run, modify and propagate the contents of this
++implementation of Go, where such license applies only to those patent
++claims, both currently owned or controlled by Google and acquired in
++the future, licensable by Google that are necessarily infringed by this
++implementation of Go.  This grant does not include claims that would be
++infringed only as a consequence of further modification of this
++implementation.  If you or your agent or exclusive licensee institute or
++order or agree to the institution of patent litigation against any
++entity (including a cross-claim or counterclaim in a lawsuit) alleging
++that this implementation of Go or any code incorporated within this
++implementation of Go constitutes direct or contributory patent
++infringement, or inducement of patent infringement, then any patent
++rights granted to you under this License for this implementation of Go
++shall terminate as of the date such litigation is filed.
+diff --git a/vendor/github.com/moby/spdystream/spdy/dictionary.go b/vendor/github.com/moby/spdystream/spdy/dictionary.go
+index 392232f17..5a5ff0e14 100644
+--- a/vendor/github.com/moby/spdystream/spdy/dictionary.go
++++ b/vendor/github.com/moby/spdystream/spdy/dictionary.go
+@@ -1,19 +1,3 @@
+-/*
+-   Copyright 2014-2021 Docker Inc.
+-
+-   Licensed under the Apache License, Version 2.0 (the "License");
+-   you may not use this file except in compliance with the License.
+-   You may obtain a copy of the License at
+-
+-       http://www.apache.org/licenses/LICENSE-2.0
+-
+-   Unless required by applicable law or agreed to in writing, software
+-   distributed under the License is distributed on an "AS IS" BASIS,
+-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-   See the License for the specific language governing permissions and
+-   limitations under the License.
+-*/
+-
+ // Copyright 2013 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+diff --git a/vendor/github.com/moby/spdystream/spdy/options.go b/vendor/github.com/moby/spdystream/spdy/options.go
+new file mode 100644
+index 000000000..ec03e0b9a
+--- /dev/null
++++ b/vendor/github.com/moby/spdystream/spdy/options.go
+@@ -0,0 +1,25 @@
++package spdy
++
++// FramerOption allows callers to customize frame parsing limits.
++type FramerOption func(*Framer)
++
++// WithMaxControlFramePayloadSize sets the control-frame payload limit.
++func WithMaxControlFramePayloadSize(size uint32) FramerOption {
++	return func(f *Framer) {
++		f.maxFrameLength = size
++	}
++}
++
++// WithMaxHeaderFieldSize sets the per-header name/value size limit.
++func WithMaxHeaderFieldSize(size uint32) FramerOption {
++	return func(f *Framer) {
++		f.maxHeaderFieldSize = size
++	}
++}
++
++// WithMaxHeaderCount sets the maximum number of headers in a frame.
++func WithMaxHeaderCount(count uint32) FramerOption {
++	return func(f *Framer) {
++		f.maxHeaderCount = count
++	}
++}
+diff --git a/vendor/github.com/moby/spdystream/spdy/read.go b/vendor/github.com/moby/spdystream/spdy/read.go
+index 75ea045b8..2abb69433 100644
+--- a/vendor/github.com/moby/spdystream/spdy/read.go
++++ b/vendor/github.com/moby/spdystream/spdy/read.go
+@@ -1,19 +1,3 @@
+-/*
+-   Copyright 2014-2021 Docker Inc.
+-
+-   Licensed under the Apache License, Version 2.0 (the "License");
+-   you may not use this file except in compliance with the License.
+-   You may obtain a copy of the License at
+-
+-       http://www.apache.org/licenses/LICENSE-2.0
+-
+-   Unless required by applicable law or agreed to in writing, software
+-   distributed under the License is distributed on an "AS IS" BASIS,
+-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-   See the License for the specific language governing permissions and
+-   limitations under the License.
+-*/
+-
+ // Copyright 2011 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+@@ -24,6 +8,7 @@ import (
+ 	"compress/zlib"
+ 	"encoding/binary"
+ 	"io"
++	"io/ioutil"
+ 	"net/http"
+ 	"strings"
+ )
+@@ -59,6 +44,11 @@ func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
+ 	if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
+ 		return err
+ 	}
++	// Each setting is 8 bytes (4-byte id + 4-byte value).
++	// Payload is 4 bytes for numSettings + numSettings*8.
++	if h.length < 4 || numSettings > (h.length-4)/8 {
++		return &Error{InvalidControlFrame, 0}
++	}
+ 	frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
+ 	for i := uint32(0); i < numSettings; i++ {
+ 		if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
+@@ -177,8 +167,19 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (
+ 	if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
+ 		return nil, err
+ 	}
++	maxControlFramePayload := uint32(MaxDataLength)
++	if f.maxFrameLength > 0 {
++		maxControlFramePayload = f.maxFrameLength
++	}
++
+ 	flags := ControlFlags((length & 0xff000000) >> 24)
+ 	length &= 0xffffff
++	if length > maxControlFramePayload {
++		if _, err := io.CopyN(ioutil.Discard, f.r, int64(length)); err != nil {
++			return nil, err
++		}
++		return nil, &Error{InvalidControlFrame, 0}
++	}
+ 	header := ControlFrameHeader{version, frameType, flags, length}
+ 	cframe, err := newControlFrame(frameType)
+ 	if err != nil {
+@@ -190,11 +191,22 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (
+ 	return cframe, nil
+ }
+ 
+-func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
++func (f *Framer) parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
+ 	var numHeaders uint32
+ 	if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
+ 		return nil, err
+ 	}
++	maxHeaders := defaultMaxHeaderCount
++	if f.maxHeaderCount > 0 {
++		maxHeaders = f.maxHeaderCount
++	}
++	if numHeaders > maxHeaders {
++		return nil, &Error{InvalidControlFrame, streamId}
++	}
++	maxFieldSize := defaultMaxHeaderFieldSize
++	if f.maxHeaderFieldSize > 0 {
++		maxFieldSize = f.maxHeaderFieldSize
++	}
+ 	var e error
+ 	h := make(http.Header, int(numHeaders))
+ 	for i := 0; i < int(numHeaders); i++ {
+@@ -202,6 +214,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error)
+ 		if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+ 			return nil, err
+ 		}
++		if length > maxFieldSize {
++			return nil, &Error{InvalidControlFrame, streamId}
++		}
+ 		nameBytes := make([]byte, length)
+ 		if _, err := io.ReadFull(r, nameBytes); err != nil {
+ 			return nil, err
+@@ -217,6 +232,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error)
+ 		if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+ 			return nil, err
+ 		}
++		if length > maxFieldSize {
++			return nil, &Error{InvalidControlFrame, streamId}
++		}
+ 		value := make([]byte, length)
+ 		if _, err := io.ReadFull(r, value); err != nil {
+ 			return nil, err
+@@ -256,7 +274,7 @@ func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame)
+ 		}
+ 		reader = f.headerDecompressor
+ 	}
+-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
++	frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId)
+ 	if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
+ 		err = &Error{WrongCompressedPayloadSize, 0}
+ 	}
+@@ -288,7 +306,7 @@ func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) e
+ 		}
+ 		reader = f.headerDecompressor
+ 	}
+-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
++	frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId)
+ 	if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
+ 		err = &Error{WrongCompressedPayloadSize, 0}
+ 	}
+@@ -320,7 +338,7 @@ func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) err
+ 		}
+ 		reader = f.headerDecompressor
+ 	}
+-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
++	frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId)
+ 	if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
+ 		err = &Error{WrongCompressedPayloadSize, 0}
+ 	}
+diff --git a/vendor/github.com/moby/spdystream/spdy/types.go b/vendor/github.com/moby/spdystream/spdy/types.go
+index a254a43ab..a5528618c 100644
+--- a/vendor/github.com/moby/spdystream/spdy/types.go
++++ b/vendor/github.com/moby/spdystream/spdy/types.go
+@@ -1,23 +1,9 @@
+-/*
+-   Copyright 2014-2021 Docker Inc.
+-
+-   Licensed under the Apache License, Version 2.0 (the "License");
+-   you may not use this file except in compliance with the License.
+-   You may obtain a copy of the License at
+-
+-       http://www.apache.org/licenses/LICENSE-2.0
+-
+-   Unless required by applicable law or agreed to in writing, software
+-   distributed under the License is distributed on an "AS IS" BASIS,
+-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-   See the License for the specific language governing permissions and
+-   limitations under the License.
+-*/
+-
+ // Copyright 2011 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+ 
++// Modifications Copyright 2014-2021 Docker Inc.
++
+ // Package spdy implements the SPDY protocol (currently SPDY/3), described in
+ // http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3.
+ package spdy
+@@ -63,8 +49,20 @@ const (
+ )
+ 
+ // MaxDataLength is the maximum number of bytes that can be stored in one frame.
++//
++// SPDY frame headers encode the payload length using a 24-bit field,
++// so the maximum representable size for both data and control frames
++// is 2^24-1 bytes.
++//
++// See the SPDY/3 specification, "Frame Format":
++// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1/
+ const MaxDataLength = 1<<24 - 1
+ 
++const (
++	defaultMaxHeaderFieldSize uint32 = 1 << 20
++	defaultMaxHeaderCount     uint32 = 1000
++)
++
+ // headerValueSepator separates multiple header values.
+ const headerValueSeparator = "\x00"
+ 
+@@ -269,6 +267,10 @@ type Framer struct {
+ 	r                         io.Reader
+ 	headerReader              io.LimitedReader
+ 	headerDecompressor        io.ReadCloser
++
++	maxFrameLength       uint32 // overrides the default frame payload length limit.
++	maxHeaderFieldSize   uint32 // overrides the default per-header name/value length limit.
++	maxHeaderCount       uint32 // overrides the default header count limit.
+ }
+ 
+ // NewFramer allocates a new Framer for a given SPDY connection, represented by
+@@ -276,6 +278,16 @@ type Framer struct {
+ // from/to the Reader and Writer, so the caller should pass in an appropriately
+ // buffered implementation to optimize performance.
+ func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
++	return newFramer(w, r)
++}
++
++// NewFramerWithOptions allocates a new Framer for a given SPDY connection and
++// applies frame parsing limits via options.
++func NewFramerWithOptions(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) {
++	return newFramer(w, r, opts...)
++}
++
++func newFramer(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) {
+ 	compressBuf := new(bytes.Buffer)
+ 	compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary))
+ 	if err != nil {
+@@ -287,5 +299,10 @@ func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
+ 		headerCompressor: compressor,
+ 		r:                r,
+ 	}
++	for _, opt := range opts {
++		if opt != nil {
++			opt(framer)
++		}
++	}
+ 	return framer, nil
+ }
+diff --git a/vendor/github.com/moby/spdystream/spdy/write.go b/vendor/github.com/moby/spdystream/spdy/write.go
+index ab6d91f3b..75084d35d 100644
+--- a/vendor/github.com/moby/spdystream/spdy/write.go
++++ b/vendor/github.com/moby/spdystream/spdy/write.go
+@@ -1,19 +1,3 @@
+-/*
+-   Copyright 2014-2021 Docker Inc.
+-
+-   Licensed under the Apache License, Version 2.0 (the "License");
+-   you may not use this file except in compliance with the License.
+-   You may obtain a copy of the License at
+-
+-       http://www.apache.org/licenses/LICENSE-2.0
+-
+-   Unless required by applicable law or agreed to in writing, software
+-   distributed under the License is distributed on an "AS IS" BASIS,
+-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-   See the License for the specific language governing permissions and
+-   limitations under the License.
+-*/
+-
+ // Copyright 2011 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+@@ -23,6 +7,7 @@ package spdy
+ import (
+ 	"encoding/binary"
+ 	"io"
++	"math"
+ 	"net/http"
+ 	"strings"
+ )
+@@ -63,13 +48,21 @@ func (frame *RstStreamFrame) write(f *Framer) (err error) {
+ func (frame *SettingsFrame) write(f *Framer) (err error) {
+ 	frame.CFHeader.version = Version
+ 	frame.CFHeader.frameType = TypeSettings
+-	frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
++	payloadLen := len(frame.FlagIdValues)*8 + 4
++	if payloadLen > MaxDataLength {
++		return &Error{InvalidControlFrame, 0}
++	}
++	frame.CFHeader.length = uint32(payloadLen)
+ 
+ 	// Serialize frame to Writer.
+ 	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
+ 		return
+ 	}
+-	if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
++	n := len(frame.FlagIdValues)
++	if uint64(n) > math.MaxUint32 {
++		return &Error{InvalidControlFrame, 0}
++	}
++	if err = binary.Write(f.w, binary.BigEndian, uint32(n)); err != nil {
+ 		return
+ 	}
+ 	for _, flagIdValue := range frame.FlagIdValues {
+@@ -170,29 +163,41 @@ func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
+ 
+ func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
+ 	n = 0
+-	if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
++	numHeaders := len(h)
++	if numHeaders > math.MaxInt32 {
++		return n, &Error{InvalidControlFrame, 0}
++	}
++	if err = binary.Write(w, binary.BigEndian, uint32(numHeaders)); err != nil {
+ 		return
+ 	}
+-	n += 2
++	n += 4
+ 	for name, values := range h {
+-		if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
++		nameLen := len(name)
++		if nameLen > math.MaxInt32 {
++			return n, &Error{InvalidControlFrame, 0}
++		}
++		if err = binary.Write(w, binary.BigEndian, uint32(nameLen)); err != nil {
+ 			return
+ 		}
+-		n += 2
++		n += 4
+ 		name = strings.ToLower(name)
+ 		if _, err = io.WriteString(w, name); err != nil {
+ 			return
+ 		}
+-		n += len(name)
++		n += nameLen
+ 		v := strings.Join(values, headerValueSeparator)
+-		if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
++		vLen := len(v)
++		if vLen > math.MaxInt32 {
++			return n, &Error{InvalidControlFrame, 0}
++		}
++		if err = binary.Write(w, binary.BigEndian, uint32(vLen)); err != nil {
+ 			return
+ 		}
+-		n += 2
++		n += 4
+ 		if _, err = io.WriteString(w, v); err != nil {
+ 			return
+ 		}
+-		n += len(v)
++		n += vLen
+ 	}
+ 	return
+ }
+@@ -216,7 +221,11 @@ func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
+ 	// Set ControlFrameHeader.
+ 	frame.CFHeader.version = Version
+ 	frame.CFHeader.frameType = TypeSynStream
+-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
++	hLen := len(f.headerBuf.Bytes()) + 10
++	if hLen > MaxDataLength {
++		return &Error{InvalidControlFrame, 0}
++	}
++	frame.CFHeader.length = uint32(hLen)
+ 
+ 	// Serialize frame to Writer.
+ 	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
+@@ -260,7 +269,11 @@ func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
+ 	// Set ControlFrameHeader.
+ 	frame.CFHeader.version = Version
+ 	frame.CFHeader.frameType = TypeSynReply
+-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
++	hLen := len(f.headerBuf.Bytes()) + 4
++	if hLen > MaxDataLength {
++		return &Error{InvalidControlFrame, 0}
++	}
++	frame.CFHeader.length = uint32(hLen)
+ 
+ 	// Serialize frame to Writer.
+ 	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
+@@ -295,7 +308,11 @@ func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
+ 	// Set ControlFrameHeader.
+ 	frame.CFHeader.version = Version
+ 	frame.CFHeader.frameType = TypeHeaders
+-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
++	hLen := len(f.headerBuf.Bytes()) + 4
++	if hLen > MaxDataLength {
++		return &Error{InvalidControlFrame, 0}
++	}
++	frame.CFHeader.length = uint32(hLen)
+ 
+ 	// Serialize frame to Writer.
+ 	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
+@@ -323,7 +340,11 @@ func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
+ 	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
+ 		return
+ 	}
+-	flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
++	dLen := len(frame.Data)
++	if dLen > MaxDataLength {
++		return &Error{InvalidDataFrame, frame.StreamId}
++	}
++	flagsAndLength := uint32(frame.Flags)<<24 | uint32(dLen)
+ 	if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
+ 		return
+ 	}
+diff --git a/vendor/github.com/moby/spdystream/stream.go b/vendor/github.com/moby/spdystream/stream.go
+index 404e3c02d..171c1e9e3 100644
+--- a/vendor/github.com/moby/spdystream/stream.go
++++ b/vendor/github.com/moby/spdystream/stream.go
+@@ -305,6 +305,8 @@ func (s *Stream) Identifier() uint32 {
+ // IsFinished returns whether the stream has finished
+ // sending data
+ func (s *Stream) IsFinished() bool {
++	s.finishLock.Lock()
++	defer s.finishLock.Unlock()
+ 	return s.finished
+ }
+ 
+diff --git a/vendor/modules.txt b/vendor/modules.txt
+index 533b56dda..ba46ac28d 100644
+--- a/vendor/modules.txt
++++ b/vendor/modules.txt
+@@ -348,7 +348,7 @@ github.com/mistifyio/go-zfs/v3
+ # github.com/moby/locker v1.0.1
+ ## explicit; go 1.13
+ github.com/moby/locker
+-# github.com/moby/spdystream v0.2.0
++# github.com/moby/spdystream v0.5.1
+ ## explicit; go 1.13
+ github.com/moby/spdystream
+ github.com/moby/spdystream/spdy
+-- 
+2.54.0.rc0.605.g598a273b03-goog
+