On 2023-02-15 11:58:54 +0800, Shengjing Zhu wrote: > Package: release.debian.org > Severity: normal > User: release.debian....@packages.debian.org > Usertags: unblock > X-Debbugs-Cc: golang-1...@packages.debian.org, z...@debian.org > Control: affects -1 + src:golang-1.19 > > Please unblock package golang-1.19
Please go ahead with the upload. > > [ Reason ] > A new upstream release that addresses 4 CVE in Go standard library. > > [ Impact ] > CVE in Go standard library and the Go packages that have statically > linked with it. > > [ Tests ] > The fixes are covered by new unit tests. > > [ Risks ] > The package is in the toolchain set. > > [ Checklist ] > [x] all changes are documented in the d/changelog > [x] I reviewed all changes and I approve them > [x] attach debdiff against the package in testing > > The diff is for golang-1.19/1.19.6-1, which I have uploaded to > experimental first. -2 should be no-change rebuild on unstable. > > [ Other info ] > So same as previous unblock request #1028452 > + This package doesn't have autopkgtest. > + The upload will trigger Release Team to perform a new round of rebuilding > outdated Built-Using for all Go packages. > > The Go upstream usually has one minor version (may or may not carry CVE > fixes) release every month. > I'm wondering what Release Team thinks how often we should update > during the freeze periods. Some options are: > + Only ask pre-approval for minor versions with CVE > + Don't update any (probably at late freeze period, like hard/full-freeze). I would suggest to stick to versions fixing CVEs for now. If there is a no-CVE releases between the last update and the start of the hard freeze, we can revisit a final update and rebuild of the golang-world. Cheers > > The package currently FTBFS on i386/experimental but it won't be problem on > unstable. > The dep-resolver (aspcud) in experimental chooses gccgo to bootstrap, > which has a bug https://github.com/golang/go/issues/51850. > But on unstable the dep-resolver is apt, and will choose old golang-go to > bootstrap. > > unblock golang-1.19/1.19.6-2 > diff -Nru golang-1.19-1.19.5/debian/changelog > golang-1.19-1.19.6/debian/changelog > --- golang-1.19-1.19.5/debian/changelog 2023-01-11 15:35:00.000000000 > +0800 > +++ golang-1.19-1.19.6/debian/changelog 2023-02-15 10:09:02.000000000 > +0800 > @@ -1,3 +1,16 @@ > +golang-1.19 (1.19.6-1) experimental; urgency=medium > + > + * Team upload > + * New upstream version 1.19.6 > + + CVE-2022-41722: path/filepath: path traversal in filepath.Clean on > + Windows > + + CVE-2022-41725: net/http, mime/multipart: denial of service from > + excessive resource consumption > + + CVE-2022-41724: crypto/tls: large handshake records may cause panics > + + CVE-2022-41723: net/http: avoid quadratic complexity in HPACK decoding > + > + -- Shengjing Zhu <z...@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