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

Bug#1031330: marked as done ([pre-approval] unblock: golang-1.19/1.19.6-2)



Your message dated Sun, 19 Feb 2023 21:26:48 +0100
with message-id <Y/KGCA9e4+S+b/sj@ramacher.at>
and subject line Re: Bug#1031330: [pre-approval] unblock: golang-1.19/1.19.6-2
has caused the Debian Bug report #1031330,
regarding [pre-approval] unblock: golang-1.19/1.19.6-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1031330: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1031330
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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

[ 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).

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

--- End Message ---
--- Begin Message ---
On 2023-02-17 00:11:52 +0100, Sebastian Ramacher wrote:
> 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.

Closing as golang-1.19 will migrate without an explicit RT action.

Cheers

> 
> 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
> 

-- 
Sebastian Ramacher

--- End Message ---

Reply to: