[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1031330: [pre-approval] unblock: golang-1.19/1.19.6-2



On 2023-02-15 11:58:54 +0800, Shengjing Zhu wrote:
> Package: release.debian.org
> Severity: normal
> User: release.debian.org@packages.debian.org
> Usertags: unblock
> X-Debbugs-Cc: golang-1.19@packages.debian.org, zhsj@debian.org
> Control: affects -1 + src:golang-1.19
> 
> Please unblock package golang-1.19

Please go ahead with the upload.

> 
> [ Reason ]
> A new upstream release that addresses 4 CVE in Go standard library.
> 
> [ Impact ]
> CVE in Go standard library and the Go packages that have statically
> linked with it.
> 
> [ Tests ]
> The fixes are covered by new unit tests.
> 
> [ Risks ]
> The package is in the toolchain set.
> 
> [ Checklist ]
>   [x] all changes are documented in the d/changelog
>   [x] I reviewed all changes and I approve them
>   [x] attach debdiff against the package in testing
> 
>       The diff is for golang-1.19/1.19.6-1, which I have uploaded to
>       experimental first. -2 should be no-change rebuild on unstable.
> 
> [ Other info ]
> So same as previous unblock request #1028452
> + This package doesn't have autopkgtest.
> + The upload will trigger Release Team to perform a new round of rebuilding
>   outdated Built-Using for all Go packages.
> 
> The Go upstream usually has one minor version (may or may not carry CVE
> fixes) release every month.
> I'm wondering what Release Team thinks how often we should update
> during the freeze periods. Some options are:
> + Only ask pre-approval for minor versions with CVE
> + Don't update any (probably at late freeze period, like hard/full-freeze).

I would suggest to stick to versions fixing CVEs for now. If there is a
no-CVE releases between the last update and the start of the hard
freeze, we can revisit a final update and rebuild of the golang-world.

Cheers

> 
> The package currently FTBFS on i386/experimental but it won't be problem on
> unstable.
> The dep-resolver (aspcud) in experimental chooses gccgo to bootstrap,
> which has a bug https://github.com/golang/go/issues/51850.
> But on unstable the dep-resolver is apt, and will choose old golang-go to
> bootstrap.
> 
> unblock golang-1.19/1.19.6-2

> diff -Nru golang-1.19-1.19.5/debian/changelog golang-1.19-1.19.6/debian/changelog
> --- golang-1.19-1.19.5/debian/changelog	2023-01-11 15:35:00.000000000 +0800
> +++ golang-1.19-1.19.6/debian/changelog	2023-02-15 10:09:02.000000000 +0800
> @@ -1,3 +1,16 @@
> +golang-1.19 (1.19.6-1) experimental; urgency=medium
> +
> +  * Team upload
> +  * New upstream version 1.19.6
> +    + CVE-2022-41722: path/filepath: path traversal in filepath.Clean on
> +      Windows
> +    + CVE-2022-41725: net/http, mime/multipart: denial of service from
> +      excessive resource consumption
> +    + CVE-2022-41724: crypto/tls: large handshake records may cause panics
> +    + CVE-2022-41723: net/http: avoid quadratic complexity in HPACK decoding
> +
> + -- Shengjing Zhu <zhsj@debian.org>  Wed, 15 Feb 2023 10:09:02 +0800
> +
>  golang-1.19 (1.19.5-1) unstable; urgency=medium
>  
>    * Team upload
> diff -Nru golang-1.19-1.19.5/src/cmd/go/internal/modfetch/coderepo_test.go golang-1.19-1.19.6/src/cmd/go/internal/modfetch/coderepo_test.go
> --- golang-1.19-1.19.5/src/cmd/go/internal/modfetch/coderepo_test.go	2023-01-10 06:38:03.000000000 +0800
> +++ golang-1.19-1.19.6/src/cmd/go/internal/modfetch/coderepo_test.go	2023-02-14 01:38:43.000000000 +0800
> @@ -379,18 +379,6 @@
>  		zipFileHash: "c15e49d58b7a4c37966cbe5bc01a0330cd5f2927e990e1839bda1d407766d9c5",
>  	},
>  	{
> -		vcs:         "git",
> -		path:        "gopkg.in/natefinch/lumberjack.v2",
> -		rev:         "latest",
> -		version:     "v2.0.0-20170531160350-a96e63847dc3",
> -		name:        "a96e63847dc3c67d17befa69c303767e2f84e54f",
> -		short:       "a96e63847dc3",
> -		time:        time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC),
> -		gomod:       "module gopkg.in/natefinch/lumberjack.v2\n",
> -		zipSum:      "h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=",
> -		zipFileHash: "b5de0da7bbbec76709eef1ac71b6c9ff423b9fbf3bb97b56743450d4937b06d5",
> -	},
> -	{
>  		vcs:  "git",
>  		path: "gopkg.in/natefinch/lumberjack.v2",
>  		// This repo has a v2.1 tag.
> @@ -578,6 +566,10 @@
>  	for _, tt := range codeRepoTests {
>  		f := func(tt codeRepoTest) func(t *testing.T) {
>  			return func(t *testing.T) {
> +				if strings.Contains(tt.path, "gopkg.in") {
> +					testenv.SkipFlaky(t, 54503)
> +				}
> +
>  				t.Parallel()
>  				if tt.vcs != "mod" {
>  					testenv.MustHaveExecPath(t, tt.vcs)
> @@ -790,11 +782,6 @@
>  	},
>  	{
>  		vcs:      "git",
> -		path:     "gopkg.in/natefinch/lumberjack.v2",
> -		versions: []string{"v2.0.0"},
> -	},
> -	{
> -		vcs:      "git",
>  		path:     "vcs-test.golang.org/git/odd-tags.git",
>  		versions: nil,
>  	},
> @@ -811,8 +798,12 @@
>  
>  	t.Run("parallel", func(t *testing.T) {
>  		for _, tt := range codeRepoVersionsTests {
> +			tt := tt
>  			t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
> -				tt := tt
> +				if strings.Contains(tt.path, "gopkg.in") {
> +					testenv.SkipFlaky(t, 54503)
> +				}
> +
>  				t.Parallel()
>  				if tt.vcs != "mod" {
>  					testenv.MustHaveExecPath(t, tt.vcs)
> diff -Nru golang-1.19-1.19.5/src/cmd/go/testdata/script/mod_gopkg_unstable.txt golang-1.19-1.19.6/src/cmd/go/testdata/script/mod_gopkg_unstable.txt
> --- golang-1.19-1.19.5/src/cmd/go/testdata/script/mod_gopkg_unstable.txt	2023-01-10 06:38:05.000000000 +0800
> +++ golang-1.19-1.19.6/src/cmd/go/testdata/script/mod_gopkg_unstable.txt	2023-02-14 01:38:43.000000000 +0800
> @@ -10,6 +10,8 @@
>  [!net] skip
>  [!exec:git] skip
>  
> +skip  # TODO(#54503): redirect gopkg.in requests to a local server and re-enable.
> +
>  env GOPROXY=direct
>  env GOSUMDB=off
>  go get gopkg.in/macaroon-bakery.v2-unstable/bakery
> diff -Nru golang-1.19-1.19.5/src/cmd/go/testdata/script/version_gc_sections.txt golang-1.19-1.19.6/src/cmd/go/testdata/script/version_gc_sections.txt
> --- golang-1.19-1.19.5/src/cmd/go/testdata/script/version_gc_sections.txt	1970-01-01 08:00:00.000000000 +0800
> +++ golang-1.19-1.19.6/src/cmd/go/testdata/script/version_gc_sections.txt	2023-02-14 01:38:43.000000000 +0800
> @@ -0,0 +1,24 @@
> +# This test checks that external linking with --gc-sections does not strip version information.
> +
> +[short] skip
> +[!cgo] skip
> +[aix] skip  # no --gc-sections
> +[darwin] skip  # no --gc-sections
> +
> +go build -ldflags='-linkmode=external -extldflags=-Wl,--gc-sections'
> +go version hello$GOEXE
> +! stdout 'not a Go executable'
> +! stderr 'not a Go executable'
> +
> +-- go.mod --
> +module hello
> +-- hello.go --
> +package main
> +
> +/*
> +*/
> +import "C"
> +
> +func main() {
> +	println("hello")
> +}
> diff -Nru golang-1.19-1.19.5/src/cmd/internal/moddeps/moddeps_test.go golang-1.19-1.19.6/src/cmd/internal/moddeps/moddeps_test.go
> --- golang-1.19-1.19.5/src/cmd/internal/moddeps/moddeps_test.go	2023-01-10 06:38:05.000000000 +0800
> +++ golang-1.19-1.19.6/src/cmd/internal/moddeps/moddeps_test.go	2023-02-14 01:38:43.000000000 +0800
> @@ -33,7 +33,7 @@
>  // See issues 36852, 41409, and 43687.
>  // (Also see golang.org/issue/27348.)
>  func TestAllDependencies(t *testing.T) {
> -	t.Skip("TODO(#57009): 1.19.4 contains unreleased changes from vendored modules")
> +	t.Skip("TODO(#58355): 1.19.4 contains unreleased changes from vendored modules")
>  
>  	goBin := testenv.GoToolPath(t)
>  
> diff -Nru golang-1.19-1.19.5/src/cmd/link/internal/ld/data.go golang-1.19-1.19.6/src/cmd/link/internal/ld/data.go
> --- golang-1.19-1.19.5/src/cmd/link/internal/ld/data.go	2023-01-10 06:38:05.000000000 +0800
> +++ golang-1.19-1.19.6/src/cmd/link/internal/ld/data.go	2023-02-14 01:38:43.000000000 +0800
> @@ -1601,6 +1601,9 @@
>  func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section {
>  	ldr := state.ctxt.loader
>  	sname := ldr.SymName(s)
> +	if sname == "go.buildinfo" { // clumsy hack for Go 1.19 builders
> +		sname = ".go.buildinfo"
> +	}
>  	sect := addsection(ldr, state.ctxt.Arch, seg, sname, rwx)
>  	sect.Align = symalign(ldr, s)
>  	state.datsize = Rnd(state.datsize, int64(sect.Align))
> @@ -2177,7 +2180,7 @@
>  	// Write the buildinfo symbol, which go version looks for.
>  	// The code reading this data is in package debug/buildinfo.
>  	ldr := ctxt.loader
> -	s := ldr.CreateSymForUpdate(".go.buildinfo", 0)
> +	s := ldr.CreateSymForUpdate("go.buildinfo", 0)
>  	s.SetType(sym.SBUILDINFO)
>  	s.SetAlign(16)
>  	// The \xff is invalid UTF-8, meant to make it less likely
> @@ -2199,6 +2202,14 @@
>  	}
>  	s.SetData(data)
>  	s.SetSize(int64(len(data)))
> +
> +	// Add reference to go:buildinfo from the rodata section,
> +	// so that external linking with -Wl,--gc-sections does not
> +	// delete the build info.
> +	sr := ldr.CreateSymForUpdate("go.buildinfo.ref", 0)
> +	sr.SetType(sym.SRODATA)
> +	sr.SetAlign(int32(ctxt.Arch.PtrSize))
> +	sr.AddAddr(ctxt.Arch, s.Sym())
>  }
>  
>  // appendString appends s to data, prefixed by its varint-encoded length.
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/boring_test.go golang-1.19-1.19.6/src/crypto/tls/boring_test.go
> --- golang-1.19-1.19.5/src/crypto/tls/boring_test.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/boring_test.go	2023-02-14 01:38:45.000000000 +0800
> @@ -269,7 +269,7 @@
>  
>  	go Client(c, clientConfig).Handshake()
>  	srv := Server(s, testConfig)
> -	msg, err := srv.readHandshake()
> +	msg, err := srv.readHandshake(nil)
>  	if err != nil {
>  		t.Fatal(err)
>  	}
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/common.go golang-1.19-1.19.6/src/crypto/tls/common.go
> --- golang-1.19-1.19.5/src/crypto/tls/common.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/common.go	2023-02-14 01:38:45.000000000 +0800
> @@ -1384,7 +1384,7 @@
>  }
>  
>  type handshakeMessage interface {
> -	marshal() []byte
> +	marshal() ([]byte, error)
>  	unmarshal([]byte) bool
>  }
>  
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/conn.go golang-1.19-1.19.6/src/crypto/tls/conn.go
> --- golang-1.19-1.19.5/src/crypto/tls/conn.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/conn.go	2023-02-14 01:38:45.000000000 +0800
> @@ -1003,18 +1003,37 @@
>  	return n, nil
>  }
>  
> -// writeRecord writes a TLS record with the given type and payload to the
> -// connection and updates the record layer state.
> -func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) {
> +// writeHandshakeRecord writes a handshake message to the connection and updates
> +// the record layer state. If transcript is non-nil the marshalled message is
> +// written to it.
> +func (c *Conn) writeHandshakeRecord(msg handshakeMessage, transcript transcriptHash) (int, error) {
>  	c.out.Lock()
>  	defer c.out.Unlock()
>  
> -	return c.writeRecordLocked(typ, data)
> +	data, err := msg.marshal()
> +	if err != nil {
> +		return 0, err
> +	}
> +	if transcript != nil {
> +		transcript.Write(data)
> +	}
> +
> +	return c.writeRecordLocked(recordTypeHandshake, data)
> +}
> +
> +// writeChangeCipherRecord writes a ChangeCipherSpec message to the connection and
> +// updates the record layer state.
> +func (c *Conn) writeChangeCipherRecord() error {
> +	c.out.Lock()
> +	defer c.out.Unlock()
> +	_, err := c.writeRecordLocked(recordTypeChangeCipherSpec, []byte{1})
> +	return err
>  }
>  
>  // readHandshake reads the next handshake message from
> -// the record layer.
> -func (c *Conn) readHandshake() (any, error) {
> +// the record layer. If transcript is non-nil, the message
> +// is written to the passed transcriptHash.
> +func (c *Conn) readHandshake(transcript transcriptHash) (any, error) {
>  	for c.hand.Len() < 4 {
>  		if err := c.readRecord(); err != nil {
>  			return nil, err
> @@ -1093,6 +1112,11 @@
>  	if !m.unmarshal(data) {
>  		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
>  	}
> +
> +	if transcript != nil {
> +		transcript.Write(data)
> +	}
> +
>  	return m, nil
>  }
>  
> @@ -1168,7 +1192,7 @@
>  		return errors.New("tls: internal error: unexpected renegotiation")
>  	}
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -1214,7 +1238,7 @@
>  		return c.handleRenegotiation()
>  	}
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -1250,7 +1274,11 @@
>  		defer c.out.Unlock()
>  
>  		msg := &keyUpdateMsg{}
> -		_, err := c.writeRecordLocked(recordTypeHandshake, msg.marshal())
> +		msgBytes, err := msg.marshal()
> +		if err != nil {
> +			return err
> +		}
> +		_, err = c.writeRecordLocked(recordTypeHandshake, msgBytes)
>  		if err != nil {
>  			// Surface the error at the next write.
>  			c.out.setErrorLocked(err)
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_client.go golang-1.19-1.19.6/src/crypto/tls/handshake_client.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_client.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_client.go	2023-02-14 01:38:45.000000000 +0800
> @@ -162,7 +162,10 @@
>  	}
>  	c.serverName = hello.serverName
>  
> -	cacheKey, session, earlySecret, binderKey := c.loadSession(hello)
> +	cacheKey, session, earlySecret, binderKey, err := c.loadSession(hello)
> +	if err != nil {
> +		return err
> +	}
>  	if cacheKey != "" && session != nil {
>  		defer func() {
>  			// If we got a handshake failure when resuming a session, throw away
> @@ -177,11 +180,12 @@
>  		}()
>  	}
>  
> -	if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil {
> +	if _, err := c.writeHandshakeRecord(hello, nil); err != nil {
>  		return err
>  	}
>  
> -	msg, err := c.readHandshake()
> +	// serverHelloMsg is not included in the transcript
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -246,9 +250,9 @@
>  }
>  
>  func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string,
> -	session *ClientSessionState, earlySecret, binderKey []byte) {
> +	session *ClientSessionState, earlySecret, binderKey []byte, err error) {
>  	if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
> -		return "", nil, nil, nil
> +		return "", nil, nil, nil, nil
>  	}
>  
>  	hello.ticketSupported = true
> @@ -263,14 +267,14 @@
>  	// renegotiation is primarily used to allow a client to send a client
>  	// certificate, which would be skipped if session resumption occurred.
>  	if c.handshakes != 0 {
> -		return "", nil, nil, nil
> +		return "", nil, nil, nil, nil
>  	}
>  
>  	// Try to resume a previously negotiated TLS session, if available.
>  	cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
>  	session, ok := c.config.ClientSessionCache.Get(cacheKey)
>  	if !ok || session == nil {
> -		return cacheKey, nil, nil, nil
> +		return cacheKey, nil, nil, nil, nil
>  	}
>  
>  	// Check that version used for the previous session is still valid.
> @@ -282,7 +286,7 @@
>  		}
>  	}
>  	if !versOk {
> -		return cacheKey, nil, nil, nil
> +		return cacheKey, nil, nil, nil, nil
>  	}
>  
>  	// Check that the cached server certificate is not expired, and that it's
> @@ -291,16 +295,16 @@
>  	if !c.config.InsecureSkipVerify {
>  		if len(session.verifiedChains) == 0 {
>  			// The original connection had InsecureSkipVerify, while this doesn't.
> -			return cacheKey, nil, nil, nil
> +			return cacheKey, nil, nil, nil, nil
>  		}
>  		serverCert := session.serverCertificates[0]
>  		if c.config.time().After(serverCert.NotAfter) {
>  			// Expired certificate, delete the entry.
>  			c.config.ClientSessionCache.Put(cacheKey, nil)
> -			return cacheKey, nil, nil, nil
> +			return cacheKey, nil, nil, nil, nil
>  		}
>  		if err := serverCert.VerifyHostname(c.config.ServerName); err != nil {
> -			return cacheKey, nil, nil, nil
> +			return cacheKey, nil, nil, nil, nil
>  		}
>  	}
>  
> @@ -308,7 +312,7 @@
>  		// In TLS 1.2 the cipher suite must match the resumed session. Ensure we
>  		// are still offering it.
>  		if mutualCipherSuite(hello.cipherSuites, session.cipherSuite) == nil {
> -			return cacheKey, nil, nil, nil
> +			return cacheKey, nil, nil, nil, nil
>  		}
>  
>  		hello.sessionTicket = session.sessionTicket
> @@ -318,14 +322,14 @@
>  	// Check that the session ticket is not expired.
>  	if c.config.time().After(session.useBy) {
>  		c.config.ClientSessionCache.Put(cacheKey, nil)
> -		return cacheKey, nil, nil, nil
> +		return cacheKey, nil, nil, nil, nil
>  	}
>  
>  	// In TLS 1.3 the KDF hash must match the resumed session. Ensure we
>  	// offer at least one cipher suite with that hash.
>  	cipherSuite := cipherSuiteTLS13ByID(session.cipherSuite)
>  	if cipherSuite == nil {
> -		return cacheKey, nil, nil, nil
> +		return cacheKey, nil, nil, nil, nil
>  	}
>  	cipherSuiteOk := false
>  	for _, offeredID := range hello.cipherSuites {
> @@ -336,7 +340,7 @@
>  		}
>  	}
>  	if !cipherSuiteOk {
> -		return cacheKey, nil, nil, nil
> +		return cacheKey, nil, nil, nil, nil
>  	}
>  
>  	// Set the pre_shared_key extension. See RFC 8446, Section 4.2.11.1.
> @@ -354,9 +358,15 @@
>  	earlySecret = cipherSuite.extract(psk, nil)
>  	binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil)
>  	transcript := cipherSuite.hash.New()
> -	transcript.Write(hello.marshalWithoutBinders())
> +	helloBytes, err := hello.marshalWithoutBinders()
> +	if err != nil {
> +		return "", nil, nil, nil, err
> +	}
> +	transcript.Write(helloBytes)
>  	pskBinders := [][]byte{cipherSuite.finishedHash(binderKey, transcript)}
> -	hello.updateBinders(pskBinders)
> +	if err := hello.updateBinders(pskBinders); err != nil {
> +		return "", nil, nil, nil, err
> +	}
>  
>  	return
>  }
> @@ -401,8 +411,12 @@
>  		hs.finishedHash.discardHandshakeBuffer()
>  	}
>  
> -	hs.finishedHash.Write(hs.hello.marshal())
> -	hs.finishedHash.Write(hs.serverHello.marshal())
> +	if err := transcriptMsg(hs.hello, &hs.finishedHash); err != nil {
> +		return err
> +	}
> +	if err := transcriptMsg(hs.serverHello, &hs.finishedHash); err != nil {
> +		return err
> +	}
>  
>  	c.buffering = true
>  	c.didResume = isResume
> @@ -473,7 +487,7 @@
>  func (hs *clientHandshakeState) doFullHandshake() error {
>  	c := hs.c
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(&hs.finishedHash)
>  	if err != nil {
>  		return err
>  	}
> @@ -482,9 +496,8 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(certMsg, msg)
>  	}
> -	hs.finishedHash.Write(certMsg.marshal())
>  
> -	msg, err = c.readHandshake()
> +	msg, err = c.readHandshake(&hs.finishedHash)
>  	if err != nil {
>  		return err
>  	}
> @@ -502,11 +515,10 @@
>  			c.sendAlert(alertUnexpectedMessage)
>  			return errors.New("tls: received unexpected CertificateStatus message")
>  		}
> -		hs.finishedHash.Write(cs.marshal())
>  
>  		c.ocspResponse = cs.response
>  
> -		msg, err = c.readHandshake()
> +		msg, err = c.readHandshake(&hs.finishedHash)
>  		if err != nil {
>  			return err
>  		}
> @@ -535,14 +547,13 @@
>  
>  	skx, ok := msg.(*serverKeyExchangeMsg)
>  	if ok {
> -		hs.finishedHash.Write(skx.marshal())
>  		err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx)
>  		if err != nil {
>  			c.sendAlert(alertUnexpectedMessage)
>  			return err
>  		}
>  
> -		msg, err = c.readHandshake()
> +		msg, err = c.readHandshake(&hs.finishedHash)
>  		if err != nil {
>  			return err
>  		}
> @@ -553,7 +564,6 @@
>  	certReq, ok := msg.(*certificateRequestMsg)
>  	if ok {
>  		certRequested = true
> -		hs.finishedHash.Write(certReq.marshal())
>  
>  		cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq)
>  		if chainToSend, err = c.getClientCertificate(cri); err != nil {
> @@ -561,7 +571,7 @@
>  			return err
>  		}
>  
> -		msg, err = c.readHandshake()
> +		msg, err = c.readHandshake(&hs.finishedHash)
>  		if err != nil {
>  			return err
>  		}
> @@ -572,7 +582,6 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(shd, msg)
>  	}
> -	hs.finishedHash.Write(shd.marshal())
>  
>  	// If the server requested a certificate then we have to send a
>  	// Certificate message, even if it's empty because we don't have a
> @@ -580,8 +589,7 @@
>  	if certRequested {
>  		certMsg = new(certificateMsg)
>  		certMsg.certificates = chainToSend.Certificate
> -		hs.finishedHash.Write(certMsg.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(certMsg, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
> @@ -592,8 +600,7 @@
>  		return err
>  	}
>  	if ckx != nil {
> -		hs.finishedHash.Write(ckx.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(ckx, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
> @@ -640,8 +647,7 @@
>  			return err
>  		}
>  
> -		hs.finishedHash.Write(certVerify.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(certVerify, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
> @@ -776,7 +782,10 @@
>  		return err
>  	}
>  
> -	msg, err := c.readHandshake()
> +	// finishedMsg is included in the transcript, but not until after we
> +	// check the client version, since the state before this message was
> +	// sent is used during verification.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -792,7 +801,11 @@
>  		c.sendAlert(alertHandshakeFailure)
>  		return errors.New("tls: server's Finished message was incorrect")
>  	}
> -	hs.finishedHash.Write(serverFinished.marshal())
> +
> +	if err := transcriptMsg(serverFinished, &hs.finishedHash); err != nil {
> +		return err
> +	}
> +
>  	copy(out, verify)
>  	return nil
>  }
> @@ -803,7 +816,7 @@
>  	}
>  
>  	c := hs.c
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(&hs.finishedHash)
>  	if err != nil {
>  		return err
>  	}
> @@ -812,7 +825,6 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(sessionTicketMsg, msg)
>  	}
> -	hs.finishedHash.Write(sessionTicketMsg.marshal())
>  
>  	hs.session = &ClientSessionState{
>  		sessionTicket:      sessionTicketMsg.ticket,
> @@ -832,14 +844,13 @@
>  func (hs *clientHandshakeState) sendFinished(out []byte) error {
>  	c := hs.c
>  
> -	if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
> +	if err := c.writeChangeCipherRecord(); err != nil {
>  		return err
>  	}
>  
>  	finished := new(finishedMsg)
>  	finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
> -	hs.finishedHash.Write(finished.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(finished, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  	copy(out, finished.verifyData)
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_client_test.go golang-1.19-1.19.6/src/crypto/tls/handshake_client_test.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_client_test.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_client_test.go	2023-02-14 01:38:45.000000000 +0800
> @@ -1257,7 +1257,7 @@
>  		cipherSuite:  TLS_RSA_WITH_AES_128_GCM_SHA256,
>  		alpnProtocol: "how-about-this",
>  	}
> -	serverHelloBytes := serverHello.marshal()
> +	serverHelloBytes := mustMarshal(t, serverHello)
>  
>  	s.Write([]byte{
>  		byte(recordTypeHandshake),
> @@ -1500,7 +1500,7 @@
>  		random:      make([]byte, 32),
>  		cipherSuite: TLS_RSA_WITH_AES_256_GCM_SHA384,
>  	}
> -	serverHelloBytes := serverHello.marshal()
> +	serverHelloBytes := mustMarshal(t, serverHello)
>  
>  	s.Write([]byte{
>  		byte(recordTypeHandshake),
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_client_tls13.go golang-1.19-1.19.6/src/crypto/tls/handshake_client_tls13.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_client_tls13.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_client_tls13.go	2023-02-14 01:38:45.000000000 +0800
> @@ -62,7 +62,10 @@
>  	}
>  
>  	hs.transcript = hs.suite.hash.New()
> -	hs.transcript.Write(hs.hello.marshal())
> +
> +	if err := transcriptMsg(hs.hello, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) {
>  		if err := hs.sendDummyChangeCipherSpec(); err != nil {
> @@ -73,7 +76,9 @@
>  		}
>  	}
>  
> -	hs.transcript.Write(hs.serverHello.marshal())
> +	if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	c.buffering = true
>  	if err := hs.processServerHello(); err != nil {
> @@ -172,8 +177,7 @@
>  	}
>  	hs.sentDummyCCS = true
>  
> -	_, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
> -	return err
> +	return hs.c.writeChangeCipherRecord()
>  }
>  
>  // processHelloRetryRequest handles the HRR in hs.serverHello, modifies and
> @@ -188,7 +192,9 @@
>  	hs.transcript.Reset()
>  	hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})
>  	hs.transcript.Write(chHash)
> -	hs.transcript.Write(hs.serverHello.marshal())
> +	if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	// The only HelloRetryRequest extensions we support are key_share and
>  	// cookie, and clients must abort the handshake if the HRR would not result
> @@ -253,10 +259,18 @@
>  			transcript := hs.suite.hash.New()
>  			transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})
>  			transcript.Write(chHash)
> -			transcript.Write(hs.serverHello.marshal())
> -			transcript.Write(hs.hello.marshalWithoutBinders())
> +			if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil {
> +				return err
> +			}
> +			helloBytes, err := hs.hello.marshalWithoutBinders()
> +			if err != nil {
> +				return err
> +			}
> +			transcript.Write(helloBytes)
>  			pskBinders := [][]byte{hs.suite.finishedHash(hs.binderKey, transcript)}
> -			hs.hello.updateBinders(pskBinders)
> +			if err := hs.hello.updateBinders(pskBinders); err != nil {
> +				return err
> +			}
>  		} else {
>  			// Server selected a cipher suite incompatible with the PSK.
>  			hs.hello.pskIdentities = nil
> @@ -264,12 +278,12 @@
>  		}
>  	}
>  
> -	hs.transcript.Write(hs.hello.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil {
>  		return err
>  	}
>  
> -	msg, err := c.readHandshake()
> +	// serverHelloMsg is not included in the transcript
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -358,6 +372,7 @@
>  	if !hs.usingPSK {
>  		earlySecret = hs.suite.extract(nil, nil)
>  	}
> +
>  	handshakeSecret := hs.suite.extract(sharedKey,
>  		hs.suite.deriveSecret(earlySecret, "derived", nil))
>  
> @@ -388,7 +403,7 @@
>  func (hs *clientHandshakeStateTLS13) readServerParameters() error {
>  	c := hs.c
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(hs.transcript)
>  	if err != nil {
>  		return err
>  	}
> @@ -398,7 +413,6 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(encryptedExtensions, msg)
>  	}
> -	hs.transcript.Write(encryptedExtensions.marshal())
>  
>  	if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil {
>  		c.sendAlert(alertUnsupportedExtension)
> @@ -427,18 +441,16 @@
>  		return nil
>  	}
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(hs.transcript)
>  	if err != nil {
>  		return err
>  	}
>  
>  	certReq, ok := msg.(*certificateRequestMsgTLS13)
>  	if ok {
> -		hs.transcript.Write(certReq.marshal())
> -
>  		hs.certReq = certReq
>  
> -		msg, err = c.readHandshake()
> +		msg, err = c.readHandshake(hs.transcript)
>  		if err != nil {
>  			return err
>  		}
> @@ -453,7 +465,6 @@
>  		c.sendAlert(alertDecodeError)
>  		return errors.New("tls: received empty certificates message")
>  	}
> -	hs.transcript.Write(certMsg.marshal())
>  
>  	c.scts = certMsg.certificate.SignedCertificateTimestamps
>  	c.ocspResponse = certMsg.certificate.OCSPStaple
> @@ -462,7 +473,10 @@
>  		return err
>  	}
>  
> -	msg, err = c.readHandshake()
> +	// certificateVerifyMsg is included in the transcript, but not until
> +	// after we verify the handshake signature, since the state before
> +	// this message was sent is used.
> +	msg, err = c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -493,7 +507,9 @@
>  		return errors.New("tls: invalid signature by the server certificate: " + err.Error())
>  	}
>  
> -	hs.transcript.Write(certVerify.marshal())
> +	if err := transcriptMsg(certVerify, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	return nil
>  }
> @@ -501,7 +517,10 @@
>  func (hs *clientHandshakeStateTLS13) readServerFinished() error {
>  	c := hs.c
>  
> -	msg, err := c.readHandshake()
> +	// finishedMsg is included in the transcript, but not until after we
> +	// check the client version, since the state before this message was
> +	// sent is used during verification.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -518,7 +537,9 @@
>  		return errors.New("tls: invalid server finished hash")
>  	}
>  
> -	hs.transcript.Write(finished.marshal())
> +	if err := transcriptMsg(finished, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	// Derive secrets that take context through the server Finished.
>  
> @@ -567,8 +588,7 @@
>  	certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0
>  	certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0
>  
> -	hs.transcript.Write(certMsg.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -605,8 +625,7 @@
>  	}
>  	certVerifyMsg.signature = sig
>  
> -	hs.transcript.Write(certVerifyMsg.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(certVerifyMsg, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -620,8 +639,7 @@
>  		verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript),
>  	}
>  
> -	hs.transcript.Write(finished.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(finished, hs.transcript); err != nil {
>  		return err
>  	}
>  
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_messages.go golang-1.19-1.19.6/src/crypto/tls/handshake_messages.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_messages.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_messages.go	2023-02-14 01:38:45.000000000 +0800
> @@ -5,6 +5,7 @@
>  package tls
>  
>  import (
> +	"errors"
>  	"fmt"
>  	"strings"
>  
> @@ -94,9 +95,181 @@
>  	pskBinders                       [][]byte
>  }
>  
> -func (m *clientHelloMsg) marshal() []byte {
> +func (m *clientHelloMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
> +	}
> +
> +	var exts cryptobyte.Builder
> +	if len(m.serverName) > 0 {
> +		// RFC 6066, Section 3
> +		exts.AddUint16(extensionServerName)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddUint8(0) // name_type = host_name
> +				exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +					exts.AddBytes([]byte(m.serverName))
> +				})
> +			})
> +		})
> +	}
> +	if m.ocspStapling {
> +		// RFC 4366, Section 3.6
> +		exts.AddUint16(extensionStatusRequest)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8(1)  // status_type = ocsp
> +			exts.AddUint16(0) // empty responder_id_list
> +			exts.AddUint16(0) // empty request_extensions
> +		})
> +	}
> +	if len(m.supportedCurves) > 0 {
> +		// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
> +		exts.AddUint16(extensionSupportedCurves)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, curve := range m.supportedCurves {
> +					exts.AddUint16(uint16(curve))
> +				}
> +			})
> +		})
> +	}
> +	if len(m.supportedPoints) > 0 {
> +		// RFC 4492, Section 5.1.2
> +		exts.AddUint16(extensionSupportedPoints)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.supportedPoints)
> +			})
> +		})
> +	}
> +	if m.ticketSupported {
> +		// RFC 5077, Section 3.2
> +		exts.AddUint16(extensionSessionTicket)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddBytes(m.sessionTicket)
> +		})
> +	}
> +	if len(m.supportedSignatureAlgorithms) > 0 {
> +		// RFC 5246, Section 7.4.1.4.1
> +		exts.AddUint16(extensionSignatureAlgorithms)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, sigAlgo := range m.supportedSignatureAlgorithms {
> +					exts.AddUint16(uint16(sigAlgo))
> +				}
> +			})
> +		})
> +	}
> +	if len(m.supportedSignatureAlgorithmsCert) > 0 {
> +		// RFC 8446, Section 4.2.3
> +		exts.AddUint16(extensionSignatureAlgorithmsCert)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, sigAlgo := range m.supportedSignatureAlgorithmsCert {
> +					exts.AddUint16(uint16(sigAlgo))
> +				}
> +			})
> +		})
> +	}
> +	if m.secureRenegotiationSupported {
> +		// RFC 5746, Section 3.2
> +		exts.AddUint16(extensionRenegotiationInfo)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.secureRenegotiation)
> +			})
> +		})
> +	}
> +	if len(m.alpnProtocols) > 0 {
> +		// RFC 7301, Section 3.1
> +		exts.AddUint16(extensionALPN)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, proto := range m.alpnProtocols {
> +					exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +						exts.AddBytes([]byte(proto))
> +					})
> +				}
> +			})
> +		})
> +	}
> +	if m.scts {
> +		// RFC 6962, Section 3.3.1
> +		exts.AddUint16(extensionSCT)
> +		exts.AddUint16(0) // empty extension_data
> +	}
> +	if len(m.supportedVersions) > 0 {
> +		// RFC 8446, Section 4.2.1
> +		exts.AddUint16(extensionSupportedVersions)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, vers := range m.supportedVersions {
> +					exts.AddUint16(vers)
> +				}
> +			})
> +		})
> +	}
> +	if len(m.cookie) > 0 {
> +		// RFC 8446, Section 4.2.2
> +		exts.AddUint16(extensionCookie)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.cookie)
> +			})
> +		})
> +	}
> +	if len(m.keyShares) > 0 {
> +		// RFC 8446, Section 4.2.8
> +		exts.AddUint16(extensionKeyShare)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, ks := range m.keyShares {
> +					exts.AddUint16(uint16(ks.group))
> +					exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +						exts.AddBytes(ks.data)
> +					})
> +				}
> +			})
> +		})
> +	}
> +	if m.earlyData {
> +		// RFC 8446, Section 4.2.10
> +		exts.AddUint16(extensionEarlyData)
> +		exts.AddUint16(0) // empty extension_data
> +	}
> +	if len(m.pskModes) > 0 {
> +		// RFC 8446, Section 4.2.9
> +		exts.AddUint16(extensionPSKModes)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.pskModes)
> +			})
> +		})
> +	}
> +	if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension
> +		// RFC 8446, Section 4.2.11
> +		exts.AddUint16(extensionPreSharedKey)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, psk := range m.pskIdentities {
> +					exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +						exts.AddBytes(psk.label)
> +					})
> +					exts.AddUint32(psk.obfuscatedTicketAge)
> +				}
> +			})
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, binder := range m.pskBinders {
> +					exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +						exts.AddBytes(binder)
> +					})
> +				}
> +			})
> +		})
> +	}
> +	extBytes, err := exts.Bytes()
> +	if err != nil {
> +		return nil, err
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -116,219 +289,53 @@
>  			b.AddBytes(m.compressionMethods)
>  		})
>  
> -		// If extensions aren't present, omit them.
> -		var extensionsPresent bool
> -		bWithoutExtensions := *b
> -
> -		b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -			if len(m.serverName) > 0 {
> -				// RFC 6066, Section 3
> -				b.AddUint16(extensionServerName)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddUint8(0) // name_type = host_name
> -						b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -							b.AddBytes([]byte(m.serverName))
> -						})
> -					})
> -				})
> -			}
> -			if m.ocspStapling {
> -				// RFC 4366, Section 3.6
> -				b.AddUint16(extensionStatusRequest)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8(1)  // status_type = ocsp
> -					b.AddUint16(0) // empty responder_id_list
> -					b.AddUint16(0) // empty request_extensions
> -				})
> -			}
> -			if len(m.supportedCurves) > 0 {
> -				// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
> -				b.AddUint16(extensionSupportedCurves)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, curve := range m.supportedCurves {
> -							b.AddUint16(uint16(curve))
> -						}
> -					})
> -				})
> -			}
> -			if len(m.supportedPoints) > 0 {
> -				// RFC 4492, Section 5.1.2
> -				b.AddUint16(extensionSupportedPoints)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.supportedPoints)
> -					})
> -				})
> -			}
> -			if m.ticketSupported {
> -				// RFC 5077, Section 3.2
> -				b.AddUint16(extensionSessionTicket)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddBytes(m.sessionTicket)
> -				})
> -			}
> -			if len(m.supportedSignatureAlgorithms) > 0 {
> -				// RFC 5246, Section 7.4.1.4.1
> -				b.AddUint16(extensionSignatureAlgorithms)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, sigAlgo := range m.supportedSignatureAlgorithms {
> -							b.AddUint16(uint16(sigAlgo))
> -						}
> -					})
> -				})
> -			}
> -			if len(m.supportedSignatureAlgorithmsCert) > 0 {
> -				// RFC 8446, Section 4.2.3
> -				b.AddUint16(extensionSignatureAlgorithmsCert)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, sigAlgo := range m.supportedSignatureAlgorithmsCert {
> -							b.AddUint16(uint16(sigAlgo))
> -						}
> -					})
> -				})
> -			}
> -			if m.secureRenegotiationSupported {
> -				// RFC 5746, Section 3.2
> -				b.AddUint16(extensionRenegotiationInfo)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.secureRenegotiation)
> -					})
> -				})
> -			}
> -			if len(m.alpnProtocols) > 0 {
> -				// RFC 7301, Section 3.1
> -				b.AddUint16(extensionALPN)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, proto := range m.alpnProtocols {
> -							b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -								b.AddBytes([]byte(proto))
> -							})
> -						}
> -					})
> -				})
> -			}
> -			if m.scts {
> -				// RFC 6962, Section 3.3.1
> -				b.AddUint16(extensionSCT)
> -				b.AddUint16(0) // empty extension_data
> -			}
> -			if len(m.supportedVersions) > 0 {
> -				// RFC 8446, Section 4.2.1
> -				b.AddUint16(extensionSupportedVersions)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, vers := range m.supportedVersions {
> -							b.AddUint16(vers)
> -						}
> -					})
> -				})
> -			}
> -			if len(m.cookie) > 0 {
> -				// RFC 8446, Section 4.2.2
> -				b.AddUint16(extensionCookie)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.cookie)
> -					})
> -				})
> -			}
> -			if len(m.keyShares) > 0 {
> -				// RFC 8446, Section 4.2.8
> -				b.AddUint16(extensionKeyShare)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, ks := range m.keyShares {
> -							b.AddUint16(uint16(ks.group))
> -							b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -								b.AddBytes(ks.data)
> -							})
> -						}
> -					})
> -				})
> -			}
> -			if m.earlyData {
> -				// RFC 8446, Section 4.2.10
> -				b.AddUint16(extensionEarlyData)
> -				b.AddUint16(0) // empty extension_data
> -			}
> -			if len(m.pskModes) > 0 {
> -				// RFC 8446, Section 4.2.9
> -				b.AddUint16(extensionPSKModes)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.pskModes)
> -					})
> -				})
> -			}
> -			if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension
> -				// RFC 8446, Section 4.2.11
> -				b.AddUint16(extensionPreSharedKey)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, psk := range m.pskIdentities {
> -							b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -								b.AddBytes(psk.label)
> -							})
> -							b.AddUint32(psk.obfuscatedTicketAge)
> -						}
> -					})
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, binder := range m.pskBinders {
> -							b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -								b.AddBytes(binder)
> -							})
> -						}
> -					})
> -				})
> -			}
> -
> -			extensionsPresent = len(b.BytesOrPanic()) > 2
> -		})
> -
> -		if !extensionsPresent {
> -			*b = bWithoutExtensions
> +		if len(extBytes) > 0 {
> +			b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> +				b.AddBytes(extBytes)
> +			})
>  		}
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  // marshalWithoutBinders returns the ClientHello through the
>  // PreSharedKeyExtension.identities field, according to RFC 8446, Section
>  // 4.2.11.2. Note that m.pskBinders must be set to slices of the correct length.
> -func (m *clientHelloMsg) marshalWithoutBinders() []byte {
> +func (m *clientHelloMsg) marshalWithoutBinders() ([]byte, error) {
>  	bindersLen := 2 // uint16 length prefix
>  	for _, binder := range m.pskBinders {
>  		bindersLen += 1 // uint8 length prefix
>  		bindersLen += len(binder)
>  	}
>  
> -	fullMessage := m.marshal()
> -	return fullMessage[:len(fullMessage)-bindersLen]
> +	fullMessage, err := m.marshal()
> +	if err != nil {
> +		return nil, err
> +	}
> +	return fullMessage[:len(fullMessage)-bindersLen], nil
>  }
>  
>  // updateBinders updates the m.pskBinders field, if necessary updating the
>  // cached marshaled representation. The supplied binders must have the same
>  // length as the current m.pskBinders.
> -func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) {
> +func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) error {
>  	if len(pskBinders) != len(m.pskBinders) {
> -		panic("tls: internal error: pskBinders length mismatch")
> +		return errors.New("tls: internal error: pskBinders length mismatch")
>  	}
>  	for i := range m.pskBinders {
>  		if len(pskBinders[i]) != len(m.pskBinders[i]) {
> -			panic("tls: internal error: pskBinders length mismatch")
> +			return errors.New("tls: internal error: pskBinders length mismatch")
>  		}
>  	}
>  	m.pskBinders = pskBinders
>  	if m.raw != nil {
> -		lenWithoutBinders := len(m.marshalWithoutBinders())
> +		helloBytes, err := m.marshalWithoutBinders()
> +		if err != nil {
> +			return err
> +		}
> +		lenWithoutBinders := len(helloBytes)
>  		b := cryptobyte.NewFixedBuilder(m.raw[:lenWithoutBinders])
>  		b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
>  			for _, binder := range m.pskBinders {
> @@ -338,9 +345,11 @@
>  			}
>  		})
>  		if out, err := b.Bytes(); err != nil || len(out) != len(m.raw) {
> -			panic("tls: internal error: failed to update binders")
> +			return errors.New("tls: internal error: failed to update binders")
>  		}
>  	}
> +
> +	return nil
>  }
>  
>  func (m *clientHelloMsg) unmarshal(data []byte) bool {
> @@ -618,9 +627,98 @@
>  	selectedGroup CurveID
>  }
>  
> -func (m *serverHelloMsg) marshal() []byte {
> +func (m *serverHelloMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
> +	}
> +
> +	var exts cryptobyte.Builder
> +	if m.ocspStapling {
> +		exts.AddUint16(extensionStatusRequest)
> +		exts.AddUint16(0) // empty extension_data
> +	}
> +	if m.ticketSupported {
> +		exts.AddUint16(extensionSessionTicket)
> +		exts.AddUint16(0) // empty extension_data
> +	}
> +	if m.secureRenegotiationSupported {
> +		exts.AddUint16(extensionRenegotiationInfo)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.secureRenegotiation)
> +			})
> +		})
> +	}
> +	if len(m.alpnProtocol) > 0 {
> +		exts.AddUint16(extensionALPN)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +					exts.AddBytes([]byte(m.alpnProtocol))
> +				})
> +			})
> +		})
> +	}
> +	if len(m.scts) > 0 {
> +		exts.AddUint16(extensionSCT)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				for _, sct := range m.scts {
> +					exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +						exts.AddBytes(sct)
> +					})
> +				}
> +			})
> +		})
> +	}
> +	if m.supportedVersion != 0 {
> +		exts.AddUint16(extensionSupportedVersions)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16(m.supportedVersion)
> +		})
> +	}
> +	if m.serverShare.group != 0 {
> +		exts.AddUint16(extensionKeyShare)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16(uint16(m.serverShare.group))
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.serverShare.data)
> +			})
> +		})
> +	}
> +	if m.selectedIdentityPresent {
> +		exts.AddUint16(extensionPreSharedKey)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16(m.selectedIdentity)
> +		})
> +	}
> +
> +	if len(m.cookie) > 0 {
> +		exts.AddUint16(extensionCookie)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.cookie)
> +			})
> +		})
> +	}
> +	if m.selectedGroup != 0 {
> +		exts.AddUint16(extensionKeyShare)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint16(uint16(m.selectedGroup))
> +		})
> +	}
> +	if len(m.supportedPoints) > 0 {
> +		exts.AddUint16(extensionSupportedPoints)
> +		exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
> +			exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
> +				exts.AddBytes(m.supportedPoints)
> +			})
> +		})
> +	}
> +
> +	extBytes, err := exts.Bytes()
> +	if err != nil {
> +		return nil, err
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -634,104 +732,15 @@
>  		b.AddUint16(m.cipherSuite)
>  		b.AddUint8(m.compressionMethod)
>  
> -		// If extensions aren't present, omit them.
> -		var extensionsPresent bool
> -		bWithoutExtensions := *b
> -
> -		b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -			if m.ocspStapling {
> -				b.AddUint16(extensionStatusRequest)
> -				b.AddUint16(0) // empty extension_data
> -			}
> -			if m.ticketSupported {
> -				b.AddUint16(extensionSessionTicket)
> -				b.AddUint16(0) // empty extension_data
> -			}
> -			if m.secureRenegotiationSupported {
> -				b.AddUint16(extensionRenegotiationInfo)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.secureRenegotiation)
> -					})
> -				})
> -			}
> -			if len(m.alpnProtocol) > 0 {
> -				b.AddUint16(extensionALPN)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -							b.AddBytes([]byte(m.alpnProtocol))
> -						})
> -					})
> -				})
> -			}
> -			if len(m.scts) > 0 {
> -				b.AddUint16(extensionSCT)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						for _, sct := range m.scts {
> -							b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -								b.AddBytes(sct)
> -							})
> -						}
> -					})
> -				})
> -			}
> -			if m.supportedVersion != 0 {
> -				b.AddUint16(extensionSupportedVersions)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16(m.supportedVersion)
> -				})
> -			}
> -			if m.serverShare.group != 0 {
> -				b.AddUint16(extensionKeyShare)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16(uint16(m.serverShare.group))
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.serverShare.data)
> -					})
> -				})
> -			}
> -			if m.selectedIdentityPresent {
> -				b.AddUint16(extensionPreSharedKey)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16(m.selectedIdentity)
> -				})
> -			}
> -
> -			if len(m.cookie) > 0 {
> -				b.AddUint16(extensionCookie)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.cookie)
> -					})
> -				})
> -			}
> -			if m.selectedGroup != 0 {
> -				b.AddUint16(extensionKeyShare)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint16(uint16(m.selectedGroup))
> -				})
> -			}
> -			if len(m.supportedPoints) > 0 {
> -				b.AddUint16(extensionSupportedPoints)
> -				b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> -					b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
> -						b.AddBytes(m.supportedPoints)
> -					})
> -				})
> -			}
> -
> -			extensionsPresent = len(b.BytesOrPanic()) > 2
> -		})
> -
> -		if !extensionsPresent {
> -			*b = bWithoutExtensions
> +		if len(extBytes) > 0 {
> +			b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
> +				b.AddBytes(extBytes)
> +			})
>  		}
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *serverHelloMsg) unmarshal(data []byte) bool {
> @@ -855,9 +864,9 @@
>  	alpnProtocol string
>  }
>  
> -func (m *encryptedExtensionsMsg) marshal() []byte {
> +func (m *encryptedExtensionsMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -877,8 +886,9 @@
>  		})
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
> @@ -926,10 +936,10 @@
>  
>  type endOfEarlyDataMsg struct{}
>  
> -func (m *endOfEarlyDataMsg) marshal() []byte {
> +func (m *endOfEarlyDataMsg) marshal() ([]byte, error) {
>  	x := make([]byte, 4)
>  	x[0] = typeEndOfEarlyData
> -	return x
> +	return x, nil
>  }
>  
>  func (m *endOfEarlyDataMsg) unmarshal(data []byte) bool {
> @@ -941,9 +951,9 @@
>  	updateRequested bool
>  }
>  
> -func (m *keyUpdateMsg) marshal() []byte {
> +func (m *keyUpdateMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -956,8 +966,9 @@
>  		}
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *keyUpdateMsg) unmarshal(data []byte) bool {
> @@ -989,9 +1000,9 @@
>  	maxEarlyData uint32
>  }
>  
> -func (m *newSessionTicketMsgTLS13) marshal() []byte {
> +func (m *newSessionTicketMsgTLS13) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1016,8 +1027,9 @@
>  		})
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *newSessionTicketMsgTLS13) unmarshal(data []byte) bool {
> @@ -1070,9 +1082,9 @@
>  	certificateAuthorities           [][]byte
>  }
>  
> -func (m *certificateRequestMsgTLS13) marshal() []byte {
> +func (m *certificateRequestMsgTLS13) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1131,8 +1143,9 @@
>  		})
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool {
> @@ -1216,9 +1229,9 @@
>  	certificates [][]byte
>  }
>  
> -func (m *certificateMsg) marshal() (x []byte) {
> +func (m *certificateMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var i int
> @@ -1227,7 +1240,7 @@
>  	}
>  
>  	length := 3 + 3*len(m.certificates) + i
> -	x = make([]byte, 4+length)
> +	x := make([]byte, 4+length)
>  	x[0] = typeCertificate
>  	x[1] = uint8(length >> 16)
>  	x[2] = uint8(length >> 8)
> @@ -1248,7 +1261,7 @@
>  	}
>  
>  	m.raw = x
> -	return
> +	return m.raw, nil
>  }
>  
>  func (m *certificateMsg) unmarshal(data []byte) bool {
> @@ -1295,9 +1308,9 @@
>  	scts         bool
>  }
>  
> -func (m *certificateMsgTLS13) marshal() []byte {
> +func (m *certificateMsgTLS13) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1315,8 +1328,9 @@
>  		marshalCertificate(b, certificate)
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) {
> @@ -1439,9 +1453,9 @@
>  	key []byte
>  }
>  
> -func (m *serverKeyExchangeMsg) marshal() []byte {
> +func (m *serverKeyExchangeMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  	length := len(m.key)
>  	x := make([]byte, length+4)
> @@ -1452,7 +1466,7 @@
>  	copy(x[4:], m.key)
>  
>  	m.raw = x
> -	return x
> +	return x, nil
>  }
>  
>  func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
> @@ -1469,9 +1483,9 @@
>  	response []byte
>  }
>  
> -func (m *certificateStatusMsg) marshal() []byte {
> +func (m *certificateStatusMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1483,8 +1497,9 @@
>  		})
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *certificateStatusMsg) unmarshal(data []byte) bool {
> @@ -1503,10 +1518,10 @@
>  
>  type serverHelloDoneMsg struct{}
>  
> -func (m *serverHelloDoneMsg) marshal() []byte {
> +func (m *serverHelloDoneMsg) marshal() ([]byte, error) {
>  	x := make([]byte, 4)
>  	x[0] = typeServerHelloDone
> -	return x
> +	return x, nil
>  }
>  
>  func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
> @@ -1518,9 +1533,9 @@
>  	ciphertext []byte
>  }
>  
> -func (m *clientKeyExchangeMsg) marshal() []byte {
> +func (m *clientKeyExchangeMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  	length := len(m.ciphertext)
>  	x := make([]byte, length+4)
> @@ -1531,7 +1546,7 @@
>  	copy(x[4:], m.ciphertext)
>  
>  	m.raw = x
> -	return x
> +	return x, nil
>  }
>  
>  func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
> @@ -1552,9 +1567,9 @@
>  	verifyData []byte
>  }
>  
> -func (m *finishedMsg) marshal() []byte {
> +func (m *finishedMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1563,8 +1578,9 @@
>  		b.AddBytes(m.verifyData)
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *finishedMsg) unmarshal(data []byte) bool {
> @@ -1586,9 +1602,9 @@
>  	certificateAuthorities       [][]byte
>  }
>  
> -func (m *certificateRequestMsg) marshal() (x []byte) {
> +func (m *certificateRequestMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	// See RFC 4346, Section 7.4.4.
> @@ -1603,7 +1619,7 @@
>  		length += 2 + 2*len(m.supportedSignatureAlgorithms)
>  	}
>  
> -	x = make([]byte, 4+length)
> +	x := make([]byte, 4+length)
>  	x[0] = typeCertificateRequest
>  	x[1] = uint8(length >> 16)
>  	x[2] = uint8(length >> 8)
> @@ -1638,7 +1654,7 @@
>  	}
>  
>  	m.raw = x
> -	return
> +	return m.raw, nil
>  }
>  
>  func (m *certificateRequestMsg) unmarshal(data []byte) bool {
> @@ -1724,9 +1740,9 @@
>  	signature             []byte
>  }
>  
> -func (m *certificateVerifyMsg) marshal() (x []byte) {
> +func (m *certificateVerifyMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	var b cryptobyte.Builder
> @@ -1740,8 +1756,9 @@
>  		})
>  	})
>  
> -	m.raw = b.BytesOrPanic()
> -	return m.raw
> +	var err error
> +	m.raw, err = b.Bytes()
> +	return m.raw, err
>  }
>  
>  func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
> @@ -1764,15 +1781,15 @@
>  	ticket []byte
>  }
>  
> -func (m *newSessionTicketMsg) marshal() (x []byte) {
> +func (m *newSessionTicketMsg) marshal() ([]byte, error) {
>  	if m.raw != nil {
> -		return m.raw
> +		return m.raw, nil
>  	}
>  
>  	// See RFC 5077, Section 3.3.
>  	ticketLen := len(m.ticket)
>  	length := 2 + 4 + ticketLen
> -	x = make([]byte, 4+length)
> +	x := make([]byte, 4+length)
>  	x[0] = typeNewSessionTicket
>  	x[1] = uint8(length >> 16)
>  	x[2] = uint8(length >> 8)
> @@ -1783,7 +1800,7 @@
>  
>  	m.raw = x
>  
> -	return
> +	return m.raw, nil
>  }
>  
>  func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
> @@ -1811,10 +1828,25 @@
>  type helloRequestMsg struct {
>  }
>  
> -func (*helloRequestMsg) marshal() []byte {
> -	return []byte{typeHelloRequest, 0, 0, 0}
> +func (*helloRequestMsg) marshal() ([]byte, error) {
> +	return []byte{typeHelloRequest, 0, 0, 0}, nil
>  }
>  
>  func (*helloRequestMsg) unmarshal(data []byte) bool {
>  	return len(data) == 4
>  }
> +
> +type transcriptHash interface {
> +	Write([]byte) (int, error)
> +}
> +
> +// transcriptMsg is a helper used to marshal and hash messages which typically
> +// are not written to the wire, and as such aren't hashed during Conn.writeRecord.
> +func transcriptMsg(msg handshakeMessage, h transcriptHash) error {
> +	data, err := msg.marshal()
> +	if err != nil {
> +		return err
> +	}
> +	h.Write(data)
> +	return nil
> +}
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_messages_test.go golang-1.19-1.19.6/src/crypto/tls/handshake_messages_test.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_messages_test.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_messages_test.go	2023-02-14 01:38:45.000000000 +0800
> @@ -38,6 +38,15 @@
>  	&certificateMsgTLS13{},
>  }
>  
> +func mustMarshal(t *testing.T, msg handshakeMessage) []byte {
> +	t.Helper()
> +	b, err := msg.marshal()
> +	if err != nil {
> +		t.Fatal(err)
> +	}
> +	return b
> +}
> +
>  func TestMarshalUnmarshal(t *testing.T) {
>  	rand := rand.New(rand.NewSource(time.Now().UnixNano()))
>  
> @@ -56,7 +65,7 @@
>  			}
>  
>  			m1 := v.Interface().(handshakeMessage)
> -			marshaled := m1.marshal()
> +			marshaled := mustMarshal(t, m1)
>  			m2 := iface.(handshakeMessage)
>  			if !m2.unmarshal(marshaled) {
>  				t.Errorf("#%d failed to unmarshal %#v %x", i, m1, marshaled)
> @@ -409,12 +418,12 @@
>  
>  	var random [32]byte
>  	sct := []byte{0x42, 0x42, 0x42, 0x42}
> -	serverHello := serverHelloMsg{
> +	serverHello := &serverHelloMsg{
>  		vers:   VersionTLS12,
>  		random: random[:],
>  		scts:   [][]byte{sct},
>  	}
> -	serverHelloBytes := serverHello.marshal()
> +	serverHelloBytes := mustMarshal(t, serverHello)
>  
>  	var serverHelloCopy serverHelloMsg
>  	if !serverHelloCopy.unmarshal(serverHelloBytes) {
> @@ -452,12 +461,12 @@
>  	// not be zero length.
>  
>  	var random [32]byte
> -	serverHello := serverHelloMsg{
> +	serverHello := &serverHelloMsg{
>  		vers:   VersionTLS12,
>  		random: random[:],
>  		scts:   [][]byte{nil},
>  	}
> -	serverHelloBytes := serverHello.marshal()
> +	serverHelloBytes := mustMarshal(t, serverHello)
>  
>  	var serverHelloCopy serverHelloMsg
>  	if serverHelloCopy.unmarshal(serverHelloBytes) {
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_server.go golang-1.19-1.19.6/src/crypto/tls/handshake_server.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_server.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_server.go	2023-02-14 01:38:45.000000000 +0800
> @@ -129,7 +129,9 @@
>  
>  // readClientHello reads a ClientHello message and selects the protocol version.
>  func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
> -	msg, err := c.readHandshake()
> +	// clientHelloMsg is included in the transcript, but we haven't initialized
> +	// it yet. The respective handshake functions will record it themselves.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return nil, err
>  	}
> @@ -463,9 +465,10 @@
>  	hs.hello.ticketSupported = hs.sessionState.usedOldKey
>  	hs.finishedHash = newFinishedHash(c.vers, hs.suite)
>  	hs.finishedHash.discardHandshakeBuffer()
> -	hs.finishedHash.Write(hs.clientHello.marshal())
> -	hs.finishedHash.Write(hs.hello.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
> +	if err := transcriptMsg(hs.clientHello, &hs.finishedHash); err != nil {
> +		return err
> +	}
> +	if _, err := hs.c.writeHandshakeRecord(hs.hello, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
> @@ -503,24 +506,23 @@
>  		// certificates won't be used.
>  		hs.finishedHash.discardHandshakeBuffer()
>  	}
> -	hs.finishedHash.Write(hs.clientHello.marshal())
> -	hs.finishedHash.Write(hs.hello.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
> +	if err := transcriptMsg(hs.clientHello, &hs.finishedHash); err != nil {
> +		return err
> +	}
> +	if _, err := hs.c.writeHandshakeRecord(hs.hello, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
>  	certMsg := new(certificateMsg)
>  	certMsg.certificates = hs.cert.Certificate
> -	hs.finishedHash.Write(certMsg.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(certMsg, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
>  	if hs.hello.ocspStapling {
>  		certStatus := new(certificateStatusMsg)
>  		certStatus.response = hs.cert.OCSPStaple
> -		hs.finishedHash.Write(certStatus.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(certStatus, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
> @@ -532,8 +534,7 @@
>  		return err
>  	}
>  	if skx != nil {
> -		hs.finishedHash.Write(skx.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(skx, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
> @@ -559,15 +560,13 @@
>  		if c.config.ClientCAs != nil {
>  			certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
>  		}
> -		hs.finishedHash.Write(certReq.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(certReq, &hs.finishedHash); err != nil {
>  			return err
>  		}
>  	}
>  
>  	helloDone := new(serverHelloDoneMsg)
> -	hs.finishedHash.Write(helloDone.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(helloDone, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
> @@ -577,7 +576,7 @@
>  
>  	var pub crypto.PublicKey // public key for client auth, if any
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(&hs.finishedHash)
>  	if err != nil {
>  		return err
>  	}
> @@ -590,7 +589,6 @@
>  			c.sendAlert(alertUnexpectedMessage)
>  			return unexpectedMessageError(certMsg, msg)
>  		}
> -		hs.finishedHash.Write(certMsg.marshal())
>  
>  		if err := c.processCertsFromClient(Certificate{
>  			Certificate: certMsg.certificates,
> @@ -601,7 +599,7 @@
>  			pub = c.peerCertificates[0].PublicKey
>  		}
>  
> -		msg, err = c.readHandshake()
> +		msg, err = c.readHandshake(&hs.finishedHash)
>  		if err != nil {
>  			return err
>  		}
> @@ -619,7 +617,6 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(ckx, msg)
>  	}
> -	hs.finishedHash.Write(ckx.marshal())
>  
>  	preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers)
>  	if err != nil {
> @@ -639,7 +636,10 @@
>  	// to the client's certificate. This allows us to verify that the client is in
>  	// possession of the private key of the certificate.
>  	if len(c.peerCertificates) > 0 {
> -		msg, err = c.readHandshake()
> +		// certificateVerifyMsg is included in the transcript, but not until
> +		// after we verify the handshake signature, since the state before
> +		// this message was sent is used.
> +		msg, err = c.readHandshake(nil)
>  		if err != nil {
>  			return err
>  		}
> @@ -674,7 +674,9 @@
>  			return errors.New("tls: invalid signature by the client certificate: " + err.Error())
>  		}
>  
> -		hs.finishedHash.Write(certVerify.marshal())
> +		if err := transcriptMsg(certVerify, &hs.finishedHash); err != nil {
> +			return err
> +		}
>  	}
>  
>  	hs.finishedHash.discardHandshakeBuffer()
> @@ -714,7 +716,10 @@
>  		return err
>  	}
>  
> -	msg, err := c.readHandshake()
> +	// finishedMsg is included in the transcript, but not until after we
> +	// check the client version, since the state before this message was
> +	// sent is used during verification.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -731,7 +736,10 @@
>  		return errors.New("tls: client's Finished message is incorrect")
>  	}
>  
> -	hs.finishedHash.Write(clientFinished.marshal())
> +	if err := transcriptMsg(clientFinished, &hs.finishedHash); err != nil {
> +		return err
> +	}
> +
>  	copy(out, verify)
>  	return nil
>  }
> @@ -765,14 +773,16 @@
>  		masterSecret: hs.masterSecret,
>  		certificates: certsFromClient,
>  	}
> -	var err error
> -	m.ticket, err = c.encryptTicket(state.marshal())
> +	stateBytes, err := state.marshal()
> +	if err != nil {
> +		return err
> +	}
> +	m.ticket, err = c.encryptTicket(stateBytes)
>  	if err != nil {
>  		return err
>  	}
>  
> -	hs.finishedHash.Write(m.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(m, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
> @@ -782,14 +792,13 @@
>  func (hs *serverHandshakeState) sendFinished(out []byte) error {
>  	c := hs.c
>  
> -	if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
> +	if err := c.writeChangeCipherRecord(); err != nil {
>  		return err
>  	}
>  
>  	finished := new(finishedMsg)
>  	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
> -	hs.finishedHash.Write(finished.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(finished, &hs.finishedHash); err != nil {
>  		return err
>  	}
>  
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_server_test.go golang-1.19-1.19.6/src/crypto/tls/handshake_server_test.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_server_test.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_server_test.go	2023-02-14 01:38:45.000000000 +0800
> @@ -30,6 +30,13 @@
>  	testClientHelloFailure(t, serverConfig, m, "")
>  }
>  
> +// testFatal is a hack to prevent the compiler from complaining that there is a
> +// call to t.Fatal from a non-test goroutine
> +func testFatal(t *testing.T, err error) {
> +	t.Helper()
> +	t.Fatal(err)
> +}
> +
>  func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessage, expectedSubStr string) {
>  	c, s := localPipe(t)
>  	go func() {
> @@ -37,7 +44,9 @@
>  		if ch, ok := m.(*clientHelloMsg); ok {
>  			cli.vers = ch.vers
>  		}
> -		cli.writeRecord(recordTypeHandshake, m.marshal())
> +		if _, err := cli.writeHandshakeRecord(m, nil); err != nil {
> +			testFatal(t, err)
> +		}
>  		c.Close()
>  	}()
>  	ctx := context.Background()
> @@ -194,7 +203,9 @@
>  	go func() {
>  		cli := Client(c, testConfig)
>  		cli.vers = clientHello.vers
> -		cli.writeRecord(recordTypeHandshake, clientHello.marshal())
> +		if _, err := cli.writeHandshakeRecord(clientHello, nil); err != nil {
> +			testFatal(t, err)
> +		}
>  
>  		buf := make([]byte, 1024)
>  		n, err := c.Read(buf)
> @@ -253,8 +264,10 @@
>  	go func() {
>  		cli := Client(c, testConfig)
>  		cli.vers = clientHello.vers
> -		cli.writeRecord(recordTypeHandshake, clientHello.marshal())
> -		reply, err := cli.readHandshake()
> +		if _, err := cli.writeHandshakeRecord(clientHello, nil); err != nil {
> +			testFatal(t, err)
> +		}
> +		reply, err := cli.readHandshake(nil)
>  		c.Close()
>  		if err != nil {
>  			replyChan <- err
> @@ -311,8 +324,10 @@
>  			go func() {
>  				cli := Client(c, testConfig)
>  				cli.vers = clientHello.vers
> -				cli.writeRecord(recordTypeHandshake, clientHello.marshal())
> -				reply, err := cli.readHandshake()
> +				if _, err := cli.writeHandshakeRecord(clientHello, nil); err != nil {
> +					testFatal(t, err)
> +				}
> +				reply, err := cli.readHandshake(nil)
>  				c.Close()
>  				if err != nil {
>  					replyChan <- err
> @@ -1426,7 +1441,9 @@
>  	go func() {
>  		cli := Client(c, testConfig)
>  		cli.vers = clientHello.vers
> -		cli.writeRecord(recordTypeHandshake, clientHello.marshal())
> +		if _, err := cli.writeHandshakeRecord(clientHello, nil); err != nil {
> +			testFatal(t, err)
> +		}
>  		c.Close()
>  	}()
>  	conn := Server(s, serverConfig)
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/handshake_server_tls13.go golang-1.19-1.19.6/src/crypto/tls/handshake_server_tls13.go
> --- golang-1.19-1.19.5/src/crypto/tls/handshake_server_tls13.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/handshake_server_tls13.go	2023-02-14 01:38:45.000000000 +0800
> @@ -302,7 +302,12 @@
>  			c.sendAlert(alertInternalError)
>  			return errors.New("tls: internal error: failed to clone hash")
>  		}
> -		transcript.Write(hs.clientHello.marshalWithoutBinders())
> +		clientHelloBytes, err := hs.clientHello.marshalWithoutBinders()
> +		if err != nil {
> +			c.sendAlert(alertInternalError)
> +			return err
> +		}
> +		transcript.Write(clientHelloBytes)
>  		pskBinder := hs.suite.finishedHash(binderKey, transcript)
>  		if !hmac.Equal(hs.clientHello.pskBinders[i], pskBinder) {
>  			c.sendAlert(alertDecryptError)
> @@ -393,8 +398,7 @@
>  	}
>  	hs.sentDummyCCS = true
>  
> -	_, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
> -	return err
> +	return hs.c.writeChangeCipherRecord()
>  }
>  
>  func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error {
> @@ -402,7 +406,9 @@
>  
>  	// The first ClientHello gets double-hashed into the transcript upon a
>  	// HelloRetryRequest. See RFC 8446, Section 4.4.1.
> -	hs.transcript.Write(hs.clientHello.marshal())
> +	if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
> +		return err
> +	}
>  	chHash := hs.transcript.Sum(nil)
>  	hs.transcript.Reset()
>  	hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})
> @@ -418,8 +424,7 @@
>  		selectedGroup:     selectedGroup,
>  	}
>  
> -	hs.transcript.Write(helloRetryRequest.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(helloRetryRequest, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -427,7 +432,8 @@
>  		return err
>  	}
>  
> -	msg, err := c.readHandshake()
> +	// clientHelloMsg is not included in the transcript.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> @@ -518,9 +524,10 @@
>  func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
>  	c := hs.c
>  
> -	hs.transcript.Write(hs.clientHello.marshal())
> -	hs.transcript.Write(hs.hello.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
> +	if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
> +		return err
> +	}
> +	if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -563,8 +570,7 @@
>  	encryptedExtensions.alpnProtocol = selectedProto
>  	c.clientProtocol = selectedProto
>  
> -	hs.transcript.Write(encryptedExtensions.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(encryptedExtensions, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -593,8 +599,7 @@
>  			certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
>  		}
>  
> -		hs.transcript.Write(certReq.marshal())
> -		if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
> +		if _, err := hs.c.writeHandshakeRecord(certReq, hs.transcript); err != nil {
>  			return err
>  		}
>  	}
> @@ -605,8 +610,7 @@
>  	certMsg.scts = hs.clientHello.scts && len(hs.cert.SignedCertificateTimestamps) > 0
>  	certMsg.ocspStapling = hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0
>  
> -	hs.transcript.Write(certMsg.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -637,8 +641,7 @@
>  	}
>  	certVerifyMsg.signature = sig
>  
> -	hs.transcript.Write(certVerifyMsg.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(certVerifyMsg, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -652,8 +655,7 @@
>  		verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript),
>  	}
>  
> -	hs.transcript.Write(finished.marshal())
> -	if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
> +	if _, err := hs.c.writeHandshakeRecord(finished, hs.transcript); err != nil {
>  		return err
>  	}
>  
> @@ -714,7 +716,9 @@
>  	finishedMsg := &finishedMsg{
>  		verifyData: hs.clientFinished,
>  	}
> -	hs.transcript.Write(finishedMsg.marshal())
> +	if err := transcriptMsg(finishedMsg, hs.transcript); err != nil {
> +		return err
> +	}
>  
>  	if !hs.shouldSendSessionTickets() {
>  		return nil
> @@ -739,8 +743,12 @@
>  			SignedCertificateTimestamps: c.scts,
>  		},
>  	}
> -	var err error
> -	m.label, err = c.encryptTicket(state.marshal())
> +	stateBytes, err := state.marshal()
> +	if err != nil {
> +		c.sendAlert(alertInternalError)
> +		return err
> +	}
> +	m.label, err = c.encryptTicket(stateBytes)
>  	if err != nil {
>  		return err
>  	}
> @@ -759,7 +767,7 @@
>  	// ticket_nonce, which must be unique per connection, is always left at
>  	// zero because we only ever send one ticket per connection.
>  
> -	if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
> +	if _, err := c.writeHandshakeRecord(m, nil); err != nil {
>  		return err
>  	}
>  
> @@ -784,7 +792,7 @@
>  	// If we requested a client certificate, then the client must send a
>  	// certificate message. If it's empty, no CertificateVerify is sent.
>  
> -	msg, err := c.readHandshake()
> +	msg, err := c.readHandshake(hs.transcript)
>  	if err != nil {
>  		return err
>  	}
> @@ -794,7 +802,6 @@
>  		c.sendAlert(alertUnexpectedMessage)
>  		return unexpectedMessageError(certMsg, msg)
>  	}
> -	hs.transcript.Write(certMsg.marshal())
>  
>  	if err := c.processCertsFromClient(certMsg.certificate); err != nil {
>  		return err
> @@ -808,7 +815,10 @@
>  	}
>  
>  	if len(certMsg.certificate.Certificate) != 0 {
> -		msg, err = c.readHandshake()
> +		// certificateVerifyMsg is included in the transcript, but not until
> +		// after we verify the handshake signature, since the state before
> +		// this message was sent is used.
> +		msg, err = c.readHandshake(nil)
>  		if err != nil {
>  			return err
>  		}
> @@ -839,7 +849,9 @@
>  			return errors.New("tls: invalid signature by the client certificate: " + err.Error())
>  		}
>  
> -		hs.transcript.Write(certVerify.marshal())
> +		if err := transcriptMsg(certVerify, hs.transcript); err != nil {
> +			return err
> +		}
>  	}
>  
>  	// If we waited until the client certificates to send session tickets, we
> @@ -854,7 +866,8 @@
>  func (hs *serverHandshakeStateTLS13) readClientFinished() error {
>  	c := hs.c
>  
> -	msg, err := c.readHandshake()
> +	// finishedMsg is not included in the transcript.
> +	msg, err := c.readHandshake(nil)
>  	if err != nil {
>  		return err
>  	}
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/key_schedule.go golang-1.19-1.19.6/src/crypto/tls/key_schedule.go
> --- golang-1.19-1.19.5/src/crypto/tls/key_schedule.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/key_schedule.go	2023-02-14 01:38:45.000000000 +0800
> @@ -8,6 +8,7 @@
>  	"crypto/elliptic"
>  	"crypto/hmac"
>  	"errors"
> +	"fmt"
>  	"hash"
>  	"io"
>  	"math/big"
> @@ -42,8 +43,24 @@
>  	hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
>  		b.AddBytes(context)
>  	})
> +	hkdfLabelBytes, err := hkdfLabel.Bytes()
> +	if err != nil {
> +		// Rather than calling BytesOrPanic, we explicitly handle this error, in
> +		// order to provide a reasonable error message. It should be basically
> +		// impossible for this to panic, and routing errors back through the
> +		// tree rooted in this function is quite painful. The labels are fixed
> +		// size, and the context is either a fixed-length computed hash, or
> +		// parsed from a field which has the same length limitation. As such, an
> +		// error here is likely to only be caused during development.
> +		//
> +		// NOTE: another reasonable approach here might be to return a
> +		// randomized slice if we encounter an error, which would break the
> +		// connection, but avoid panicking. This would perhaps be safer but
> +		// significantly more confusing to users.
> +		panic(fmt.Errorf("failed to construct HKDF label: %s", err))
> +	}
>  	out := make([]byte, length)
> -	n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
> +	n, err := hkdf.Expand(c.hash.New, secret, hkdfLabelBytes).Read(out)
>  	if err != nil || n != length {
>  		panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
>  	}
> diff -Nru golang-1.19-1.19.5/src/crypto/tls/ticket.go golang-1.19-1.19.6/src/crypto/tls/ticket.go
> --- golang-1.19-1.19.5/src/crypto/tls/ticket.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/tls/ticket.go	2023-02-14 01:38:45.000000000 +0800
> @@ -32,7 +32,7 @@
>  	usedOldKey bool
>  }
>  
> -func (m *sessionState) marshal() []byte {
> +func (m *sessionState) marshal() ([]byte, error) {
>  	var b cryptobyte.Builder
>  	b.AddUint16(m.vers)
>  	b.AddUint16(m.cipherSuite)
> @@ -47,7 +47,7 @@
>  			})
>  		}
>  	})
> -	return b.BytesOrPanic()
> +	return b.Bytes()
>  }
>  
>  func (m *sessionState) unmarshal(data []byte) bool {
> @@ -86,7 +86,7 @@
>  	certificate      Certificate // CertificateEntry certificate_list<0..2^24-1>;
>  }
>  
> -func (m *sessionStateTLS13) marshal() []byte {
> +func (m *sessionStateTLS13) marshal() ([]byte, error) {
>  	var b cryptobyte.Builder
>  	b.AddUint16(VersionTLS13)
>  	b.AddUint8(0) // revision
> @@ -96,7 +96,7 @@
>  		b.AddBytes(m.resumptionSecret)
>  	})
>  	marshalCertificate(&b, m.certificate)
> -	return b.BytesOrPanic()
> +	return b.Bytes()
>  }
>  
>  func (m *sessionStateTLS13) unmarshal(data []byte) bool {
> diff -Nru golang-1.19-1.19.5/src/crypto/x509/boring_test.go golang-1.19-1.19.6/src/crypto/x509/boring_test.go
> --- golang-1.19-1.19.5/src/crypto/x509/boring_test.go	2023-01-10 06:38:14.000000000 +0800
> +++ golang-1.19-1.19.6/src/crypto/x509/boring_test.go	2023-02-14 01:38:45.000000000 +0800
> @@ -54,7 +54,7 @@
>  
>  func TestBoringAllowCert(t *testing.T) {
>  	R1 := testBoringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK)
> -	R2 := testBoringCert(t, "R2", boringRSAKey(t, 8192), nil, boringCertCA)
> +	R2 := testBoringCert(t, "R2", boringRSAKey(t, 512), nil, boringCertCA)
>  	R3 := testBoringCert(t, "R3", boringRSAKey(t, 4096), nil, boringCertCA|boringCertFIPSOK)
>  
>  	M1_R1 := testBoringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK)
> diff -Nru golang-1.19-1.19.5/src/mime/multipart/formdata.go golang-1.19-1.19.6/src/mime/multipart/formdata.go
> --- golang-1.19-1.19.5/src/mime/multipart/formdata.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/mime/multipart/formdata.go	2023-02-14 01:38:47.000000000 +0800
> @@ -7,6 +7,7 @@
>  import (
>  	"bytes"
>  	"errors"
> +	"internal/godebug"
>  	"io"
>  	"math"
>  	"net/textproto"
> @@ -33,23 +34,58 @@
>  
>  func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
>  	form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
> +	var (
> +		file    *os.File
> +		fileOff int64
> +	)
> +	numDiskFiles := 0
> +	multipartFiles := godebug.Get("multipartfiles")
> +	combineFiles := multipartFiles != "distinct"
>  	defer func() {
> +		if file != nil {
> +			if cerr := file.Close(); err == nil {
> +				err = cerr
> +			}
> +		}
> +		if combineFiles && numDiskFiles > 1 {
> +			for _, fhs := range form.File {
> +				for _, fh := range fhs {
> +					fh.tmpshared = true
> +				}
> +			}
> +		}
>  		if err != nil {
>  			form.RemoveAll()
> +			if file != nil {
> +				os.Remove(file.Name())
> +			}
>  		}
>  	}()
>  
> -	// Reserve an additional 10 MB for non-file parts.
> -	maxValueBytes := maxMemory + int64(10<<20)
> -	if maxValueBytes <= 0 {
> +	// maxFileMemoryBytes is the maximum bytes of file data we will store in memory.
> +	// Data past this limit is written to disk.
> +	// This limit strictly applies to content, not metadata (filenames, MIME headers, etc.),
> +	// since metadata is always stored in memory, not disk.
> +	//
> +	// maxMemoryBytes is the maximum bytes we will store in memory, including file content,
> +	// non-file part values, metdata, and map entry overhead.
> +	//
> +	// We reserve an additional 10 MB in maxMemoryBytes for non-file data.
> +	//
> +	// The relationship between these parameters, as well as the overly-large and
> +	// unconfigurable 10 MB added on to maxMemory, is unfortunate but difficult to change
> +	// within the constraints of the API as documented.
> +	maxFileMemoryBytes := maxMemory
> +	maxMemoryBytes := maxMemory + int64(10<<20)
> +	if maxMemoryBytes <= 0 {
>  		if maxMemory < 0 {
> -			maxValueBytes = 0
> +			maxMemoryBytes = 0
>  		} else {
> -			maxValueBytes = math.MaxInt64
> +			maxMemoryBytes = math.MaxInt64
>  		}
>  	}
>  	for {
> -		p, err := r.NextPart()
> +		p, err := r.nextPart(false, maxMemoryBytes)
>  		if err == io.EOF {
>  			break
>  		}
> @@ -63,16 +99,27 @@
>  		}
>  		filename := p.FileName()
>  
> +		// Multiple values for the same key (one map entry, longer slice) are cheaper
> +		// than the same number of values for different keys (many map entries), but
> +		// using a consistent per-value cost for overhead is simpler.
> +		maxMemoryBytes -= int64(len(name))
> +		maxMemoryBytes -= 100 // map overhead
> +		if maxMemoryBytes < 0 {
> +			// We can't actually take this path, since nextPart would already have
> +			// rejected the MIME headers for being too large. Check anyway.
> +			return nil, ErrMessageTooLarge
> +		}
> +
>  		var b bytes.Buffer
>  
>  		if filename == "" {
>  			// value, store as string in memory
> -			n, err := io.CopyN(&b, p, maxValueBytes+1)
> +			n, err := io.CopyN(&b, p, maxMemoryBytes+1)
>  			if err != nil && err != io.EOF {
>  				return nil, err
>  			}
> -			maxValueBytes -= n
> -			if maxValueBytes < 0 {
> +			maxMemoryBytes -= n
> +			if maxMemoryBytes < 0 {
>  				return nil, ErrMessageTooLarge
>  			}
>  			form.Value[name] = append(form.Value[name], b.String())
> @@ -80,35 +127,45 @@
>  		}
>  
>  		// file, store in memory or on disk
> +		maxMemoryBytes -= mimeHeaderSize(p.Header)
> +		if maxMemoryBytes < 0 {
> +			return nil, ErrMessageTooLarge
> +		}
>  		fh := &FileHeader{
>  			Filename: filename,
>  			Header:   p.Header,
>  		}
> -		n, err := io.CopyN(&b, p, maxMemory+1)
> +		n, err := io.CopyN(&b, p, maxFileMemoryBytes+1)
>  		if err != nil && err != io.EOF {
>  			return nil, err
>  		}
> -		if n > maxMemory {
> -			// too big, write to disk and flush buffer
> -			file, err := os.CreateTemp("", "multipart-")
> -			if err != nil {
> -				return nil, err
> +		if n > maxFileMemoryBytes {
> +			if file == nil {
> +				file, err = os.CreateTemp(r.tempDir, "multipart-")
> +				if err != nil {
> +					return nil, err
> +				}
>  			}
> +			numDiskFiles++
>  			size, err := io.Copy(file, io.MultiReader(&b, p))
> -			if cerr := file.Close(); err == nil {
> -				err = cerr
> -			}
>  			if err != nil {
> -				os.Remove(file.Name())
>  				return nil, err
>  			}
>  			fh.tmpfile = file.Name()
>  			fh.Size = size
> +			fh.tmpoff = fileOff
> +			fileOff += size
> +			if !combineFiles {
> +				if err := file.Close(); err != nil {
> +					return nil, err
> +				}
> +				file = nil
> +			}
>  		} else {
>  			fh.content = b.Bytes()
>  			fh.Size = int64(len(fh.content))
> -			maxMemory -= n
> -			maxValueBytes -= n
> +			maxFileMemoryBytes -= n
> +			maxMemoryBytes -= n
>  		}
>  		form.File[name] = append(form.File[name], fh)
>  	}
> @@ -116,6 +173,17 @@
>  	return form, nil
>  }
>  
> +func mimeHeaderSize(h textproto.MIMEHeader) (size int64) {
> +	for k, vs := range h {
> +		size += int64(len(k))
> +		size += 100 // map entry overhead
> +		for _, v := range vs {
> +			size += int64(len(v))
> +		}
> +	}
> +	return size
> +}
> +
>  // Form is a parsed multipart form.
>  // Its File parts are stored either in memory or on disk,
>  // and are accessible via the *FileHeader's Open method.
> @@ -133,7 +201,7 @@
>  		for _, fh := range fhs {
>  			if fh.tmpfile != "" {
>  				e := os.Remove(fh.tmpfile)
> -				if e != nil && err == nil {
> +				if e != nil && !errors.Is(e, os.ErrNotExist) && err == nil {
>  					err = e
>  				}
>  			}
> @@ -148,15 +216,25 @@
>  	Header   textproto.MIMEHeader
>  	Size     int64
>  
> -	content []byte
> -	tmpfile string
> +	content   []byte
> +	tmpfile   string
> +	tmpoff    int64
> +	tmpshared bool
>  }
>  
>  // Open opens and returns the FileHeader's associated File.
>  func (fh *FileHeader) Open() (File, error) {
>  	if b := fh.content; b != nil {
>  		r := io.NewSectionReader(bytes.NewReader(b), 0, int64(len(b)))
> -		return sectionReadCloser{r}, nil
> +		return sectionReadCloser{r, nil}, nil
> +	}
> +	if fh.tmpshared {
> +		f, err := os.Open(fh.tmpfile)
> +		if err != nil {
> +			return nil, err
> +		}
> +		r := io.NewSectionReader(f, fh.tmpoff, fh.Size)
> +		return sectionReadCloser{r, f}, nil
>  	}
>  	return os.Open(fh.tmpfile)
>  }
> @@ -175,8 +253,12 @@
>  
>  type sectionReadCloser struct {
>  	*io.SectionReader
> +	io.Closer
>  }
>  
>  func (rc sectionReadCloser) Close() error {
> +	if rc.Closer != nil {
> +		return rc.Closer.Close()
> +	}
>  	return nil
>  }
> diff -Nru golang-1.19-1.19.5/src/mime/multipart/formdata_test.go golang-1.19-1.19.6/src/mime/multipart/formdata_test.go
> --- golang-1.19-1.19.5/src/mime/multipart/formdata_test.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/mime/multipart/formdata_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -6,8 +6,10 @@
>  
>  import (
>  	"bytes"
> +	"fmt"
>  	"io"
>  	"math"
> +	"net/textproto"
>  	"os"
>  	"strings"
>  	"testing"
> @@ -208,8 +210,8 @@
>  		maxMemory int64
>  		err       error
>  	}{
> -		{"smaller", 50, nil},
> -		{"exact-fit", 25, nil},
> +		{"smaller", 50 + int64(len("largetext")) + 100, nil},
> +		{"exact-fit", 25 + int64(len("largetext")) + 100, nil},
>  		{"too-large", 0, ErrMessageTooLarge},
>  	}
>  	for _, tc := range testCases {
> @@ -224,7 +226,7 @@
>  				defer f.RemoveAll()
>  			}
>  			if tc.err != err {
> -				t.Fatalf("ReadForm error - got: %v; expected: %v", tc.err, err)
> +				t.Fatalf("ReadForm error - got: %v; expected: %v", err, tc.err)
>  			}
>  			if err == nil {
>  				if g := f.Value["largetext"][0]; g != largeTextValue {
> @@ -234,3 +236,135 @@
>  		})
>  	}
>  }
> +
> +// TestReadForm_MetadataTooLarge verifies that we account for the size of field names,
> +// MIME headers, and map entry overhead while limiting the memory consumption of parsed forms.
> +func TestReadForm_MetadataTooLarge(t *testing.T) {
> +	for _, test := range []struct {
> +		name string
> +		f    func(*Writer)
> +	}{{
> +		name: "large name",
> +		f: func(fw *Writer) {
> +			name := strings.Repeat("a", 10<<20)
> +			w, _ := fw.CreateFormField(name)
> +			w.Write([]byte("value"))
> +		},
> +	}, {
> +		name: "large MIME header",
> +		f: func(fw *Writer) {
> +			h := make(textproto.MIMEHeader)
> +			h.Set("Content-Disposition", `form-data; name="a"`)
> +			h.Set("X-Foo", strings.Repeat("a", 10<<20))
> +			w, _ := fw.CreatePart(h)
> +			w.Write([]byte("value"))
> +		},
> +	}, {
> +		name: "many parts",
> +		f: func(fw *Writer) {
> +			for i := 0; i < 110000; i++ {
> +				w, _ := fw.CreateFormField("f")
> +				w.Write([]byte("v"))
> +			}
> +		},
> +	}} {
> +		t.Run(test.name, func(t *testing.T) {
> +			var buf bytes.Buffer
> +			fw := NewWriter(&buf)
> +			test.f(fw)
> +			if err := fw.Close(); err != nil {
> +				t.Fatal(err)
> +			}
> +			fr := NewReader(&buf, fw.Boundary())
> +			_, err := fr.ReadForm(0)
> +			if err != ErrMessageTooLarge {
> +				t.Errorf("fr.ReadForm() = %v, want ErrMessageTooLarge", err)
> +			}
> +		})
> +	}
> +}
> +
> +// TestReadForm_ManyFiles_Combined tests that a multipart form containing many files only
> +// results in a single on-disk file.
> +func TestReadForm_ManyFiles_Combined(t *testing.T) {
> +	const distinct = false
> +	testReadFormManyFiles(t, distinct)
> +}
> +
> +// TestReadForm_ManyFiles_Distinct tests that setting GODEBUG=multipartfiles=distinct
> +// results in every file in a multipart form being placed in a distinct on-disk file.
> +func TestReadForm_ManyFiles_Distinct(t *testing.T) {
> +	t.Setenv("GODEBUG", "multipartfiles=distinct")
> +	const distinct = true
> +	testReadFormManyFiles(t, distinct)
> +}
> +
> +func testReadFormManyFiles(t *testing.T, distinct bool) {
> +	var buf bytes.Buffer
> +	fw := NewWriter(&buf)
> +	const numFiles = 10
> +	for i := 0; i < numFiles; i++ {
> +		name := fmt.Sprint(i)
> +		w, err := fw.CreateFormFile(name, name)
> +		if err != nil {
> +			t.Fatal(err)
> +		}
> +		w.Write([]byte(name))
> +	}
> +	if err := fw.Close(); err != nil {
> +		t.Fatal(err)
> +	}
> +	fr := NewReader(&buf, fw.Boundary())
> +	fr.tempDir = t.TempDir()
> +	form, err := fr.ReadForm(0)
> +	if err != nil {
> +		t.Fatal(err)
> +	}
> +	for i := 0; i < numFiles; i++ {
> +		name := fmt.Sprint(i)
> +		if got := len(form.File[name]); got != 1 {
> +			t.Fatalf("form.File[%q] has %v entries, want 1", name, got)
> +		}
> +		fh := form.File[name][0]
> +		file, err := fh.Open()
> +		if err != nil {
> +			t.Fatalf("form.File[%q].Open() = %v", name, err)
> +		}
> +		if distinct {
> +			if _, ok := file.(*os.File); !ok {
> +				t.Fatalf("form.File[%q].Open: %T, want *os.File", name, file)
> +			}
> +		}
> +		got, err := io.ReadAll(file)
> +		file.Close()
> +		if string(got) != name || err != nil {
> +			t.Fatalf("read form.File[%q]: %q, %v; want %q, nil", name, string(got), err, name)
> +		}
> +	}
> +	dir, err := os.Open(fr.tempDir)
> +	if err != nil {
> +		t.Fatal(err)
> +	}
> +	defer dir.Close()
> +	names, err := dir.Readdirnames(0)
> +	if err != nil {
> +		t.Fatal(err)
> +	}
> +	wantNames := 1
> +	if distinct {
> +		wantNames = numFiles
> +	}
> +	if len(names) != wantNames {
> +		t.Fatalf("temp dir contains %v files; want 1", len(names))
> +	}
> +	if err := form.RemoveAll(); err != nil {
> +		t.Fatalf("form.RemoveAll() = %v", err)
> +	}
> +	names, err = dir.Readdirnames(0)
> +	if err != nil {
> +		t.Fatal(err)
> +	}
> +	if len(names) != 0 {
> +		t.Fatalf("temp dir contains %v files; want 0", len(names))
> +	}
> +}
> diff -Nru golang-1.19-1.19.5/src/mime/multipart/multipart.go golang-1.19-1.19.6/src/mime/multipart/multipart.go
> --- golang-1.19-1.19.5/src/mime/multipart/multipart.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/mime/multipart/multipart.go	2023-02-14 01:38:47.000000000 +0800
> @@ -128,12 +128,12 @@
>  	return n, r.err
>  }
>  
> -func newPart(mr *Reader, rawPart bool) (*Part, error) {
> +func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
>  	bp := &Part{
>  		Header: make(map[string][]string),
>  		mr:     mr,
>  	}
> -	if err := bp.populateHeaders(); err != nil {
> +	if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil {
>  		return nil, err
>  	}
>  	bp.r = partReader{bp}
> @@ -149,12 +149,16 @@
>  	return bp, nil
>  }
>  
> -func (p *Part) populateHeaders() error {
> +func (p *Part) populateHeaders(maxMIMEHeaderSize int64) error {
>  	r := textproto.NewReader(p.mr.bufReader)
> -	header, err := r.ReadMIMEHeader()
> +	header, err := readMIMEHeader(r, maxMIMEHeaderSize)
>  	if err == nil {
>  		p.Header = header
>  	}
> +	// TODO: Add a distinguishable error to net/textproto.
> +	if err != nil && err.Error() == "message too large" {
> +		err = ErrMessageTooLarge
> +	}
>  	return err
>  }
>  
> @@ -311,6 +315,7 @@
>  // isn't supported.
>  type Reader struct {
>  	bufReader *bufio.Reader
> +	tempDir   string // used in tests
>  
>  	currentPart *Part
>  	partsRead   int
> @@ -321,6 +326,10 @@
>  	dashBoundary     []byte // "--boundary"
>  }
>  
> +// maxMIMEHeaderSize is the maximum size of a MIME header we will parse,
> +// including header keys, values, and map overhead.
> +const maxMIMEHeaderSize = 10 << 20
> +
>  // NextPart returns the next part in the multipart or an error.
>  // When there are no more parts, the error io.EOF is returned.
>  //
> @@ -328,7 +337,7 @@
>  // has a value of "quoted-printable", that header is instead
>  // hidden and the body is transparently decoded during Read calls.
>  func (r *Reader) NextPart() (*Part, error) {
> -	return r.nextPart(false)
> +	return r.nextPart(false, maxMIMEHeaderSize)
>  }
>  
>  // NextRawPart returns the next part in the multipart or an error.
> @@ -337,10 +346,10 @@
>  // Unlike NextPart, it does not have special handling for
>  // "Content-Transfer-Encoding: quoted-printable".
>  func (r *Reader) NextRawPart() (*Part, error) {
> -	return r.nextPart(true)
> +	return r.nextPart(true, maxMIMEHeaderSize)
>  }
>  
> -func (r *Reader) nextPart(rawPart bool) (*Part, error) {
> +func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
>  	if r.currentPart != nil {
>  		r.currentPart.Close()
>  	}
> @@ -365,7 +374,7 @@
>  
>  		if r.isBoundaryDelimiterLine(line) {
>  			r.partsRead++
> -			bp, err := newPart(r, rawPart)
> +			bp, err := newPart(r, rawPart, maxMIMEHeaderSize)
>  			if err != nil {
>  				return nil, err
>  			}
> diff -Nru golang-1.19-1.19.5/src/mime/multipart/readmimeheader.go golang-1.19-1.19.6/src/mime/multipart/readmimeheader.go
> --- golang-1.19-1.19.5/src/mime/multipart/readmimeheader.go	1970-01-01 08:00:00.000000000 +0800
> +++ golang-1.19-1.19.6/src/mime/multipart/readmimeheader.go	2023-02-14 01:38:47.000000000 +0800
> @@ -0,0 +1,14 @@
> +// Copyright 2023 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.
> +package multipart
> +
> +import (
> +	"net/textproto"
> +	_ "unsafe" // for go:linkname
> +)
> +
> +// readMIMEHeader is defined in package net/textproto.
> +//
> +//go:linkname readMIMEHeader net/textproto.readMIMEHeader
> +func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, error)
> diff -Nru golang-1.19-1.19.5/src/net/http/readrequest_test.go golang-1.19-1.19.6/src/net/http/readrequest_test.go
> --- golang-1.19-1.19.5/src/net/http/readrequest_test.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/net/http/readrequest_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -450,16 +450,19 @@
>  Content-Length: 4
>  
>  abc`)},
> -	{"smuggle_content_len_head", reqBytes(`HEAD / HTTP/1.1
> +	{"smuggle_two_content_len_head", reqBytes(`HEAD / HTTP/1.1
>  Host: foo
> -Content-Length: 5`)},
> +Content-Length: 4
> +Content-Length: 5
> +
> +1234`)},
>  
>  	// golang.org/issue/22464
>  	{"leading_space_in_header", reqBytes(`HEAD / HTTP/1.1
>   Host: foo
>  Content-Length: 5`)},
>  	{"leading_tab_in_header", reqBytes(`HEAD / HTTP/1.1
> -\tHost: foo
> +` + "\t" + `Host: foo
>  Content-Length: 5`)},
>  }
>  
> diff -Nru golang-1.19-1.19.5/src/net/http/request_test.go golang-1.19-1.19.6/src/net/http/request_test.go
> --- golang-1.19-1.19.5/src/net/http/request_test.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/net/http/request_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -485,10 +485,6 @@
>  	1: {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF.Error(), nil},
>  	2: {"", io.EOF.Error(), nil},
>  	3: {
> -		in:  "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
> -		err: "http: method cannot contain a Content-Length",
> -	},
> -	4: {
>  		in:     "HEAD / HTTP/1.1\r\n\r\n",
>  		header: Header{},
>  	},
> @@ -496,32 +492,32 @@
>  	// Multiple Content-Length values should either be
>  	// deduplicated if same or reject otherwise
>  	// See Issue 16490.
> -	5: {
> +	4: {
>  		in:  "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n",
>  		err: "cannot contain multiple Content-Length headers",
>  	},
> -	6: {
> +	5: {
>  		in:  "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n",
>  		err: "cannot contain multiple Content-Length headers",
>  	},
> -	7: {
> +	6: {
>  		in:     "PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n",
>  		err:    "",
>  		header: Header{"Content-Length": {"6"}},
>  	},
> -	8: {
> +	7: {
>  		in:  "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n",
>  		err: "cannot contain multiple Content-Length headers",
>  	},
> -	9: {
> +	8: {
>  		in:  "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n",
>  		err: "cannot contain multiple Content-Length headers",
>  	},
> -	10: {
> +	9: {
>  		in:     "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
>  		header: Header{"Content-Length": {"0"}},
>  	},
> -	11: {
> +	10: {
>  		in:  "HEAD / HTTP/1.1\r\nHost: foo\r\nHost: bar\r\n\r\n\r\n\r\n",
>  		err: "too many Host headers",
>  	},
> @@ -1108,7 +1104,7 @@
>  		t.Errorf("FormFile file = %v, want nil", f)
>  	}
>  	if fh != nil {
> -		t.Errorf("FormFile file header = %q, want nil", fh)
> +		t.Errorf("FormFile file header = %v, want nil", fh)
>  	}
>  	if err != ErrMissingFile {
>  		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
> diff -Nru golang-1.19-1.19.5/src/net/http/serve_test.go golang-1.19-1.19.6/src/net/http/serve_test.go
> --- golang-1.19-1.19.5/src/net/http/serve_test.go	2023-01-10 06:38:18.000000000 +0800
> +++ golang-1.19-1.19.6/src/net/http/serve_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -6758,3 +6758,73 @@
>  		t.Errorf("unexpected response; got %q; should start by %q", got, expected)
>  	}
>  }
> +
> +func TestHeadBody(t *testing.T) {
> +	const identityMode = false
> +	const chunkedMode = true
> +	t.Run("h1", func(t *testing.T) {
> +		t.Run("identity", func(t *testing.T) { testHeadBody(t, h1Mode, identityMode, "HEAD") })
> +		t.Run("chunked", func(t *testing.T) { testHeadBody(t, h1Mode, chunkedMode, "HEAD") })
> +	})
> +	t.Run("h2", func(t *testing.T) {
> +		t.Run("identity", func(t *testing.T) { testHeadBody(t, h2Mode, identityMode, "HEAD") })
> +		t.Run("chunked", func(t *testing.T) { testHeadBody(t, h2Mode, chunkedMode, "HEAD") })
> +	})
> +}
> +
> +func TestGetBody(t *testing.T) {
> +	const identityMode = false
> +	const chunkedMode = true
> +	t.Run("h1", func(t *testing.T) {
> +		t.Run("identity", func(t *testing.T) { testHeadBody(t, h1Mode, identityMode, "GET") })
> +		t.Run("chunked", func(t *testing.T) { testHeadBody(t, h1Mode, chunkedMode, "GET") })
> +	})
> +	t.Run("h2", func(t *testing.T) {
> +		t.Run("identity", func(t *testing.T) { testHeadBody(t, h2Mode, identityMode, "GET") })
> +		t.Run("chunked", func(t *testing.T) { testHeadBody(t, h2Mode, chunkedMode, "GET") })
> +	})
> +}
> +
> +func testHeadBody(t *testing.T, h2, chunked bool, method string) {
> +	setParallel(t)
> +	defer afterTest(t)
> +	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
> +		b, err := io.ReadAll(r.Body)
> +		if err != nil {
> +			t.Errorf("server reading body: %v", err)
> +			return
> +		}
> +		w.Header().Set("X-Request-Body", string(b))
> +		w.Header().Set("Content-Length", "0")
> +	}))
> +	defer cst.close()
> +	for _, reqBody := range []string{
> +		"",
> +		"",
> +		"request_body",
> +		"",
> +	} {
> +		var bodyReader io.Reader
> +		if reqBody != "" {
> +			bodyReader = strings.NewReader(reqBody)
> +			if chunked {
> +				bodyReader = bufio.NewReader(bodyReader)
> +			}
> +		}
> +		req, err := NewRequest(method, cst.ts.URL, bodyReader)
> +		if err != nil {
> +			t.Fatal(err)
> +		}
> +		res, err := cst.c.Do(req)
> +		if err != nil {
> +			t.Fatal(err)
> +		}
> +		res.Body.Close()
> +		if got, want := res.StatusCode, 200; got != want {
> +			t.Errorf("%v request with %d-byte body: StatusCode = %v, want %v", method, len(reqBody), got, want)
> +		}
> +		if got, want := res.Header.Get("X-Request-Body"), reqBody; got != want {
> +			t.Errorf("%v request with %d-byte body: handler read body %q, want %q", method, len(reqBody), got, want)
> +		}
> +	}
> +}
> diff -Nru golang-1.19-1.19.5/src/net/http/transfer.go golang-1.19-1.19.6/src/net/http/transfer.go
> --- golang-1.19-1.19.5/src/net/http/transfer.go	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/net/http/transfer.go	2023-02-14 01:38:47.000000000 +0800
> @@ -557,7 +557,7 @@
>  	// or close connection when finished, since multipart is not supported yet
>  	switch {
>  	case t.Chunked:
> -		if noResponseBodyExpected(t.RequestMethod) || !bodyAllowedForStatus(t.StatusCode) {
> +		if isResponse && (noResponseBodyExpected(t.RequestMethod) || !bodyAllowedForStatus(t.StatusCode)) {
>  			t.Body = NoBody
>  		} else {
>  			t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
> @@ -691,14 +691,7 @@
>  	}
>  
>  	// Logic based on response type or status
> -	if noResponseBodyExpected(requestMethod) {
> -		// For HTTP requests, as part of hardening against request
> -		// smuggling (RFC 7230), don't allow a Content-Length header for
> -		// methods which don't permit bodies. As an exception, allow
> -		// exactly one Content-Length header if its value is "0".
> -		if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
> -			return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
> -		}
> +	if isResponse && noResponseBodyExpected(requestMethod) {
>  		return 0, nil
>  	}
>  	if status/100 == 1 {
> diff -Nru golang-1.19-1.19.5/src/net/textproto/reader.go golang-1.19-1.19.6/src/net/textproto/reader.go
> --- golang-1.19-1.19.5/src/net/textproto/reader.go	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/net/textproto/reader.go	2023-02-14 01:38:47.000000000 +0800
> @@ -7,8 +7,10 @@
>  import (
>  	"bufio"
>  	"bytes"
> +	"errors"
>  	"fmt"
>  	"io"
> +	"math"
>  	"strconv"
>  	"strings"
>  	"sync"
> @@ -481,6 +483,12 @@
>  //		"Long-Key": {"Even Longer Value"},
>  //	}
>  func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
> +	return readMIMEHeader(r, math.MaxInt64)
> +}
> +
> +// readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
> +// It is called by the mime/multipart package.
> +func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
>  	// Avoid lots of small slice allocations later by allocating one
>  	// large one ahead of time which we'll cut up into smaller
>  	// slices. If this isn't big enough later, we allocate small ones.
> @@ -522,9 +530,19 @@
>  		}
>  
>  		// Skip initial spaces in value.
> -		value := strings.TrimLeft(string(v), " \t")
> +		value := string(bytes.TrimLeft(v, " \t"))
>  
>  		vv := m[key]
> +		if vv == nil {
> +			lim -= int64(len(key))
> +			lim -= 100 // map entry overhead
> +		}
> +		lim -= int64(len(value))
> +		if lim < 0 {
> +			// TODO: This should be a distinguishable error (ErrMessageTooLarge)
> +			// to allow mime/multipart to detect it.
> +			return m, errors.New("message too large")
> +		}
>  		if vv == nil && len(strs) > 0 {
>  			// More than likely this will be a single-element key.
>  			// Most headers aren't multi-valued.
> diff -Nru golang-1.19-1.19.5/src/path/filepath/path.go golang-1.19-1.19.6/src/path/filepath/path.go
> --- golang-1.19-1.19.5/src/path/filepath/path.go	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/path/filepath/path.go	2023-02-14 01:38:47.000000000 +0800
> @@ -15,6 +15,7 @@
>  	"errors"
>  	"io/fs"
>  	"os"
> +	"runtime"
>  	"sort"
>  	"strings"
>  )
> @@ -117,21 +118,9 @@
>  		case os.IsPathSeparator(path[r]):
>  			// empty path element
>  			r++
> -		case path[r] == '.' && r+1 == n:
> +		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
>  			// . element
>  			r++
> -		case path[r] == '.' && os.IsPathSeparator(path[r+1]):
> -			// ./ element
> -			r++
> -
> -			for r < len(path) && os.IsPathSeparator(path[r]) {
> -				r++
> -			}
> -			if out.w == 0 && volumeNameLen(path[r:]) > 0 {
> -				// When joining prefix "." and an absolute path on Windows,
> -				// the prefix should not be removed.
> -				out.append('.')
> -			}
>  		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
>  			// .. element: remove to last separator
>  			r += 2
> @@ -157,6 +146,18 @@
>  			if rooted && out.w != 1 || !rooted && out.w != 0 {
>  				out.append(Separator)
>  			}
> +			// If a ':' appears in the path element at the start of a Windows path,
> +			// insert a .\ at the beginning to avoid converting relative paths
> +			// like a/../c: into c:.
> +			if runtime.GOOS == "windows" && out.w == 0 && out.volLen == 0 && r != 0 {
> +				for i := r; i < n && !os.IsPathSeparator(path[i]); i++ {
> +					if path[i] == ':' {
> +						out.append('.')
> +						out.append(Separator)
> +						break
> +					}
> +				}
> +			}
>  			// copy element
>  			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
>  				out.append(path[r])
> diff -Nru golang-1.19-1.19.5/src/path/filepath/path_test.go golang-1.19-1.19.6/src/path/filepath/path_test.go
> --- golang-1.19-1.19.5/src/path/filepath/path_test.go	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/path/filepath/path_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -96,6 +96,13 @@
>  	{`.\c:`, `.\c:`},
>  	{`.\c:\foo`, `.\c:\foo`},
>  	{`.\c:foo`, `.\c:foo`},
> +
> +	// Don't allow cleaning to move an element with a colon to the start of the path.
> +	{`a/../c:`, `.\c:`},
> +	{`a\..\c:`, `.\c:`},
> +	{`a/../c:/a`, `.\c:\a`},
> +	{`a/../../c:`, `..\c:`},
> +	{`foo:bar`, `foo:bar`},
>  }
>  
>  func TestClean(t *testing.T) {
> diff -Nru golang-1.19-1.19.5/src/path/filepath/path_windows_test.go golang-1.19-1.19.6/src/path/filepath/path_windows_test.go
> --- golang-1.19-1.19.5/src/path/filepath/path_windows_test.go	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/path/filepath/path_windows_test.go	2023-02-14 01:38:47.000000000 +0800
> @@ -542,7 +542,7 @@
>  	}{
>  		{`..\.`, `C:`, `..\C:`},
>  		{`..`, `C:`, `..\C:`},
> -		{`.`, `:`, `:`},
> +		{`.`, `:`, `.\:`},
>  		{`.`, `C:`, `.\C:`},
>  		{`.`, `C:/a/b/../c`, `.\C:\a\c`},
>  		{`.`, `\C:`, `.\C:`},
> diff -Nru golang-1.19-1.19.5/src/runtime/asm_ppc64x.s golang-1.19-1.19.6/src/runtime/asm_ppc64x.s
> --- golang-1.19-1.19.5/src/runtime/asm_ppc64x.s	2023-01-10 06:38:19.000000000 +0800
> +++ golang-1.19-1.19.6/src/runtime/asm_ppc64x.s	2023-02-14 01:38:47.000000000 +0800
> @@ -339,8 +339,11 @@
>  	// the caller doesn't save LR on stack but passes it as a
>  	// register (R5), and the unwinder currently doesn't understand.
>  	// Make it SPWRITE to stop unwinding. (See issue 54332)
> -	MOVD	R1, R1
> +	// Use OR R0, R1 instead of MOVD R1, R1 as the MOVD instruction
> +	// has a special affect on Power8,9,10 by lowering the thread 
> +	// priority and causing a slowdown in execution time
>  
> +	OR	R0, R1
>  	MOVD	R0, R11
>  	BR	runtime·morestack(SB)
>  
> diff -Nru golang-1.19-1.19.5/src/time/zoneinfo_abbrs_windows.go golang-1.19-1.19.6/src/time/zoneinfo_abbrs_windows.go
> --- golang-1.19-1.19.5/src/time/zoneinfo_abbrs_windows.go	2023-01-10 06:38:24.000000000 +0800
> +++ golang-1.19-1.19.6/src/time/zoneinfo_abbrs_windows.go	2023-02-14 01:38:48.000000000 +0800
> @@ -16,10 +16,11 @@
>  	"Egypt Standard Time":             {"EET", "EET"},     // Africa/Cairo
>  	"Morocco Standard Time":           {"+00", "+01"},     // Africa/Casablanca
>  	"South Africa Standard Time":      {"SAST", "SAST"},   // Africa/Johannesburg
> +	"South Sudan Standard Time":       {"CAT", "CAT"},     // Africa/Juba
>  	"Sudan Standard Time":             {"CAT", "CAT"},     // Africa/Khartoum
>  	"W. Central Africa Standard Time": {"WAT", "WAT"},     // Africa/Lagos
>  	"E. Africa Standard Time":         {"EAT", "EAT"},     // Africa/Nairobi
> -	"Sao Tome Standard Time":          {"GMT", "WAT"},     // Africa/Sao_Tome
> +	"Sao Tome Standard Time":          {"GMT", "GMT"},     // Africa/Sao_Tome
>  	"Libya Standard Time":             {"EET", "EET"},     // Africa/Tripoli
>  	"Namibia Standard Time":           {"CAT", "CAT"},     // Africa/Windhoek
>  	"Aleutian Standard Time":          {"HST", "HDT"},     // America/Adak
> @@ -33,8 +34,8 @@
>  	"Venezuela Standard Time":         {"-04", "-04"},     // America/Caracas
>  	"SA Eastern Standard Time":        {"-03", "-03"},     // America/Cayenne
>  	"Central Standard Time":           {"CST", "CDT"},     // America/Chicago
> -	"Mountain Standard Time (Mexico)": {"MST", "MDT"},     // America/Chihuahua
> -	"Central Brazilian Standard Time": {"-04", "-03"},     // America/Cuiaba
> +	"Mountain Standard Time (Mexico)": {"CST", "CST"},     // America/Chihuahua
> +	"Central Brazilian Standard Time": {"-04", "-04"},     // America/Cuiaba
>  	"Mountain Standard Time":          {"MST", "MDT"},     // America/Denver
>  	"Greenland Standard Time":         {"-03", "-02"},     // America/Godthab
>  	"Turks And Caicos Standard Time":  {"EST", "EDT"},     // America/Grand_Turk
> @@ -44,7 +45,7 @@
>  	"US Eastern Standard Time":        {"EST", "EDT"},     // America/Indianapolis
>  	"SA Western Standard Time":        {"-04", "-04"},     // America/La_Paz
>  	"Pacific Standard Time":           {"PST", "PDT"},     // America/Los_Angeles
> -	"Central Standard Time (Mexico)":  {"CST", "CDT"},     // America/Mexico_City
> +	"Central Standard Time (Mexico)":  {"CST", "CST"},     // America/Mexico_City
>  	"Saint Pierre Standard Time":      {"-03", "-02"},     // America/Miquelon
>  	"Montevideo Standard Time":        {"-03", "-03"},     // America/Montevideo
>  	"Eastern Standard Time":           {"EST", "EDT"},     // America/New_York
> @@ -53,11 +54,12 @@
>  	"Magallanes Standard Time":        {"-03", "-03"},     // America/Punta_Arenas
>  	"Canada Central Standard Time":    {"CST", "CST"},     // America/Regina
>  	"Pacific SA Standard Time":        {"-04", "-03"},     // America/Santiago
> -	"E. South America Standard Time":  {"-03", "-02"},     // America/Sao_Paulo
> +	"E. South America Standard Time":  {"-03", "-03"},     // America/Sao_Paulo
>  	"Newfoundland Standard Time":      {"NST", "NDT"},     // America/St_Johns
>  	"Pacific Standard Time (Mexico)":  {"PST", "PDT"},     // America/Tijuana
> +	"Yukon Standard Time":             {"MST", "MST"},     // America/Whitehorse
>  	"Central Asia Standard Time":      {"+06", "+06"},     // Asia/Almaty
> -	"Jordan Standard Time":            {"EET", "EEST"},    // Asia/Amman
> +	"Jordan Standard Time":            {"+03", "+03"},     // Asia/Amman
>  	"Arabic Standard Time":            {"+03", "+03"},     // Asia/Baghdad
>  	"Azerbaijan Standard Time":        {"+04", "+04"},     // Asia/Baku
>  	"SE Asia Standard Time":           {"+07", "+07"},     // Asia/Bangkok
> @@ -66,7 +68,7 @@
>  	"India Standard Time":             {"IST", "IST"},     // Asia/Calcutta
>  	"Transbaikal Standard Time":       {"+09", "+09"},     // Asia/Chita
>  	"Sri Lanka Standard Time":         {"+0530", "+0530"}, // Asia/Colombo
> -	"Syria Standard Time":             {"EET", "EEST"},    // Asia/Damascus
> +	"Syria Standard Time":             {"+03", "+03"},     // Asia/Damascus
>  	"Bangladesh Standard Time":        {"+06", "+06"},     // Asia/Dhaka
>  	"Arabian Standard Time":           {"+04", "+04"},     // Asia/Dubai
>  	"West Bank Standard Time":         {"EET", "EEST"},    // Asia/Hebron
> @@ -82,7 +84,7 @@
>  	"N. Central Asia Standard Time":   {"+07", "+07"},     // Asia/Novosibirsk
>  	"Omsk Standard Time":              {"+06", "+06"},     // Asia/Omsk
>  	"North Korea Standard Time":       {"KST", "KST"},     // Asia/Pyongyang
> -	"Qyzylorda Standard Time":         {"+05", "+06"},     // Asia/Qyzylorda
> +	"Qyzylorda Standard Time":         {"+05", "+05"},     // Asia/Qyzylorda
>  	"Myanmar Standard Time":           {"+0630", "+0630"}, // Asia/Rangoon
>  	"Arab Standard Time":              {"+03", "+03"},     // Asia/Riyadh
>  	"Sakhalin Standard Time":          {"+11", "+11"},     // Asia/Sakhalin
> @@ -93,7 +95,7 @@
>  	"Taipei Standard Time":            {"CST", "CST"},     // Asia/Taipei
>  	"West Asia Standard Time":         {"+05", "+05"},     // Asia/Tashkent
>  	"Georgian Standard Time":          {"+04", "+04"},     // Asia/Tbilisi
> -	"Iran Standard Time":              {"+0330", "+0430"}, // Asia/Tehran
> +	"Iran Standard Time":              {"+0330", "+0330"}, // Asia/Tehran
>  	"Tokyo Standard Time":             {"JST", "JST"},     // Asia/Tokyo
>  	"Tomsk Standard Time":             {"+07", "+07"},     // Asia/Tomsk
>  	"Ulaanbaatar Standard Time":       {"+08", "+08"},     // Asia/Ulaanbaatar
> @@ -112,7 +114,6 @@
>  	"Lord Howe Standard Time":         {"+1030", "+11"},   // Australia/Lord_Howe
>  	"W. Australia Standard Time":      {"AWST", "AWST"},   // Australia/Perth
>  	"AUS Eastern Standard Time":       {"AEST", "AEDT"},   // Australia/Sydney
> -	"UTC":                             {"GMT", "GMT"},     // Etc/GMT
>  	"UTC-11":                          {"-11", "-11"},     // Etc/GMT+11
>  	"Dateline Standard Time":          {"-12", "-12"},     // Etc/GMT+12
>  	"UTC-02":                          {"-02", "-02"},     // Etc/GMT+2
> @@ -120,6 +121,7 @@
>  	"UTC-09":                          {"-09", "-09"},     // Etc/GMT+9
>  	"UTC+12":                          {"+12", "+12"},     // Etc/GMT-12
>  	"UTC+13":                          {"+13", "+13"},     // Etc/GMT-13
> +	"UTC":                             {"UTC", "UTC"},     // Etc/UTC
>  	"Astrakhan Standard Time":         {"+04", "+04"},     // Europe/Astrakhan
>  	"W. Europe Standard Time":         {"CET", "CEST"},    // Europe/Berlin
>  	"GTB Standard Time":               {"EET", "EEST"},    // Europe/Bucharest
> @@ -134,20 +136,20 @@
>  	"Romance Standard Time":           {"CET", "CEST"},    // Europe/Paris
>  	"Russia Time Zone 3":              {"+04", "+04"},     // Europe/Samara
>  	"Saratov Standard Time":           {"+04", "+04"},     // Europe/Saratov
> -	"Volgograd Standard Time":         {"+04", "+04"},     // Europe/Volgograd
> +	"Volgograd Standard Time":         {"+03", "+03"},     // Europe/Volgograd
>  	"Central European Standard Time":  {"CET", "CEST"},    // Europe/Warsaw
>  	"Mauritius Standard Time":         {"+04", "+04"},     // Indian/Mauritius
> -	"Samoa Standard Time":             {"+13", "+14"},     // Pacific/Apia
> +	"Samoa Standard Time":             {"+13", "+13"},     // Pacific/Apia
>  	"New Zealand Standard Time":       {"NZST", "NZDT"},   // Pacific/Auckland
>  	"Bougainville Standard Time":      {"+11", "+11"},     // Pacific/Bougainville
>  	"Chatham Islands Standard Time":   {"+1245", "+1345"}, // Pacific/Chatham
>  	"Easter Island Standard Time":     {"-06", "-05"},     // Pacific/Easter
> -	"Fiji Standard Time":              {"+12", "+13"},     // Pacific/Fiji
> +	"Fiji Standard Time":              {"+12", "+12"},     // Pacific/Fiji
>  	"Central Pacific Standard Time":   {"+11", "+11"},     // Pacific/Guadalcanal
>  	"Hawaiian Standard Time":          {"HST", "HST"},     // Pacific/Honolulu
>  	"Line Islands Standard Time":      {"+14", "+14"},     // Pacific/Kiritimati
>  	"Marquesas Standard Time":         {"-0930", "-0930"}, // Pacific/Marquesas
> -	"Norfolk Standard Time":           {"+11", "+11"},     // Pacific/Norfolk
> +	"Norfolk Standard Time":           {"+11", "+12"},     // Pacific/Norfolk
>  	"West Pacific Standard Time":      {"+10", "+10"},     // Pacific/Port_Moresby
>  	"Tonga Standard Time":             {"+13", "+13"},     // Pacific/Tongatapu
>  }
> diff -Nru golang-1.19-1.19.5/src/vendor/golang.org/x/net/http2/hpack/hpack.go golang-1.19-1.19.6/src/vendor/golang.org/x/net/http2/hpack/hpack.go
> --- golang-1.19-1.19.5/src/vendor/golang.org/x/net/http2/hpack/hpack.go	2023-01-10 06:38:24.000000000 +0800
> +++ golang-1.19-1.19.6/src/vendor/golang.org/x/net/http2/hpack/hpack.go	2023-02-14 01:38:48.000000000 +0800
> @@ -359,6 +359,7 @@
>  
>  	var hf HeaderField
>  	wantStr := d.emitEnabled || it.indexed()
> +	var undecodedName undecodedString
>  	if nameIdx > 0 {
>  		ihf, ok := d.at(nameIdx)
>  		if !ok {
> @@ -366,15 +367,27 @@
>  		}
>  		hf.Name = ihf.Name
>  	} else {
> -		hf.Name, buf, err = d.readString(buf, wantStr)
> +		undecodedName, buf, err = d.readString(buf)
>  		if err != nil {
>  			return err
>  		}
>  	}
> -	hf.Value, buf, err = d.readString(buf, wantStr)
> +	undecodedValue, buf, err := d.readString(buf)
>  	if err != nil {
>  		return err
>  	}
> +	if wantStr {
> +		if nameIdx <= 0 {
> +			hf.Name, err = d.decodeString(undecodedName)
> +			if err != nil {
> +				return err
> +			}
> +		}
> +		hf.Value, err = d.decodeString(undecodedValue)
> +		if err != nil {
> +			return err
> +		}
> +	}
>  	d.buf = buf
>  	if it.indexed() {
>  		d.dynTab.add(hf)
> @@ -459,46 +472,52 @@
>  	return 0, origP, errNeedMore
>  }
>  
> -// readString decodes an hpack string from p.
> +// readString reads an hpack string from p.
>  //
> -// wantStr is whether s will be used. If false, decompression and
> -// []byte->string garbage are skipped if s will be ignored
> -// anyway. This does mean that huffman decoding errors for non-indexed
> -// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
> -// is returning an error anyway, and because they're not indexed, the error
> -// won't affect the decoding state.
> -func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
> +// It returns a reference to the encoded string data to permit deferring decode costs
> +// until after the caller verifies all data is present.
> +func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {
>  	if len(p) == 0 {
> -		return "", p, errNeedMore
> +		return u, p, errNeedMore
>  	}
>  	isHuff := p[0]&128 != 0
>  	strLen, p, err := readVarInt(7, p)
>  	if err != nil {
> -		return "", p, err
> +		return u, p, err
>  	}
>  	if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
> -		return "", nil, ErrStringLength
> +		// Returning an error here means Huffman decoding errors
> +		// for non-indexed strings past the maximum string length
> +		// are ignored, but the server is returning an error anyway
> +		// and because the string is not indexed the error will not
> +		// affect the decoding state.
> +		return u, nil, ErrStringLength
>  	}
>  	if uint64(len(p)) < strLen {
> -		return "", p, errNeedMore
> -	}
> -	if !isHuff {
> -		if wantStr {
> -			s = string(p[:strLen])
> -		}
> -		return s, p[strLen:], nil
> +		return u, p, errNeedMore
>  	}
> +	u.isHuff = isHuff
> +	u.b = p[:strLen]
> +	return u, p[strLen:], nil
> +}
>  
> -	if wantStr {
> -		buf := bufPool.Get().(*bytes.Buffer)
> -		buf.Reset() // don't trust others
> -		defer bufPool.Put(buf)
> -		if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
> -			buf.Reset()
> -			return "", nil, err
> -		}
> +type undecodedString struct {
> +	isHuff bool
> +	b      []byte
> +}
> +
> +func (d *Decoder) decodeString(u undecodedString) (string, error) {
> +	if !u.isHuff {
> +		return string(u.b), nil
> +	}
> +	buf := bufPool.Get().(*bytes.Buffer)
> +	buf.Reset() // don't trust others
> +	var s string
> +	err := huffmanDecode(buf, d.maxStrLen, u.b)
> +	if err == nil {
>  		s = buf.String()
> -		buf.Reset() // be nice to GC
>  	}
> -	return s, p[strLen:], nil
> +	buf.Reset() // be nice to GC
> +	bufPool.Put(buf)
> +	return s, err
>  }
> diff -Nru golang-1.19-1.19.5/VERSION golang-1.19-1.19.6/VERSION
> --- golang-1.19-1.19.5/VERSION	2023-01-10 06:38:00.000000000 +0800
> +++ golang-1.19-1.19.6/VERSION	2023-02-14 01:38:41.000000000 +0800
> @@ -1 +1 @@
> -go1.19.5
> \ No newline at end of file
> +go1.19.6
> \ No newline at end of file


-- 
Sebastian Ramacher


Reply to: