commit a2cbd465e14cc67f7bc94e652e1a5e9af7fab76e Author: Adrian Schröter Date: Wed Jan 24 09:20:10 2024 +0100 Sync from SUSE:ALP:Source:Standard:1.0 go1.18-openssl revision 7180eba8e4043a58324d5c6f50150a19 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fecc750 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/README.SUSE b/README.SUSE new file mode 100644 index 0000000..1f8a426 --- /dev/null +++ b/README.SUSE @@ -0,0 +1,120 @@ +Updated: 05.05.2012 +Authors: Graham Anderson, + + +PROJECT DETAILS +--------------- + +OBS: https://build.opensuse.org/project/show?project=devel:languages:go + +Maintainers: Sascha Peilicke (saschpe), + Graham Anderson (andtecheu) + +Wiki: http://en.opensuse.org/Go + http://en.opensuse.org/openSUSE:Packaging_Go + + +GENERAL NOTES +------------- + +Go toolchain environmental variables are configured via go.sh, which is +installed to /etc/profile.d/go.sh + +Packaging guidelines and an RPM spec file recipe for packaging third party Go +libraries can be found on the openSUSE wiki: + + http://en.opensuse.org/openSUSE:Packaging_Go + +The openSUSE go package uses the standard Go distribution toolchain, with a +a small patchset to modify a few of the toolchain commands to suit our +environment and packaging needs. + +This means that many of the standard go toolchain commands are not inside a +users PATH, but rather are invoked and used via the "go" command. Should you +wish to script or manually use the commands, the install location on a 64 bit +system is /usr/lib64/go/pkg/tool/linux_amd64 + +The "go" tool, the "godoc" document server are inside a users PATH. + +We currently don't support the gccgo implementation, this is not for +any other reason than contributer and maintainer time constraints. + + +GO DOCUMENTATION +---------------- + +As of yet, there are no man pages for the standard Go distribution toolchain, +please see the documentation provided by the "godoc" command. Man pages are +slated to be included in the release in future. + +One of the diffs from the maintained patchset adds the distro specific doc and +source file locations of the *-doc RPM packages to the virtual filesystem of +the "godoc" documentation server. That is to say, as long as packages follow +the Go packaging guidelines, API and other documentation should always be +available via the godoc server if the packages "doc" RPM is installed. + + +PACKAGE INSTALL LOCATIONS +------------------------- + +Go standard library packages are installed to a location in $GOROOT, which is +defined as /usr/lib64/go on 64bit systems. + +Third party package binaries are installed to the default system wide +$GOPATH entry. On 64bit systems the location /usr/lib64/go/contrib is used. +This is specified in the macros.go RPM macro definition file that is part of +the main Go package and is used for packaging most third party Go libraries. + +The reasons binary packages are installed to a GOPATH entry instead of GOROOT +are mainly to do with how the Go toolchain prioritises and behaves with +packages installed to the same location as the Go std library. + +By installing third party packages to a system-wide GOPATH entry location, +we can ensure that no packages clobber the standard library namespace or file +tree. Additionally we can support binary only packages, which as of Go 1.1 +will only be supported outside of the $GOROOT. + +There are additional benefits to this location; such as allowing users and +developers to prioritise linking from their own user defined GOPATH, which +defaults to $HOME/go configured via /etc/profile.d/go.sh config. This has +particular benefit for development workflows. + +For Go 1.1 and beyond, building and linking with binary only pacakges will +only be supported with the following caveat. Package source code must not +exist in the same GOPATH segment as the binary package .a archive file. + +If both the binary archive (.a) and the package source are installed to the +same GOPATH segment, then the "go build" or "go install" command will +prioritise building the software using package sources before using package +binary archives. A side effect of this is that is actually possible to have +source code only third party packages. + +To summarise the priority of binary package linking and building: + + 1. Any source files or binary packages in $GOROOT are considered first. Any + binary packages in $GOROOT that are considered "stale" by the build tools + are ignored in favour of the package source. + + 2. $GOPATH is considered next for import statements. GOPATH is a colon + delimited list of paths. GOPATH segments are examined by the build tools + in a FIFO manner, left to right. + + Both a system wide and a user GOPATH segment are configured by default, + the user GOPATH segment takes priority over the system segment to allow + flexibility for development workflows. + + The default user GOPATH is: + + GOPATH=$HOME/go:$GOROOT/contrib + + The default root user GOPATH is: + + GOPATH=$GOROOT/contrib + + 3. For Go < 1.1, If both the source and binary archive is available for a + package import in the same GOPATH segment, the binary archive will take + precedence and will be linked during compilation. + + For Go >= 1.1 If the package source is avaiable in the GOPATH segment, it + will always be used in preference to the binary + diff --git a/_constraints b/_constraints new file mode 100644 index 0000000..67b6111 --- /dev/null +++ b/_constraints @@ -0,0 +1,7 @@ + + + + 5 + + + diff --git a/_service b/_service new file mode 100644 index 0000000..505a75d --- /dev/null +++ b/_service @@ -0,0 +1,18 @@ + + + https://github.com/golang-fips/go.git + git + .git + go1.18.10-1-openssl-fips + @PARENT_TAG@ + enable + go([0-9\.]+)-([0-9])-openssl-fips + \1.\2 + + + + + go*.tar + gz + + diff --git a/_servicedata b/_servicedata new file mode 100644 index 0000000..adc671a --- /dev/null +++ b/_servicedata @@ -0,0 +1,4 @@ + + + https://github.com/golang-fips/go.git + 7311cdf4f66997a4903d88fccab241b9b1306678 \ No newline at end of file diff --git a/bsc1208491-41724.patch b/bsc1208491-41724.patch new file mode 100644 index 0000000..939de23 --- /dev/null +++ b/bsc1208491-41724.patch @@ -0,0 +1,2392 @@ +From 00b256e9e3c0fa02a278ec9dfc3e191e02ceaf80 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Wed, 14 Dec 2022 09:43:16 -0800 +Subject: [PATCH] [release-branch.go1.19] crypto/tls: replace all usages of + BytesOrPanic + +Message marshalling makes use of BytesOrPanic a lot, under the +assumption that it will never panic. This assumption was incorrect, and +specifically crafted handshakes could trigger panics. Rather than just +surgically replacing the usages of BytesOrPanic in paths that could +panic, replace all usages of it with proper error returns in case there +are other ways of triggering panics which we didn't find. + +In one specific case, the tree routed by expandLabel, we replace the +usage of BytesOrPanic, but retain a panic. This function already +explicitly panicked elsewhere, and returning an error from it becomes +rather painful because it requires changing a large number of APIs. +The marshalling is unlikely to ever panic, as the inputs are all either +fixed length, or already limited to the sizes required. If it were to +panic, it'd likely only be during development. A close inspection shows +no paths for a user to cause a panic currently. + +This patches ends up being rather large, since it requires routing +errors back through functions which previously had no error returns. +Where possible I've tried to use helpers that reduce the verbosity +of frequently repeated stanzas, and to make the diffs as minimal as +possible. + +Thanks to Marten Seemann for reporting this issue. + +Updates #58001 +Fixes #58358 +Fixes CVE-2022-41724 + +Change-Id: Ieb55867ef0a3e1e867b33f09421932510cb58851 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1679436 +Reviewed-by: Julie Qiu +TryBot-Result: Security TryBots +Run-TryBot: Roland Shoemaker +Reviewed-by: Damien Neil +(cherry picked from commit 0f3a44ad7b41cc89efdfad25278953e17d9c1e04) +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728204 +Reviewed-by: Tatiana Bradley +Reviewed-on: https://go-review.googlesource.com/c/go/+/468117 +Auto-Submit: Michael Pratt +Run-TryBot: Michael Pratt +TryBot-Result: Gopher Robot +Reviewed-by: Than McIntosh +--- + src/crypto/tls/boring_test.go | 2 +- + src/crypto/tls/common.go | 2 +- + src/crypto/tls/conn.go | 46 +- + src/crypto/tls/handshake_client.go | 95 +-- + src/crypto/tls/handshake_client_test.go | 4 +- + src/crypto/tls/handshake_client_tls13.go | 74 ++- + src/crypto/tls/handshake_messages.go | 716 +++++++++++----------- + src/crypto/tls/handshake_messages_test.go | 19 +- + src/crypto/tls/handshake_server.go | 73 ++- + src/crypto/tls/handshake_server_test.go | 31 +- + src/crypto/tls/handshake_server_tls13.go | 71 ++- + src/crypto/tls/key_schedule.go | 19 +- + src/crypto/tls/ticket.go | 8 +- + 13 files changed, 657 insertions(+), 503 deletions(-) + +Index: go/src/crypto/tls/common.go +=================================================================== +--- go.orig/src/crypto/tls/common.go ++++ go/src/crypto/tls/common.go +@@ -1379,7 +1379,7 @@ func (c *Certificate) leaf() (*x509.Cert + } + + type handshakeMessage interface { +- marshal() []byte ++ marshal() ([]byte, error) + unmarshal([]byte) bool + } + +Index: go/src/crypto/tls/conn.go +=================================================================== +--- go.orig/src/crypto/tls/conn.go ++++ go/src/crypto/tls/conn.go +@@ -1001,18 +1001,37 @@ func (c *Conn) writeRecordLocked(typ rec + 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 +@@ -1091,6 +1110,11 @@ func (c *Conn) readHandshake() (any, err + if !m.unmarshal(data) { + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } ++ ++ if transcript != nil { ++ transcript.Write(data) ++ } ++ + return m, nil + } + +@@ -1166,7 +1190,7 @@ func (c *Conn) handleRenegotiation() err + return errors.New("tls: internal error: unexpected renegotiation") + } + +- msg, err := c.readHandshake() ++ msg, err := c.readHandshake(nil) + if err != nil { + return err + } +@@ -1212,7 +1236,7 @@ func (c *Conn) handlePostHandshakeMessag + return c.handleRenegotiation() + } + +- msg, err := c.readHandshake() ++ msg, err := c.readHandshake(nil) + if err != nil { + return err + } +@@ -1248,7 +1272,11 @@ func (c *Conn) handleKeyUpdate(keyUpdate + 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) +Index: go/src/crypto/tls/handshake_client.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_client.go ++++ go/src/crypto/tls/handshake_client.go +@@ -157,7 +157,10 @@ func (c *Conn) clientHandshake(ctx conte + } + 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 +@@ -172,11 +175,12 @@ func (c *Conn) clientHandshake(ctx conte + }() + } + +- 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 + } +@@ -241,9 +245,9 @@ func (c *Conn) clientHandshake(ctx conte + } + + 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 +@@ -258,14 +262,14 @@ func (c *Conn) loadSession(hello *client + // 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. +@@ -277,7 +281,7 @@ func (c *Conn) loadSession(hello *client + } + } + 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 +@@ -286,16 +290,16 @@ func (c *Conn) loadSession(hello *client + 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 + } + } + +@@ -303,7 +307,7 @@ func (c *Conn) loadSession(hello *client + // 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 +@@ -313,14 +317,14 @@ func (c *Conn) loadSession(hello *client + // 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 { +@@ -331,7 +335,7 @@ func (c *Conn) loadSession(hello *client + } + } + 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. +@@ -349,9 +353,15 @@ func (c *Conn) loadSession(hello *client + 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 + } +@@ -396,8 +406,12 @@ func (hs *clientHandshakeState) handshak + 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 +@@ -468,7 +482,7 @@ func (hs *clientHandshakeState) pickCiph + func (hs *clientHandshakeState) doFullHandshake() error { + c := hs.c + +- msg, err := c.readHandshake() ++ msg, err := c.readHandshake(&hs.finishedHash) + if err != nil { + return err + } +@@ -477,9 +491,8 @@ func (hs *clientHandshakeState) doFullHa + 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 + } +@@ -497,11 +510,10 @@ func (hs *clientHandshakeState) doFullHa + 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 + } +@@ -530,14 +542,13 @@ func (hs *clientHandshakeState) doFullHa + + 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 + } +@@ -548,7 +559,6 @@ func (hs *clientHandshakeState) doFullHa + 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 { +@@ -556,7 +566,7 @@ func (hs *clientHandshakeState) doFullHa + return err + } + +- msg, err = c.readHandshake() ++ msg, err = c.readHandshake(&hs.finishedHash) + if err != nil { + return err + } +@@ -567,7 +577,6 @@ func (hs *clientHandshakeState) doFullHa + 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 +@@ -575,8 +584,7 @@ func (hs *clientHandshakeState) doFullHa + 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 + } + } +@@ -587,8 +595,7 @@ func (hs *clientHandshakeState) doFullHa + 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 + } + } +@@ -635,8 +642,7 @@ func (hs *clientHandshakeState) doFullHa + 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 + } + } +@@ -771,7 +777,10 @@ func (hs *clientHandshakeState) readFini + 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 + } +@@ -787,7 +796,11 @@ func (hs *clientHandshakeState) readFini + 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 + } +@@ -798,7 +811,7 @@ func (hs *clientHandshakeState) readSess + } + + c := hs.c +- msg, err := c.readHandshake() ++ msg, err := c.readHandshake(&hs.finishedHash) + if err != nil { + return err + } +@@ -807,7 +820,6 @@ func (hs *clientHandshakeState) readSess + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(sessionTicketMsg, msg) + } +- hs.finishedHash.Write(sessionTicketMsg.marshal()) + + hs.session = &ClientSessionState{ + sessionTicket: sessionTicketMsg.ticket, +@@ -827,14 +839,13 @@ func (hs *clientHandshakeState) readSess + 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) +Index: go/src/crypto/tls/handshake_client_test.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_client_test.go ++++ go/src/crypto/tls/handshake_client_test.go +@@ -1257,7 +1257,7 @@ func TestServerSelectingUnconfiguredAppl + 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 @@ func TestServerSelectingUnconfiguredCiph + random: make([]byte, 32), + cipherSuite: TLS_RSA_WITH_AES_256_GCM_SHA384, + } +- serverHelloBytes := serverHello.marshal() ++ serverHelloBytes := mustMarshal(t, serverHello) + + s.Write([]byte{ + byte(recordTypeHandshake), +Index: go/src/crypto/tls/handshake_client_tls13.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_client_tls13.go ++++ go/src/crypto/tls/handshake_client_tls13.go +@@ -58,7 +58,10 @@ func (hs *clientHandshakeStateTLS13) han + } + + 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 { +@@ -69,7 +72,9 @@ func (hs *clientHandshakeStateTLS13) han + } + } + +- 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 { +@@ -168,8 +173,7 @@ func (hs *clientHandshakeStateTLS13) sen + } + 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 +@@ -184,7 +188,9 @@ func (hs *clientHandshakeStateTLS13) pro + 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 +@@ -249,10 +255,18 @@ func (hs *clientHandshakeStateTLS13) pro + 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 +@@ -260,12 +274,12 @@ func (hs *clientHandshakeStateTLS13) pro + } + } + +- 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 + } +@@ -354,6 +368,7 @@ func (hs *clientHandshakeStateTLS13) est + if !hs.usingPSK { + earlySecret = hs.suite.extract(nil, nil) + } ++ + handshakeSecret := hs.suite.extract(sharedKey, + hs.suite.deriveSecret(earlySecret, "derived", nil)) + +@@ -384,7 +399,7 @@ func (hs *clientHandshakeStateTLS13) est + func (hs *clientHandshakeStateTLS13) readServerParameters() error { + c := hs.c + +- msg, err := c.readHandshake() ++ msg, err := c.readHandshake(hs.transcript) + if err != nil { + return err + } +@@ -394,7 +409,6 @@ func (hs *clientHandshakeStateTLS13) rea + 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) +@@ -423,18 +437,16 @@ func (hs *clientHandshakeStateTLS13) rea + 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 + } +@@ -449,7 +461,6 @@ func (hs *clientHandshakeStateTLS13) rea + 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 +@@ -458,7 +469,10 @@ func (hs *clientHandshakeStateTLS13) rea + 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 + } +@@ -489,7 +503,9 @@ func (hs *clientHandshakeStateTLS13) rea + 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 + } +@@ -497,7 +513,10 @@ func (hs *clientHandshakeStateTLS13) rea + 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 + } +@@ -514,7 +533,9 @@ func (hs *clientHandshakeStateTLS13) rea + 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. + +@@ -563,8 +584,7 @@ func (hs *clientHandshakeStateTLS13) sen + 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 + } + +@@ -601,8 +621,7 @@ func (hs *clientHandshakeStateTLS13) sen + } + 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 + } + +@@ -616,8 +635,7 @@ func (hs *clientHandshakeStateTLS13) sen + 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 + } + +Index: go/src/crypto/tls/handshake_messages.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_messages.go ++++ go/src/crypto/tls/handshake_messages.go +@@ -5,6 +5,7 @@ + package tls + + import ( ++ "errors" + "fmt" + "strings" + +@@ -94,9 +95,181 @@ type clientHelloMsg struct { + 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 @@ func (m *clientHelloMsg) marshal() []byt + 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 @@ func (m *clientHelloMsg) updateBinders(p + } + }) + 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 { +@@ -612,9 +621,98 @@ type serverHelloMsg struct { + 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 +@@ -628,104 +726,15 @@ func (m *serverHelloMsg) marshal() []byt + 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 { +@@ -843,9 +852,9 @@ type encryptedExtensionsMsg struct { + 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 +@@ -865,8 +874,9 @@ func (m *encryptedExtensionsMsg) marshal + }) + }) + +- 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 { +@@ -914,10 +924,10 @@ func (m *encryptedExtensionsMsg) unmarsh + + 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 { +@@ -929,9 +939,9 @@ type keyUpdateMsg struct { + 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 +@@ -944,8 +954,9 @@ func (m *keyUpdateMsg) marshal() []byte + } + }) + +- 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 { +@@ -977,9 +988,9 @@ type newSessionTicketMsgTLS13 struct { + 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 +@@ -1004,8 +1015,9 @@ func (m *newSessionTicketMsgTLS13) marsh + }) + }) + +- 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 { +@@ -1058,9 +1070,9 @@ type certificateRequestMsgTLS13 struct { + 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 +@@ -1119,8 +1131,9 @@ func (m *certificateRequestMsgTLS13) mar + }) + }) + +- 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 { +@@ -1204,9 +1217,9 @@ type certificateMsg struct { + 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 +@@ -1215,7 +1228,7 @@ func (m *certificateMsg) marshal() (x [] + } + + 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) +@@ -1236,7 +1249,7 @@ func (m *certificateMsg) marshal() (x [] + } + + m.raw = x +- return ++ return m.raw, nil + } + + func (m *certificateMsg) unmarshal(data []byte) bool { +@@ -1283,9 +1296,9 @@ type certificateMsgTLS13 struct { + 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 +@@ -1303,8 +1316,9 @@ func (m *certificateMsgTLS13) marshal() + 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) { +@@ -1427,9 +1441,9 @@ type serverKeyExchangeMsg struct { + 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) +@@ -1440,7 +1454,7 @@ func (m *serverKeyExchangeMsg) marshal() + copy(x[4:], m.key) + + m.raw = x +- return x ++ return x, nil + } + + func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool { +@@ -1457,9 +1471,9 @@ type certificateStatusMsg struct { + 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 +@@ -1471,8 +1485,9 @@ func (m *certificateStatusMsg) marshal() + }) + }) + +- 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 { +@@ -1491,10 +1506,10 @@ func (m *certificateStatusMsg) unmarshal + + 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 { +@@ -1506,9 +1521,9 @@ type clientKeyExchangeMsg struct { + 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) +@@ -1519,7 +1534,7 @@ func (m *clientKeyExchangeMsg) marshal() + copy(x[4:], m.ciphertext) + + m.raw = x +- return x ++ return x, nil + } + + func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool { +@@ -1540,9 +1555,9 @@ type finishedMsg struct { + 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 +@@ -1551,8 +1566,9 @@ func (m *finishedMsg) marshal() []byte { + 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 { +@@ -1574,9 +1590,9 @@ type certificateRequestMsg struct { + 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. +@@ -1591,7 +1607,7 @@ func (m *certificateRequestMsg) marshal( + 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) +@@ -1626,7 +1642,7 @@ func (m *certificateRequestMsg) marshal( + } + + m.raw = x +- return ++ return m.raw, nil + } + + func (m *certificateRequestMsg) unmarshal(data []byte) bool { +@@ -1712,9 +1728,9 @@ type certificateVerifyMsg struct { + 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 +@@ -1728,8 +1744,9 @@ func (m *certificateVerifyMsg) marshal() + }) + }) + +- 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 { +@@ -1752,15 +1769,15 @@ type newSessionTicketMsg struct { + 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) +@@ -1771,7 +1788,7 @@ func (m *newSessionTicketMsg) marshal() + + m.raw = x + +- return ++ return m.raw, nil + } + + func (m *newSessionTicketMsg) unmarshal(data []byte) bool { +@@ -1799,10 +1816,25 @@ func (m *newSessionTicketMsg) unmarshal( + 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 ++} +Index: go/src/crypto/tls/handshake_messages_test.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_messages_test.go ++++ go/src/crypto/tls/handshake_messages_test.go +@@ -37,6 +37,15 @@ var tests = []any{ + &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())) + +@@ -55,7 +64,7 @@ func TestMarshalUnmarshal(t *testing.T) + } + + 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) +@@ -408,12 +417,12 @@ func TestRejectEmptySCTList(t *testing.T + + 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) { +@@ -451,12 +460,12 @@ func TestRejectEmptySCT(t *testing.T) { + // 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) { +Index: go/src/crypto/tls/handshake_server.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_server.go ++++ go/src/crypto/tls/handshake_server.go +@@ -129,7 +129,9 @@ func (hs *serverHandshakeState) handshak + + // 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 @@ func (hs *serverHandshakeState) doResume + 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 @@ func (hs *serverHandshakeState) doFullHa + // 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 @@ func (hs *serverHandshakeState) doFullHa + 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 @@ func (hs *serverHandshakeState) doFullHa + 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 @@ func (hs *serverHandshakeState) doFullHa + + 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 @@ func (hs *serverHandshakeState) doFullHa + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } +- hs.finishedHash.Write(certMsg.marshal()) + + if err := c.processCertsFromClient(Certificate{ + Certificate: certMsg.certificates, +@@ -601,7 +599,7 @@ func (hs *serverHandshakeState) doFullHa + pub = c.peerCertificates[0].PublicKey + } + +- msg, err = c.readHandshake() ++ msg, err = c.readHandshake(&hs.finishedHash) + if err != nil { + return err + } +@@ -619,7 +617,6 @@ func (hs *serverHandshakeState) doFullHa + 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 @@ func (hs *serverHandshakeState) doFullHa + // 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 @@ func (hs *serverHandshakeState) doFullHa + 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 @@ func (hs *serverHandshakeState) readFini + 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 @@ func (hs *serverHandshakeState) readFini + 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 @@ func (hs *serverHandshakeState) sendSess + 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) sendSess + 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 + } + +Index: go/src/crypto/tls/handshake_server_test.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_server_test.go ++++ go/src/crypto/tls/handshake_server_test.go +@@ -30,6 +30,13 @@ func testClientHello(t *testing.T, serve + 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 @@ func testClientHelloFailure(t *testing.T + 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 @@ func TestRenegotiationExtension(t *testi + 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 @@ func TestTLS12OnlyCipherSuites(t *testin + 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 @@ func TestTLSPointFormats(t *testing.T) { + 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 +@@ -1436,7 +1451,9 @@ func TestSNIGivenOnFailure(t *testing.T) + 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) +Index: go/src/crypto/tls/handshake_server_tls13.go +=================================================================== +--- go.orig/src/crypto/tls/handshake_server_tls13.go ++++ go/src/crypto/tls/handshake_server_tls13.go +@@ -298,7 +298,12 @@ func (hs *serverHandshakeStateTLS13) che + 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) +@@ -389,8 +394,7 @@ func (hs *serverHandshakeStateTLS13) sen + } + hs.sentDummyCCS = true + +- _, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) +- return err ++ return hs.c.writeChangeCipherRecord() + } + + func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error { +@@ -398,7 +402,9 @@ func (hs *serverHandshakeStateTLS13) doH + + // 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))}) +@@ -414,8 +420,7 @@ func (hs *serverHandshakeStateTLS13) doH + 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 + } + +@@ -423,7 +428,8 @@ func (hs *serverHandshakeStateTLS13) doH + return err + } + +- msg, err := c.readHandshake() ++ // clientHelloMsg is not included in the transcript. ++ msg, err := c.readHandshake(nil) + if err != nil { + return err + } +@@ -514,9 +520,10 @@ func illegalClientHelloChange(ch, ch1 *c + 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 + } + +@@ -559,8 +566,7 @@ func (hs *serverHandshakeStateTLS13) sen + 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 + } + +@@ -589,8 +595,7 @@ func (hs *serverHandshakeStateTLS13) sen + 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 + } + } +@@ -601,8 +606,7 @@ func (hs *serverHandshakeStateTLS13) sen + 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 + } + +@@ -633,8 +637,7 @@ func (hs *serverHandshakeStateTLS13) sen + } + 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 + } + +@@ -648,8 +651,7 @@ func (hs *serverHandshakeStateTLS13) sen + 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 + } + +@@ -710,7 +712,9 @@ func (hs *serverHandshakeStateTLS13) sen + 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 +@@ -735,8 +739,12 @@ func (hs *serverHandshakeStateTLS13) sen + 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 + } +@@ -755,7 +763,7 @@ func (hs *serverHandshakeStateTLS13) sen + // 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 + } + +@@ -780,7 +788,7 @@ func (hs *serverHandshakeStateTLS13) rea + // 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 + } +@@ -790,7 +798,6 @@ func (hs *serverHandshakeStateTLS13) rea + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } +- hs.transcript.Write(certMsg.marshal()) + + if err := c.processCertsFromClient(certMsg.certificate); err != nil { + return err +@@ -804,7 +811,10 @@ func (hs *serverHandshakeStateTLS13) rea + } + + 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 + } +@@ -835,7 +845,9 @@ func (hs *serverHandshakeStateTLS13) rea + 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 +@@ -850,7 +862,8 @@ func (hs *serverHandshakeStateTLS13) rea + 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 + } +Index: go/src/crypto/tls/key_schedule.go +=================================================================== +--- go.orig/src/crypto/tls/key_schedule.go ++++ go/src/crypto/tls/key_schedule.go +@@ -8,6 +8,7 @@ import ( + "crypto/elliptic" + "crypto/hmac" + "errors" ++ "fmt" + "hash" + "io" + "math/big" +@@ -42,8 +43,24 @@ func (c *cipherSuiteTLS13) expandLabel(s + 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") + } +Index: go/src/crypto/tls/ticket.go +=================================================================== +--- go.orig/src/crypto/tls/ticket.go ++++ go/src/crypto/tls/ticket.go +@@ -32,7 +32,7 @@ type sessionState struct { + 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 @@ func (m *sessionState) marshal() []byte + }) + } + }) +- return b.BytesOrPanic() ++ return b.Bytes() + } + + func (m *sessionState) unmarshal(data []byte) bool { +@@ -86,7 +86,7 @@ type sessionStateTLS13 struct { + 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 @@ func (m *sessionStateTLS13) marshal() [] + b.AddBytes(m.resumptionSecret) + }) + marshalCertificate(&b, m.certificate) +- return b.BytesOrPanic() ++ return b.Bytes() + } + + func (m *sessionStateTLS13) unmarshal(data []byte) bool { diff --git a/bsc1208491-41725.patch b/bsc1208491-41725.patch new file mode 100644 index 0000000..3014749 --- /dev/null +++ b/bsc1208491-41725.patch @@ -0,0 +1,641 @@ +From 5c55ac9bf1e5f779220294c843526536605f42ab Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Wed, 25 Jan 2023 09:27:01 -0800 +Subject: [PATCH] [release-branch.go1.19] mime/multipart: limit memory/inode + consumption of ReadForm + +Reader.ReadForm is documented as storing "up to maxMemory bytes + 10MB" +in memory. Parsed forms can consume substantially more memory than +this limit, since ReadForm does not account for map entry overhead +and MIME headers. + +In addition, while the amount of disk memory consumed by ReadForm can +be constrained by limiting the size of the parsed input, ReadForm will +create one temporary file per form part stored on disk, potentially +consuming a large number of inodes. + +Update ReadForm's memory accounting to include part names, +MIME headers, and map entry overhead. + +Update ReadForm to store all on-disk file parts in a single +temporary file. + +Files returned by FileHeader.Open are documented as having a concrete +type of *os.File when a file is stored on disk. The change to use a +single temporary file for all parts means that this is no longer the +case when a form contains more than a single file part stored on disk. + +The previous behavior of storing each file part in a separate disk +file may be reenabled with GODEBUG=multipartfiles=distinct. + +Update Reader.NextPart and Reader.NextRawPart to set a 10MiB cap +on the size of MIME headers. + +Thanks to Jakob Ackermann (@das7pad) for reporting this issue. + +Updates #58006 +Fixes #58362 +Fixes CVE-2022-41725 + +Change-Id: Ibd780a6c4c83ac8bcfd3cbe344f042e9940f2eab +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1714276 +Reviewed-by: Julie Qiu +TryBot-Result: Security TryBots +Reviewed-by: Roland Shoemaker +Run-TryBot: Damien Neil +(cherry picked from commit ed4664330edcd91b24914c9371c377c132dbce8c) +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728949 +Reviewed-by: Tatiana Bradley +Run-TryBot: Roland Shoemaker +Reviewed-by: Damien Neil +Reviewed-on: https://go-review.googlesource.com/c/go/+/468116 +TryBot-Result: Gopher Robot +Reviewed-by: Than McIntosh +Run-TryBot: Michael Pratt +Auto-Submit: Michael Pratt +--- + src/mime/multipart/formdata.go | 132 ++++++++++++++++++++----- + src/mime/multipart/formdata_test.go | 140 ++++++++++++++++++++++++++- + src/mime/multipart/multipart.go | 25 +++-- + src/mime/multipart/readmimeheader.go | 14 +++ + src/net/http/request_test.go | 2 +- + src/net/textproto/reader.go | 20 +++- + 6 files changed, 295 insertions(+), 38 deletions(-) + create mode 100644 src/mime/multipart/readmimeheader.go + +Index: go/src/mime/multipart/formdata.go +=================================================================== +--- go.orig/src/mime/multipart/formdata.go ++++ go/src/mime/multipart/formdata.go +@@ -7,6 +7,7 @@ package multipart + import ( + "bytes" + "errors" ++ "internal/godebug" + "io" + "math" + "net/textproto" +@@ -33,23 +34,58 @@ func (r *Reader) ReadForm(maxMemory int6 + + 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 @@ func (r *Reader) readForm(maxMemory int6 + } + 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 @@ func (r *Reader) readForm(maxMemory int6 + } + + // 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 @@ func (r *Reader) readForm(maxMemory int6 + 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 @@ func (f *Form) RemoveAll() error { + 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 @@ type FileHeader struct { + 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 File interface { + + type sectionReadCloser struct { + *io.SectionReader ++ io.Closer + } + + func (rc sectionReadCloser) Close() error { ++ if rc.Closer != nil { ++ return rc.Closer.Close() ++ } + return nil + } +Index: go/src/mime/multipart/formdata_test.go +=================================================================== +--- go.orig/src/mime/multipart/formdata_test.go ++++ go/src/mime/multipart/formdata_test.go +@@ -6,8 +6,10 @@ package multipart + + import ( + "bytes" ++ "fmt" + "io" + "math" ++ "net/textproto" + "os" + "strings" + "testing" +@@ -208,8 +210,8 @@ Content-Disposition: form-data; name="la + 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 @@ Content-Disposition: form-data; name="la + 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 @@ Content-Disposition: form-data; name="la + }) + } + } ++ ++// 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)) ++ } ++} +Index: go/src/mime/multipart/multipart.go +=================================================================== +--- go.orig/src/mime/multipart/multipart.go ++++ go/src/mime/multipart/multipart.go +@@ -128,12 +128,12 @@ func (r *stickyErrorReader) Read(p []byt + 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,11 +149,15 @@ func newPart(mr *Reader, rawPart bool) ( + return bp, nil + } + +-func (bp *Part) populateHeaders() error { +- r := textproto.NewReader(bp.mr.bufReader) +- header, err := r.ReadMIMEHeader() ++func (p *Part) populateHeaders(maxMIMEHeaderSize int64) error { ++ r := textproto.NewReader(p.mr.bufReader) ++ header, err := readMIMEHeader(r, maxMIMEHeaderSize) + if err == nil { +- bp.Header = header ++ p.Header = header ++ } ++ // TODO: Add a distinguishable error to net/textproto. ++ if err != nil && err.Error() == "message too large" { ++ err = ErrMessageTooLarge + } + return err + } +@@ -294,6 +298,7 @@ func (p *Part) Close() error { + // isn't supported. + type Reader struct { + bufReader *bufio.Reader ++ tempDir string // used in tests + + currentPart *Part + partsRead int +@@ -304,6 +309,10 @@ type Reader struct { + 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. + // +@@ -311,7 +320,7 @@ type Reader struct { + // 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. +@@ -320,10 +329,10 @@ func (r *Reader) NextPart() (*Part, erro + // 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() + } +@@ -348,7 +357,7 @@ func (r *Reader) nextPart(rawPart bool) + + if r.isBoundaryDelimiterLine(line) { + r.partsRead++ +- bp, err := newPart(r, rawPart) ++ bp, err := newPart(r, rawPart, maxMIMEHeaderSize) + if err != nil { + return nil, err + } +Index: go/src/mime/multipart/readmimeheader.go +=================================================================== +--- /dev/null ++++ go/src/mime/multipart/readmimeheader.go +@@ -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) +Index: go/src/net/http/request_test.go +=================================================================== +--- go.orig/src/net/http/request_test.go ++++ go/src/net/http/request_test.go +@@ -1116,7 +1116,7 @@ func testMissingFile(t *testing.T, req * + 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) +Index: go/src/net/textproto/reader.go +=================================================================== +--- go.orig/src/net/textproto/reader.go ++++ go/src/net/textproto/reader.go +@@ -7,8 +7,10 @@ package textproto + import ( + "bufio" + "bytes" ++ "errors" + "fmt" + "io" ++ "math" + "strconv" + "strings" + "sync" +@@ -483,6 +485,12 @@ var colon = []byte(":") + // } + // + 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. +@@ -524,9 +532,19 @@ func (r *Reader) ReadMIMEHeader() (MIMEH + } + + // 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 --git a/bsc1208491.patch b/bsc1208491.patch new file mode 100644 index 0000000..a048195 --- /dev/null +++ b/bsc1208491.patch @@ -0,0 +1,165 @@ +From 5c3e11bd0b5c0a86e5beffcd4339b86a902b21c3 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Mon, 6 Feb 2023 10:03:44 -0800 +Subject: [PATCH] [release-branch.go1.19] net/http: update bundled + golang.org/x/net/http2 + +Disable cmd/internal/moddeps test, since this update includes PRIVATE +track fixes. + +Fixes CVE-2022-41723 +Fixes #58355 +Updates #57855 + +Change-Id: Ie870562a6f6e44e4e8f57db6a0dde1a41a2b090c +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728939 +Reviewed-by: Damien Neil +Reviewed-by: Julie Qiu +Reviewed-by: Tatiana Bradley +Run-TryBot: Roland Shoemaker +Reviewed-on: https://go-review.googlesource.com/c/go/+/468118 +TryBot-Result: Gopher Robot +Run-TryBot: Michael Pratt +Auto-Submit: Michael Pratt +Reviewed-by: Than McIntosh +--- + src/cmd/internal/moddeps/moddeps_test.go | 2 +- + .../golang.org/x/net/http2/hpack/hpack.go | 79 ++++++++++++------- + 2 files changed, 50 insertions(+), 31 deletions(-) + +Index: go/src/cmd/internal/moddeps/moddeps_test.go +=================================================================== +--- go.orig/src/cmd/internal/moddeps/moddeps_test.go ++++ go/src/cmd/internal/moddeps/moddeps_test.go +@@ -34,7 +34,7 @@ import ( + // See issues 36852, 41409, and 43687. + // (Also see golang.org/issue/27348.) + func TestAllDependencies(t *testing.T) { +- t.Skip("TODO(#57008): 1.18.9 contains unreleased changes from vendored modules") ++ t.Skip("TODO(#58355): 1.18.9 contains unreleased changes from vendored modules") + + goBin := testenv.GoToolPath(t) + +Index: go/src/vendor/golang.org/x/net/http2/hpack/hpack.go +=================================================================== +--- go.orig/src/vendor/golang.org/x/net/http2/hpack/hpack.go ++++ go/src/vendor/golang.org/x/net/http2/hpack/hpack.go +@@ -359,6 +359,7 @@ func (d *Decoder) parseFieldLiteral(n ui + + 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 @@ func (d *Decoder) parseFieldLiteral(n ui + } + 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 @@ func readVarInt(n byte, p []byte) (i uin + 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 --git a/dont-force-gold-on-arm64.patch b/dont-force-gold-on-arm64.patch new file mode 100644 index 0000000..b40684d --- /dev/null +++ b/dont-force-gold-on-arm64.patch @@ -0,0 +1,33 @@ +--- go/src/cmd/link/internal/ld/lib.go ++++ go/src/cmd/link/internal/ld/lib.go +@@ -1391,30 +1391,6 @@ + // Use lld to avoid errors from default linker (issue #38838) + altLinker = "lld" + } +- +- if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) && buildcfg.GOOS == "linux" { +- // On ARM, the GNU linker will generate COPY relocations +- // even with -znocopyreloc set. +- // https://sourceware.org/bugzilla/show_bug.cgi?id=19962 +- // +- // On ARM64, the GNU linker will fail instead of +- // generating COPY relocations. +- // +- // In both cases, switch to gold. +- altLinker = "gold" +- +- // If gold is not installed, gcc will silently switch +- // back to ld.bfd. So we parse the version information +- // and provide a useful error if gold is missing. +- name, args := flagExtld[0], flagExtld[1:] +- args = append(args, "-fuse-ld=gold", "-Wl,--version") +- cmd := exec.Command(name, args...) +- if out, err := cmd.CombinedOutput(); err == nil { +- if !bytes.Contains(out, []byte("GNU gold")) { +- log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out) +- } +- } +- } + } + if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" { + // Switch to ld.bfd on freebsd/arm64. diff --git a/gcc-go.patch b/gcc-go.patch new file mode 100644 index 0000000..86d501c --- /dev/null +++ b/gcc-go.patch @@ -0,0 +1,77 @@ +Index: go/src/cmd/dist/buildtool.go +=================================================================== +--- go.orig/src/cmd/dist/buildtool.go ++++ go/src/cmd/dist/buildtool.go +@@ -205,7 +205,7 @@ func bootstrapBuildTools() { + // only applies to the final cmd/go binary, but that's OK: if this is Go 1.10 + // or later we don't need to disable inlining to work around bugs in the Go 1.4 compiler. + cmd := []string{ +- pathf("%s/bin/go", goroot_bootstrap), ++ pathf("%s/bin/go-$gcc_go_version", goroot_bootstrap), + "install", + "-gcflags=-l", + "-tags=math_big_pure_go compiler_bootstrap", +Index: go/src/make.bash +=================================================================== +--- go.orig/src/make.bash ++++ go/src/make.bash +@@ -60,7 +60,7 @@ + # time goes when these scripts run. + # + # GOROOT_BOOTSTRAP: A working Go tree >= Go 1.4 for bootstrap. +-# If $GOROOT_BOOTSTRAP/bin/go is missing, $(go env GOROOT) is ++# If $GOROOT_BOOTSTRAP/bin/go-$gcc_go_version is missing, $(go env GOROOT) is + # tried for all "go" in $PATH. $HOME/go1.4 by default. + + set -e +@@ -176,8 +176,8 @@ + fi + fi + done; unset IFS +-if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then +- echo "ERROR: Cannot find $GOROOT_BOOTSTRAP/bin/go." >&2 ++if [ ! -x "$GOROOT_BOOTSTRAP/bin/go-$gcc_go_version" ]; then ++ echo "ERROR: Cannot find $GOROOT_BOOTSTRAP/bin/go-$gcc_go_version." >&2 + echo "Set \$GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4." >&2 + exit 1 + fi +@@ -195,7 +195,7 @@ + exit 1 + fi + rm -f cmd/dist/dist +-GOROOT="$GOROOT_BOOTSTRAP" GOOS="" GOARCH="" GO111MODULE=off "$GOROOT_BOOTSTRAP/bin/go" build -o cmd/dist/dist ./cmd/dist ++GOROOT="$GOROOT_BOOTSTRAP" GOOS="" GOARCH="" GO111MODULE=off "$GOROOT_BOOTSTRAP/bin/go-$gcc_go_version" build -o cmd/dist/dist ./cmd/dist + + # -e doesn't propagate out of eval, so check success by hand. + eval $(./cmd/dist/dist env -p || echo FAIL=true) +Index: go/src/make.rc +=================================================================== +--- go.orig/src/make.rc ++++ go/src/make.rc +@@ -60,7 +60,7 @@ if(! ~ $#GOROOT_BOOTSTRAP 1){ + GOROOT_BOOTSTRAP = $home/$d + } + for(p in $path){ +- if(! test -x $GOROOT_BOOTSTRAP/bin/go){ ++ if(! test -x $GOROOT_BOOTSTRAP/bin/go-$gcc_go_version){ + if(go_exe = `{path=$p whatis go}){ + goroot = `{GOROOT='' $go_exe env GOROOT} + if(! ~ $goroot $GOROOT){ +@@ -73,7 +73,7 @@ for(p in $path){ + } + } + } +-if(! test -x $GOROOT_BOOTSTRAP/bin/go){ ++if(! test -x $GOROOT_BOOTSTRAP/bin/go-$gcc_go_version){ + echo 'ERROR: Cannot find '$GOROOT_BOOTSTRAP'/bin/go.' >[1=2] + echo 'Set $GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4.' >[1=2] + exit bootstrap +@@ -87,7 +87,7 @@ if(~ $GOROOT_BOOTSTRAP $GOROOT){ + echo 'Building Go cmd/dist using '^$GOROOT_BOOTSTRAP + if(~ $#vflag 1) + echo cmd/dist +-GOROOT=$GOROOT_BOOTSTRAP GOOS='' GOARCH='' GO111MODULE=off $GOROOT_BOOTSTRAP/bin/go build -o cmd/dist/dist ./cmd/dist ++GOROOT=$GOROOT_BOOTSTRAP GOOS='' GOARCH='' GO111MODULE=off $GOROOT_BOOTSTRAP/bin/go-$gcc_go_version build -o cmd/dist/dist ./cmd/dist + + eval `{./cmd/dist/dist env -9} + if(~ $#vflag 1) diff --git a/go-rpmlintrc b/go-rpmlintrc new file mode 100644 index 0000000..39945d5 --- /dev/null +++ b/go-rpmlintrc @@ -0,0 +1,9 @@ +addFilter("binaryinfo-readelf-failed") # go binaries are suposedly ELF-compliant +addFilter("statically-linked-binary") # go doesn't yet support dynamic linking + +# .syso files are special. Note that while they are architecture-dependent, +# they are named to avoid conflicts (and we make sure of that in the RPM +# through go_arch). +addFilter("unstripped-binary-or-object.*\.syso$") +addFilter("arch-dependent-file-in-usr-share.*\.syso$") +addFilter("W: position-independent-executable-suggested") diff --git a/go.gdbinit b/go.gdbinit new file mode 100644 index 0000000..f9a266f --- /dev/null +++ b/go.gdbinit @@ -0,0 +1 @@ +add-auto-load-safe-path /usr/lib/go/$go_label/src/runtime/runtime-gdb.py diff --git a/go1.18-openssl.changes b/go1.18-openssl.changes new file mode 100644 index 0000000..eb0f868 --- /dev/null +++ b/go1.18-openssl.changes @@ -0,0 +1,774 @@ +------------------------------------------------------------------- +Fri Apr 14 23:41:22 UTC 2023 - Jeff Kowalczyk + +- Build subpackage go1.x-libstd compiled shared object libstd.so + only on Tumbleweed at this time. + Refs jsc#PED-1962 + +------------------------------------------------------------------- +Fri Apr 14 23:20:06 UTC 2023 - Jeff Kowalczyk + +- Add subpackage go1.x-libstd for compiled shared object libstd.so. + Refs jsc#PED-1962 + * Main go1.x package included libstd.so in previous versions + * Split libstd.so into subpackage that can be installed standalone + * Continues the slimming down of main go1.x package by 40 Mb + * Experimental and not recommended for general use, Go currently has no ABI + * Upstream Go has not committed to support buildmode=shared long-term + * Do not use in packaging, build static single binaries (the default) + * Upstream Go go1.x binary releases do not include libstd.so + * go1.x Suggests go1.x-libstd so not installed by default Recommends + * go1.x-libstd does not Require: go1.x so can install standalone + * Provides go-libstd unversioned package name + * Fix build step -buildmode=shared std to omit -linkshared +- Packaging improvements: + * go1.x Suggests go1.x-doc so not installed by default Recommends + * Use Group: Development/Languages/Go instead of Other + +------------------------------------------------------------------- +Fri Apr 14 23:06:51 UTC 2023 - Jeff Kowalczyk + +- Improvements to go1.x packaging spec: + * On Tumbleweed bootstrap with current default gcc13 and gccgo118 + * On SLE-12 aarch64 ppc64le ppc64 remove overrides to bootstrap + using go1.x package (%bcond_without gccgo). This is no longer + needed on current SLE-12:Update and removing will consolidate + the build configurations used. + * Change source URLs to go.dev as per Go upstream + * On x86_64 export GOAMD64=v1 as per the current baseline. + At this time forgo GOAMD64=v3 option for x86_64_v3 support. + * On x86_64 %define go_amd64=v1 as current instruction baseline + +------------------------------------------------------------------- +Thu Apr 13 04:58:20 UTC 2023 - Martin Liška + +- Use gcc13 compiler for Tumbleweed. + +------------------------------------------------------------------- +Wed Mar 1 17:04:37 UTC 2023 - Jaroslav Jindrak + +- Fix for SG#65262, bsc#1208491: + * go#57855 boo#1208270 security: fix CVE-2022-41723 bsc1208491.patch + * go#58001 boo#1208271 security: fix CVE-2022-41724 bsc1208491-41724.patch + * go#58006 boo#1208272 security: fix CVE-2022-41725 bsc1208491-41725.patch + +------------------------------------------------------------------- +Thu Jan 19 16:28:40 UTC 2023 - Jeff Kowalczyk + +- Update to version 1.18.10.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.10-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.10 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Tue Jan 10 22:13:49 UTC 2023 - Jeff Kowalczyk + +- go1.18.10 (released 2023-01-10) includes fixes to cgo, the + compiler, the linker, and the crypto/x509, net/http, and syscall + packages. + Refs boo#1193742 go1.18 release tracking + * go#57705 misc/cgo: backport needed for dlltool fix + * go#57426 crypto/x509: Verify on macOS does not return typed errors + * go#57344 cmd/compile: the loong64 intrinsic for CompareAndSwapUint32 function needs to sign extend its "old" argument. + * go#57338 syscall, internal/poll: accept4-to-accept fallback removal broke Go code on Synology DSM 6.2 ARM devices + * go#57213 os: TestLstat failure on Linux Aarch64 + * go#57211 reflect: sort.SliceStable sorts incorrectly on arm64 with less function created with reflect.MakeFunc and slice of sufficient length + * go#57057 cmd/go: remove test dependency on gopkg.in service + * go#57054 cmd/go: TestScript/version_buildvcs_git_gpg (if enabled) fails on linux longtest builders + * go#57044 cgo: malformed DWARF TagVariable entry + * go#57028 cmd/cgo: Wrong types in compiler errors with clang 14 + * go#56833 cmd/link/internal/ppc64: too-far trampoline is reused + * go#56711 net: reenable TestLookupDotsWithRemoteSource and TestLookupGoogleSRV with a different target + * go#56323 net/http: bad handling of HEAD requests with a body + +------------------------------------------------------------------- +Thu Dec 8 23:31:00 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.9.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.9-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.9 into dev.boringcrypto.go1.18 + * [dev.boringcrypto.go1.18] crypto/tls: allow BoringCrypto to use 4096-bit keys + +------------------------------------------------------------------- +Tue Dec 6 20:49:04 UTC 2022 - Jeff Kowalczyk + +- go1.18.9 (released 2022-12-06) includes security fixes to the + net/http and os packages, as well as bug fixes to cgo, the + compiler, the runtime, and the crypto/x509 and os/exec packages. + Refs boo#1193742 go1.18 release tracking + CVE-2022-41717 CVE-2022-41720 + * go#57008 boo#1206135 security: fix CVE-2022-41717 net/http: limit canonical header cache by bytes, not entries + * go#57005 boo#1206134 security: fix CVE-2022-41720 os, net/http: avoid escapes from os.DirFS and http.Dir on Windows + * go#56751 runtime,cmd/compile: apparent memory corruption in compress/flate + * go#56709 net: builders failing TestLookupDotsWithRemoteSource and TestLookupGoogleSRV due to missing host for _xmpp-server._tcp.google.com + * go#56675 x/net/http2/h2c: ineffective mitigation for unsafe io.ReadAll + * go#56635 runtime: traceback stuck in runtime.systemstack + * go#56556 cmd/compile: some x/sys versions no longer build due to "go:linkname must refer to declared function or variable" + * go#56550 os/exec: Plan 9 build has been broken by a Windows security fix (also breaks 1.19.3 and 1.18.8) + * go#56437 crypto/x509: respect GODEBUG changes during program lifetime + * go#56396 runtime: on linux/PPC64, usleep computes incorrect tv_nsec parameter + * go#56359 cmd/compile: panic: offset too large + +------------------------------------------------------------------- +Fri Nov 4 17:37:18 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.8.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.8-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.8 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Tue Nov 1 17:18:30 UTC 2022 - Jeff Kowalczyk + +- go1.18.8 (released 2022-11-01) includes security fixes to the + os/exec and syscall packages, as well as bug fixes to the + runtime. + Refs boo#1193742 go1.18 release tracking + CVE-2022-41716 + * go#56327 boo#1204941 security: fix CVE-2022-41716 syscall, os/exec: unsanitized NUL in environment variables + * go#56308 runtime: "runtime·lock: lock count" fatal error when cgo is enabled + +------------------------------------------------------------------- +Mon Oct 31 20:32:46 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.7.2 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.7-2-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.7 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Tue Oct 4 18:21:57 UTC 2022 - Jeff Kowalczyk + +- go1.18.7 (released 2022-10-04) includes security fixes to the + archive/tar, net/http/httputil, and regexp packages, as well as + bug fixes to the compiler, the linker, and the go/types package. + Refs boo#1193742 go1.18 release tracking + CVE-2022-41715 CVE-2022-2879 CVE-2022-2880 + * go#55950 boo#1204023 security: fix CVE-2022-41715 regexp/syntax: limit memory used by parsing regexps + * go#55925 boo#1204024 security: fix CVE-2022-2879 archive/tar: unbounded memory consumption when reading headers + * go#55842 boo#1204025 security: fix CVE-2022-2880 net/http/httputil: ReverseProxy should not forward unparseable query parameters + * go#55151 fatal error: bulkBarrierPreWrite: unaligned arguments + * go#55148 go/types: no way to construct the signature of append(s, "string"...) via the API + * go#55113 cmd/link: new darwin linker warning on -pagezero_size and -no_pie deprecation + * go#54918 cmd/compile: Value live at entry + +------------------------------------------------------------------- +Wed Sep 28 01:38:34 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.6.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.6-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.6 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Wed Sep 28 01:35:18 UTC 2022 - Jeff Kowalczyk + +- go1.18.6 (released 2022-09-06) includes security fixes to the + net/http package, as well as bug fixes to the compiler, the go + command, the pprof command, the runtime, and the crypto/tls, + encoding/xml, and net packages. + Refs boo#1193742 go1.18 release tracking + CVE-2022-27664 + * go#53977 bsc#1203185 CVE-2022-27664 net/http: handle server errors after sending GOAWAY + * go#54733 cmd/go: git fetch errors dropped when producing pseudo-versions for commits + * go#54725 cmd/compile: compile failed with "Value live at entry" + * go#54674 runtime: morestack_noctxt missing SPWRITE, causes "traceback stuck" assert + * go#54664 runtime: segfault running ppc64/linux binaries with kernel 5.18 + * go#54659 cmd/go: go test -race does not set implicit race build tag + * go#54642 crypto/tls: support ECDHE key exchanges when ec_point_formats is missing in ClientHello extension + * go#54636 cmd/go: data race in TestScript + * go#54603 cmd/compile: miscompilation of partially-overlapping array assignments + * go#54502 cmd/link: Trampoline insertion breaks DWARF Line Program Table output on Darwin/ARM64 + * go#54464 cmd/pprof: graphviz node names are funny with generics + * go#54128 encoding/xml: crash on android/arm64 due to https://go.dev/cl/417062 + * go#54074 net: WriteMsgUDPAddrPort should accept IPv4 destination addresses on IPv6 UDP sockets + * go#54056 misc/cgo: TestSignalForwardingExternal sometimes fails with wrong signal SIGINT + * go#53397 go/reflect: Incorrect behavior on arm64 when using MakeFunc / Call + +------------------------------------------------------------------- +Wed Sep 28 01:01:19 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.5.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.5-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.5 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Mon Aug 22 20:44:19 UTC 2022 - Jeff Kowalczyk + +- Define go_bootstrap_version go1.16 without suse_version checks +- Simplify conditional gcc_go_version 12 on Tumbleweed, 11 elsewhere + +------------------------------------------------------------------- +Fri Aug 19 15:47:43 UTC 2022 - Dirk Müller + +- Bootstrap using go1.16 on SLE-15 and newer. go1.16 is + bootstrapped using gcc-go 11 or 12. This allows dropping older + versions of Go from Factory. + +------------------------------------------------------------------- +Mon Aug 1 15:40:03 UTC 2022 - Jeff Kowalczyk + +- go1.18.5 (released 2022-08-01) includes security fixes to the + encoding/gob and math/big packages, as well as bug fixes to the + compiler, the go command, the runtime, and the testing package. + Refs boo#1193742 go1.18 release tracking + CVE-2022-32189 + * boo#1202035 CVE-2022-32189 go#53871 + * go#54095 math/big: index out of range in Float.GobDecode + * go#53883 cmd/compile: interface conversion with generics reports "types from different scopes" + * go#53875 cmd/go: livelock when computing module graph in a workspace with GOPROXY=off + * go#53852 cmd/compile: internal compiler error: assertion failed + * go#53847 runtime: modified timer results in extreme cpu load + * go#53119 cmd/go: Build information embedded by Go 1.18 impairs build reproducibility with cgo flags + * go#53112 runtime: gentraceback() dead loop on arm64 casued the process hang + * go#52986 testing: TempDir RemoveAll cleanup failures with "The process cannot access the file because it is being used by another process." + * go#52961 cmd/compile: miscompilation in pointer operations + +------------------------------------------------------------------- +Wed Jul 20 18:43:55 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.4.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.4-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.4 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Tue Jul 12 20:28:01 UTC 2022 - Jeff Kowalczyk + +- go1.18.4 (released 2022-07-12) includes security fixes to the + compress/gzip, encoding/gob, encoding/xml, go/parser, io/fs, + net/http, and path/filepath packages, as well as bug fixes to the + compiler, the go command, the linker, the runtime, and the + runtime/metrics package. + Refs boo#1193742 go1.18 release tracking + CVE-2022-1705 CVE-2022-32148 CVE-2022-30631 CVE-2022-30633 CVE-2022-28131 CVE-2022-30635 CVE-2022-30632 CVE-2022-30630 CVE-2022-1962 + * boo#1201434 CVE-2022-1705 go#53188 + * go#53433 net/http: improper sanitization of Transfer-Encoding header + * boo#1201436 CVE-2022-32148 go#53423 + * go#53621 net/http/httputil: NewSingleHostReverseProxy - omit X-Forwarded-For not working + * boo#1201437 CVE-2022-30631 go#53168 + * go#53718 compress/gzip: stack exhaustion in Reader.Read (CVE-2022-30631) + * boo#1201440 CVE-2022-30633 go#53611 + * go#53716 encoding/xml: stack exhaustion in Unmarshal (CVE-2022-30633) + * boo#1201443 CVE-2022-28131 go#53614 + * go#53712 encoding/xml: stack exhaustion in Decoder.Skip (CVE-2022-28131) + * boo#1201444 CVE-2022-30635 go#53615 + * go#53710 encoding/gob: stack exhaustion in Decoder.Decode (CVE-2022-30635) + * boo#1201445 CVE-2022-30632 go#53416 + * go#53714 path/filepath: stack exhaustion in Glob (CVE-2022-30632) + * boo#1201447 CVE-2022-30630 go#53415 + * go#53720 io/fs: stack exhaustion in Glob (CVE-2022-30630) + * boo#1201448 CVE-2022-1962 go#53616 + * go#53708 go/parser: stack exhaustion in all Parse* functions (CVE-2022-1962) + * go#53723 cmd/compile: ambiguous selector with generic interface & embedded types + * go#53618 cmd/compile: condition in for loop body is incorrectly optimised away + * go#53613 syscall: NewCallback triggers data race on Windows when used from different goroutine + * go#53590 runtime/metrics: data race detected in Read + * go#53588 cmd/go: "v1.x.y is not a tag" when .gitconfig sets log.decorate to full + * go#53587 cmd/compile: miscompilation of value switch involving generic interface types + * go#53471 cmd/compile: internal compiler error: width not calculated: int128 + * go#53357 cmd/compile: type assertion on generic type fails incorrectly + * go#53159 cmd/compile: unsafe.Offsetof returns incorrect value in embedded struct with type parameters + * go#53107 cmd/link: unexpected trampoline error on ppc64le musl with -buildmode=pie + * go#52689 runtime: total allocation stats are managed in a uintptr which can quickly wrap around on 32-bit architectures + +------------------------------------------------------------------- +Tue Jul 12 17:51:26 UTC 2022 - Jeff Kowalczyk + +- go1.18.3 (released 2022-06-01) includes security fixes to the + crypto/rand, crypto/tls, os/exec, and path/filepath packages, as + well as bug fixes to the compiler, and the crypto/tls and + text/template/parse packages. + Refs boo#1193742 go1.18 release tracking + CVE-2022-30634 CVE-2022-30629 CVE-2022-30580 CVE-2022-29804 + * boo#1200134 go#52561 CVE-2022-30634 + * go#52933 crypto/rand: Read hangs when passed buffer larger than 1<<32 - 1 + * boo#1200135 go#52814 CVE-2022-30629 + * go#52833 crypto/tls: randomly generate ticket_age_add + * boo#1200136 go#52574 CVE-2022-30580 + * go#53057 os/exec: Cmd.{Run,Start} should fail if Cmd.Path is unset + * boo#1200137 go#52476 CVE-2022-29804 + * go#52479 path/filepath: Clean(.\c:) returns c: on Windows + * go#51849 cmd/compile: crash on pointer conversion in call to mapaccess2 + * go#52242 cmd/compile: compiler crash on valid code + * go#52286 cmd/compile: compiler crash with "Dictionary should have already been generated" + * go#52791 crypto/tls: 500% increase in allocations from (*tls.Conn).Read in go 1.17 + * go#52878 text/template: break/continue require no whitespace around them + * go#53043 misc/cgo/testsanitizers: occasional hangs in TestTSAN/tsan12 + * go#53115 misc/cgo/testsanitizers: deadlock in TestTSAN/tsan11 + +------------------------------------------------------------------- +Wed Jul 6 13:45:11 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.2.2 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.2-2-openssl-fips. + * Update VERSION file + +------------------------------------------------------------------- +Fri May 13 13:33:37 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.2.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.2-1-openssl-fips. + * Merge branch dev.boringcrypto.go1.18 into go1.18-openssl-fips + * Merge go1.18.2 into dev.boringcrypto.go1.18 + +------------------------------------------------------------------- +Tue May 10 22:25:54 UTC 2022 - Jeff Kowalczyk + +- go1.18.2 (released 2022-05-10) includes security fixes to the + syscall package, as well as bug fixes to the compiler, runtime, + the go command, and the crypto/x509, go/types, net/http/httptest, + reflect, and sync/atomic packages. + Refs boo#1193742 go1.18 release tracking + CVE-2022-29526 + * boo#1199413 go#52313 CVE-2022-29526 + * go#52440 syscall: Faccessat checks wrong group + * go#51738 runtime: wrong type assertion result when using generic types + * go#51798 cmd/go: add (and default to) -buildvcs=auto + * go#51859 crypto/x509: x509 certificate with issuerUniqueID and/or subjectUniqueID parse error + * go#51897 net/http/httptest: race in Close + * go#52028 go/types: documentation on instance de-duplication is unclear about guarantees + * go#52149 syscall: TestGroupCleanupUserNamespace failure on linux-s390x-ibm + * go#52244 go/types, types2: go generic assert compile escape + * go#52305 runtime: doAllThreadsSyscall has an unaligned atomic load on 32-bit architectures + * go#52366 cmd/compile/internal/ssa: occurred the wrong rewrite cycle detection + * go#52375 runtime: executable compiled under Go 1.17.7 will occasionally wedge + * go#52386 reflect: can set map elem with string key of a different string type + * go#52441 cmd/compile: incorrect handling of iota in 1.18 + * go#52468 cmd/go: go run -mod=mod [files...] does not update go.mod and go.sum + * go#52558 cmd/compile: cannot convert v (variable of type *Bar[T]) to type *Foo[T] + * go#52606 cmd/compile: internal compiler error: weird package in name: .dict0 => .dict0 from "", not "test/p" + * go#52615 sync/atomic: compare and swap of inconsistently typed values with uninitialized Value + * go#52691 cmd/compile: generic function appears to use incorrect type descriptor + * go#52699 runtime: support debugCall on arm64 + * go#52706 net: TestDialCancel is not compatible with new macOS ARM64 builders + * go#52804 go/types: NewMethodSet doesn't terminate for recursively embedded generics + +------------------------------------------------------------------- +Mon May 2 08:43:22 UTC 2022 - Martin Liška + +- Remove remaining use of gold linker when bootstrapping with + gccgo. The binutils-gold package will be removed in the future. + * History: go1.8.3 2017-06-18 added conditional if gccgo defined + BuildRequires: binutils-gold for arches other than s390x + * No information available why binutils-gold was used initially + * Unrelated to upstream recent hardcoded gold dependency for ARM + +------------------------------------------------------------------- +Thu Apr 28 22:27:43 UTC 2022 - Jeff Kowalczyk + +- Update to version 1.18.1.1 cut from the go1.18-openssl-fips + branch at the revision tagged go1.18.1-1-openssl-fips. + * crypto/boring: correctly disable/re-enable fips tls in test + * crypto/boring: Disable TestDisableSHA1ForCertOnly + * crypto/boring: Remove restriction on build architecture + * Fix use-after-free bug in VerifyECDSA + * Add support for OpenSSL 3.0 + * Free blank allocations and avoid zero-sized allocs + * crypto/boring: Fix LDFLAGS + * crypto/boring: Fix usage of boring.Enabled after rebase + * crypto/boring: Fix tests and rsa error message + +------------------------------------------------------------------- +Tue Apr 12 17:42:46 UTC 2022 - Jeff Kowalczyk + +- go1.18.1 (released 2022-04-12) includes security fixes to the + crypto/elliptic, crypto/x509, and encoding/pem packages, as well + as bug fixes to the compiler, linker, runtime, the go command, + vet, and the bytes, crypto/x509, and go/types packages. + Refs boo#1193742 go1.18 release tracking + CVE-2022-24675 CVE-2022-28327 CVE-2022-27536 + * boo#1198423 go#51853 CVE-2022-24675 + * go#52037 encoding/pem: stack overflow + boo#1198424 go#52075 CVE-2022-28327 + * go#52077 crypto/elliptic: generic P-256 panic when scalar has too many leading zeroes + * boo#1198427 go#51759 CVE-2022-27536 + * go#51763 crypto/x509: Certificate.Verify crash on macOS with Go 1.18 + * go#52140 cmd/go: go work use -r panics when given a directory that does not exist + * go#52119 go/types, cmd/compile: type set overlapping implementation for interface types might be not correct + * go#52032 go/types: spurious diagnostics for untyped shift operands with GoVersion < go1.13 + * go#52007 go/types, types2: scope is unset on receivers of instantiated methods + * go#51874 cmd/go: Segfault on ppc64le during Go 1.18 build on Alpine Linux + * go#51855 cmd/compile: internal compiler error: panic: runtime error: index out of range [0] with length 0 + * go#51852 crypto/x509: reject SHA-1 signatures in Verify + * go#51847 cmd/compile: cannot import "package" (type parameter bound more than once) + * go#51846 cmd/compile: internal compiler error: walkExpr: switch 1 unknown op RECOVER + * go#51796 bytes: Trim returns empty slice instead of nil in 1.18 + * go#51767 cmd/go: "go test" seems to now require git due to -buildvcs + * go#51764 cmd/go: go work use panics when given a file + * go#51741 cmd/cgo: pointer to incomplete C type is mangled when passed through interface type and generic type assert + * go#51737 plugin: tls handshake panic: unreachable method called. linker bug? + * go#51727 cmd/vet, go/types: go vet crash when using self-recursive anonymous types in constraints + * go#51697 runtime: some tests fails on Windows with CGO_ENABLED=0 + * go#51669 cmd/compile: irgen uses wrong dict param to generate code for getting dict type + * go#51665 go/types, types2: gopls crash in recordTypeAndValue + +------------------------------------------------------------------- +Wed Apr 11 19:37:11 UTC 2022 - Jeff Kowalczyk + +- Initial package go1.18-openssl version 1.18.0.1 cut from the + go1.18-openssl-fips branch at the revision tagged + go1.18.0-1-openssl-fips. + Refs jsc#SLE-18320 + * Contains a fork of the Go toolchain dev.boringcrypto branch and + necessary modifications from the golang-fips/go GitHub project + for the Go crypto library to use an external cryptographic + library in a FIPS compliant way. + * Modifies the crypto/* packages to use OpenSSL for cryptographic + operations. + * Uses dlopen() to call into OpenSSL. + * FIPS mode (or boring mode as the package is named) is enabled + either via an environment variable GOLANG_FIPS=1 or by virtue + of the host being in FIPS mode. + * When the operating system is operating in FIPS mode, Go + applications which import crypto/tls/fipsonly limit operations + to the FIPS ciphersuite. + * SUSE RPM packaging introduces a fourth version digit go1.x.y.z + corresponding to the golang-fips/go patchset tagged revision + which can be updated independently of upstream Go maintenance + releases. + +------------------------------------------------------------------- +Thu Apr 7 23:57:47 UTC 2022 - Jeff Kowalczyk + +- Template gcc-go.patch to substitute gcc_go_version and eliminate + multiple similar patches each with hardcoded gcc go binary name. + gcc-go.patch inserts gcc-go binary name e.g. go-8 to compensate + for current lack of gcc-go update-alternatives usage. + * add gcc-go.patch + * drop gcc6-go.patch + * drop gcc7-go.patch + +------------------------------------------------------------------- +Thu Apr 7 17:51:56 UTC 2022 - Jeff Kowalczyk + +- For SLE-12 set gcc_go_version to 8 to bootstrap using gcc8-go. + gcc6-go and gcc7-go no longer successfully bootstrap go1.17 or + go1.18 on SLE-12 aarch64 ppc64le or s390x. + * gcc6-go fails with errors e.g. libnoder.a(_go_.o):(.toc+0x0): + undefined reference to `__go_pimt__I4_DiagFrN4_boolee3 + +------------------------------------------------------------------- +Tue Mar 19 21:05:53 UTC 2022 - Jeff Kowalczyk + +- Add %define go_label as a configurable Go toolchain directory + * go_label can be used to package multiple Go toolchains with + the same go_api + * go_label should be defined as go_api with an optional suffix + e.g. %{go_api} or %{go_api}-foo + * Default go_label = go_api makes no changes to package layout + +------------------------------------------------------------------- +Tue Mar 15 17:42:07 UTC 2022 - Jeff Kowalczyk + +- go1.18 (released 2022-03-15) is a major release of Go. + go1.18.x minor releases will be provided through February 2023. + https://github.com/golang/go/wiki/Go-Release-Cycle + Go 1.18 is a significant release, including changes to the + language, implementation of the toolchain, runtime, and + libraries. Go 1.18 arrives seven months after Go 1.17. As always, + the release maintains the Go 1 promise of compatibility. We + expect almost all Go programs to continue to compile and run as + before. + Refs boo#1193742 go1.18 release tracking + * See release notes https://golang.org/doc/go1.18. Excerpts + relevant to OBS environment and for SUSE/openSUSE follow: + * Go 1.18 includes an implementation of generic features as + described by the Type Parameters Proposal. This includes major + but fully backward-compatible changes to the language. + * The Go 1.18 compiler now correctly reports declared but not + used errors for variables that are set inside a function + literal but are never used. Before Go 1.18, the compiler did + not report an error in such cases. This fixes long-outstanding + compiler issue go#8560. + * The Go 1.18 compiler now reports an overflow when passing a + rune constant expression such as '1' << 32 as an argument to + the predeclared functions print and println, consistent with + the behavior of user-defined functions. Before Go 1.18, the + compiler did not report an error in such cases but silently + accepted such constant arguments if they fit into an + int64. Since go vet always pointed out this error, the number + of affected programs is likely very small. + * AMD64: Go 1.18 introduces the new GOAMD64 environment variable, + which selects at compile time a minimum target version of the + AMD64 architecture. Allowed values are v1, v2, v3, or v4. Each + higher level requires, and takes advantage of, additional + processor features. A detailed description can be found + here. The GOAMD64 environment variable defaults to v1. + * RISC-V: The 64-bit RISC-V architecture on Linux (the + linux/riscv64 port) now supports the c-archive and c-shared + build modes. + * Linux: Go 1.18 requires Linux kernel version 2.6.32 or later. + * Fuzzing: Go 1.18 includes an implementation of fuzzing as + described by the fuzzing proposal. See the fuzzing landing page + to get started. Please be aware that fuzzing can consume a lot + of memory and may impact your machine’s performance while it + runs. + * go get: go get no longer builds or installs packages in + module-aware mode. go get is now dedicated to adjusting + dependencies in go.mod. Effectively, the -d flag is always + enabled. To install the latest version of an executable outside + the context of the current module, use go install + example.com/cmd@latest. Any version query may be used instead + of latest. This form of go install was added in Go 1.16, so + projects supporting older versions may need to provide install + instructions for both go install and go get. go get now reports + an error when used outside a module, since there is no go.mod + file to update. In GOPATH mode (with GO111MODULE=off), go get + still builds and installs packages, as before. + * Automatic go.mod and go.sum updates: The go mod graph, go mod + vendor, go mod verify, and go mod why subcommands no longer + automatically update the go.mod and go.sum files. (Those files + can be updated explicitly using go get, go mod tidy, or go mod + download.) + * go version: The go command now embeds version control + information in binaries. It includes the currently checked-out + revision, commit time, and a flag indicating whether edited or + untracked files are present. Version control information is + embedded if the go command is invoked in a directory within a + Git, Mercurial, Fossil, or Bazaar repository, and the main + package and its containing main module are in the same + repository. This information may be omitted using the flag + -buildvcs=false. Additionally, the go command embeds + information about the build, including build and tool tags (set + with -tags), compiler, assembler, and linker flags (like + -gcflags), whether cgo was enabled, and if it was, the values + of the cgo environment variables (like CGO_CFLAGS). Both VCS + and build information may be read together with module + information using go version -m file or + runtime/debug.ReadBuildInfo (for the currently running binary) + or the new debug/buildinfo package. The underlying data format + of the embedded build information can change with new go + releases, so an older version of go may not handle the build + information produced with a newer version of go. To read the + version information from a binary built with go 1.18, use the + go version command and the debug/buildinfo package from go + 1.18+. + * go mod download: If the main module's go.mod file specifies go + 1.17 or higher, go mod download without arguments now downloads + source code for only the modules explicitly required in the + main module's go.mod file. (In a go 1.17 or higher module, that + set already includes all dependencies needed to build the + packages and tests in the main module.) To also download source + code for transitive dependencies, use go mod download all. + * go mod vendor: The go mod vendor subcommand now supports a -o + flag to set the output directory. (Other go commands still read + from the vendor directory at the module root when loading + packages with -mod=vendor, so the main use for this flag is for + third-party tools that need to collect package source code.) + * go mod tidy: The go mod tidy command now retains additional + checksums in the go.sum file for modules whose source code is + needed to verify that each imported package is provided by only + one module in the build list. Because this condition is rare + and failure to apply it results in a build error, this change + is not conditioned on the go version in the main module's + go.mod file. + * go work: The go command now supports a "Workspace" mode. If a + go.work file is found in the working directory or a parent + directory, or one is specified using the GOWORK environment + variable, it will put the go command into workspace mode. In + workspace mode, the go.work file will be used to determine the + set of main modules used as the roots for module resolution, + instead of using the normally-found go.mod file to specify the + single main module. For more information see the go work + documentation. + * go build -asan: The go build command and related commands now + support an -asan flag that enables interoperation with C (or + C++) code compiled with the address sanitizer (C compiler + option -fsanitize=address). + * //go:build lines: Go 1.17 introduced //go:build lines as a more + readable way to write build constraints, instead of // +build + lines. As of Go 1.17, gofmt adds //go:build lines to match + existing +build lines and keeps them in sync, while go vet + diagnoses when they are out of sync. Since the release of Go + 1.18 marks the end of support for Go 1.16, all supported + versions of Go now understand //go:build lines. In Go 1.18, go + fix now removes the now-obsolete // +build lines in modules + declaring go 1.17 or later in their go.mod files. For more + information, see https://go.dev/design/draft-gobuild. + * go vet: The vet tool is updated to support generic code. In + most cases, it reports an error in generic code whenever it + would report an error in the equivalent non-generic code after + substituting for type parameters with a type from their type + set. + * go vet: The cmd/vet checkers copylock, printf, sortslice, + testinggoroutine, and tests have all had moderate precision + improvements to handle additional code patterns. This may lead + to newly reported errors in existing packages. + * Runtime: The garbage collector now includes non-heap sources of + garbage collector work (e.g., stack scanning) when determining + how frequently to run. As a result, garbage collector overhead + is more predictable when these sources are significant. For + most applications these changes will be negligible; however, + some Go applications may now use less memory and spend more + time on garbage collection, or vice versa, than before. The + intended workaround is to tweak GOGC where necessary. The + runtime now returns memory to the operating system more + efficiently and has been tuned to work more aggressively as a + result. + * Compiler: Go 1.17 implemented a new way of passing function + arguments and results using registers instead of the stack on + 64-bit x86 architecture on selected operating systems. Go 1.18 + expands the supported platforms to include 64-bit ARM + (GOARCH=arm64), big- and little-endian 64-bit PowerPC + (GOARCH=ppc64, ppc64le), as well as 64-bit x86 architecture + (GOARCH=amd64) on all operating systems. On 64-bit ARM and + 64-bit PowerPC systems, benchmarking shows typical performance + improvements of 10% or more. As mentioned in the Go 1.17 + release notes, this change does not affect the functionality of + any safe Go code and is designed to have no impact on most + assembly code. See the Go 1.17 release notes for more details. + * Compiler: The compiler now can inline functions that contain + range loops or labeled for loops. + * Compiler: The new -asan compiler option supports the new go + command -asan option. + * Compiler: Because the compiler's type checker was replaced in + its entirety to support generics, some error messages now may + use different wording than before. In some cases, pre-Go 1.18 + error messages provided more detail or were phrased in a more + helpful way. We intend to address these cases in Go + 1.19. Because of changes in the compiler related to supporting + generics, the Go 1.18 compile speed can be roughly 15% slower + than the Go 1.17 compile speed. The execution time of the + compiled code is not affected. We intend to improve the speed + of the compiler in Go 1.19. + * Linker: The linker emits far fewer relocations. As a result, + most codebases will link faster, require less memory to link, + and generate smaller binaries. Tools that process Go binaries + should use Go 1.18's debug/gosym package to transparently + handle both old and new binaries. + * Linker: The new -asan linker option supports the new go command + -asan option. + * Bootstrap: When building a Go release from source and + GOROOT_BOOTSTRAP is not set, previous versions of Go looked for + a Go 1.4 or later bootstrap toolchain in the directory + $HOME/go1.4 (%HOMEDRIVE%%HOMEPATH%\go1.4 on Windows). Go now + looks first for $HOME/go1.17 or $HOME/sdk/go1.17 before falling + back to $HOME/go1.4. We intend for Go 1.19 to require Go 1.17 + or later for bootstrap, and this change should make the + transition smoother. For more details, see go#44505. + * The new debug/buildinfo package provides access to module + versions, version control information, and build flags embedded + in executable files built by the go command. The same + information is also available via runtime/debug.ReadBuildInfo + for the currently running binary and via go version -m on the + command line. + * The new net/netip package defines a new IP address type, + Addr. Compared to the existing net.IP type, the netip.Addr type + takes less memory, is immutable, and is comparable so it + supports == and can be used as a map key. + * TLS 1.0 and 1.1 disabled by default client-side: If + Config.MinVersion is not set, it now defaults to TLS 1.2 for + client connections. Any safely up-to-date server is expected to + support TLS 1.2, and browsers have required it since 2020. TLS + 1.0 and 1.1 are still supported by setting Config.MinVersion to + VersionTLS10. The server-side default is unchanged at TLS + 1.0. The default can be temporarily reverted to TLS 1.0 by + setting the GODEBUG=tls10default=1 environment variable. This + option will be removed in Go 1.19. + * Rejecting SHA-1 certificates: crypto/x509 will now reject + certificates signed with the SHA-1 hash function. This doesn't + apply to self-signed root certificates. Practical attacks + against SHA-1 have been demonstrated since 2017 and publicly + trusted Certificate Authorities have not issued SHA-1 + certificates since 2015. This can be temporarily reverted by + setting the GODEBUG=x509sha1=1 environment variable. This + option will be removed in Go 1.19. + * crypto/elliptic The P224, P384, and P521 curve implementations + are now all backed by code generated by the addchain and + fiat-crypto projects, the latter of which is based on a + formally-verified model of the arithmetic operations. They now + use safer complete formulas and internal APIs. P-224 and P-384 + are now approximately four times faster. All specific curve + implementations are now constant-time. Operating on invalid + curve points (those for which the IsOnCurve method returns + false, and which are never returned by Unmarshal or a Curve + method operating on a valid point) has always been undefined + behavior, can lead to key recovery attacks, and is now + unsupported by the new backend. If an invalid point is supplied + to a P224, P384, or P521 method, that method will now return a + random point. The behavior might change to an explicit panic in + a future release. + * crypto/tls: The new Conn.NetConn method allows access to the + underlying net.Conn. + * crypto/x509: Certificate.Verify now uses platform APIs to + verify certificate validity on macOS and iOS when it is called + with a nil VerifyOpts.Roots or when using the root pool + returned from SystemCertPool. SystemCertPool is now available + on Windows. + * crypto/x509: CertPool.Subjects is deprecated. On Windows, + macOS, and iOS the CertPool returned by SystemCertPool will + return a pool which does not include system roots in the slice + returned by Subjects, as a static list can't appropriately + represent the platform policies and might not be available at + all from the platform APIs. + * crypto/x509: Support for signing certificates using signature + algorithms that depend on the MD5 and SHA-1 hashes (MD5WithRSA, + SHA1WithRSA, and ECDSAWithSHA1) may be removed in Go 1.19. + * net/http: When looking up a domain name containing non-ASCII + characters, the Unicode-to-ASCII conversion is now done in + accordance with Nontransitional Processing as defined in the + Unicode IDNA Compatibility Processing standard (UTS #46). The + interpretation of four distinct runes are changed: ß, ς, + zero-width joiner U+200D, and zero-width non-joiner + U+200C. Nontransitional Processing is consistent with most + applications and web browsers. + * os/user: User.GroupIds now uses a Go native implementation when + cgo is not available. + * runtime/debug: The BuildInfo struct has two new fields, + containing additional information about how the binary was + built: GoVersion holds the version of Go used to build the + binary. Settings is a slice of BuildSettings structs holding + key/value pairs describing the build. + * runtime/pprof: The CPU profiler now uses per-thread timers on + Linux. This increases the maximum CPU usage that a profile can + observe, and reduces some forms of bias. + * syscall: The new function SyscallN has been introduced for + Windows, allowing for calls with arbitrary number of arguments. + As a result, Syscall, Syscall6, Syscall9, Syscall12, Syscall15, + and Syscall18 are deprecated in favor of SyscallN. + +------------------------------------------------------------------- +Wed Mar 9 17:03:28 UTC 2022 - Dirk Müller + +- add dont-force-gold-on-arm64.patch (bsc#1183043) +- drop binutils-gold dependency + +------------------------------------------------------------------- +Fri Feb 18 02:10:17 UTC 2022 - Jeff Kowalczyk + +- Add .bin assembler pattern table file and test data to packaging. + * Error manifests building some Go applications as: + src/crypto/elliptic/p256_asm.go:24:12: + pattern p256_asm_table.bin: no matching files found + * A Quick Guide to Go's Assembler https://go.dev/doc/asm + * New assembler pattern file added to packaging with mode 644: + src/crypto/elliptic/p256_asm_table.bin + * Existing test data files added to packaging with mode 644: + src/compress/bzip2/testdata/pass-random2.bin + src/compress/bzip2/testdata/pass-random1.bin + src/debug/dwarf/testdata/line-gcc-win.bin + +------------------------------------------------------------------- +Thu Feb 17 07:38:54 UTC 2022 - Jeff Kowalczyk + +- go1.18rc1 (released 2022-02-16) is a release candidate version of + go1.18 cut from the master branch at the revision tagged + go1.18rc1. + Refs boo#1193742 go1.18 release tracking + +------------------------------------------------------------------- +Mon Jan 31 19:25:36 UTC 2022 - Jeff Kowalczyk + +- go1.18beta2 (released 2022-01-31) is a beta version of go1.18 cut + from the master branch at the revision tagged go1.18beta2. + Refs boo#1193742 go1.18 release tracking + +------------------------------------------------------------------- +Tue Dec 14 20:06:19 UTC 2021 - Jeff Kowalczyk + +- go1.18beta1 (released 2021-12-14) is a beta version of go1.18 cut + from the master branch at the revision tagged go1.18beta1. + Refs boo#1193742 go1.18 release tracking diff --git a/go1.18-openssl.spec b/go1.18-openssl.spec new file mode 100644 index 0000000..ce210ef --- /dev/null +++ b/go1.18-openssl.spec @@ -0,0 +1,479 @@ +# +# spec file for package go1.18-openssl +# +# Copyright (c) 2023 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# +# nodebuginfo + + +# strip will cause Go's .a archives to become invalid because strip appears to +# reassemble the archive incorrectly. This is a known issue upstream +# (https://github.com/golang/go/issues/17890), but we have to deal with it in +# the meantime. +%undefine _build_create_debug +%define __arch_install_post export NO_BRP_STRIP_DEBUG=true NO_BRP_AR=true + +# Specify Go toolchain version used to bootstrap this package's Go toolchain +# go_bootstrap_version bootstrap go toolchain with specific existing go1.x package +# gcc_go_version bootstrap go toolchain with specific version of gcc-go +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +# Usually ahead of bootstrap version specified by upstream Go +# Use Tumbleweed default gccgo and N-1 go1.x for testing +%define gcc_go_version 13 +%define go_bootstrap_version go1.17 +%else +# Use gccgo and go1.x specified by upstream Go +%define gcc_go_version 11 +%define go_bootstrap_version go1.17 +%endif + +# Bootstrap go toolchain using existing go package go_bootstrap_version +# To bootstrap using gccgo use '--with gccgo' +%bcond_with gccgo + +# gccgo on ppc64le with default PIE enabled fails with: +# error while loading shared libraries: +# R_PPC64_ADDR16_HA re10143fb0c for symbol `' out of range +# track https://github.com/golang/go/issues/28531 +# linuxppc-dev discussion: +# "PIE binaries are no longer mapped below 4 GiB on ppc64le" +# https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-November/180862.html +%ifarch ppc64le +#!BuildIgnore: gcc-PIE +%endif + +# Build go-race only on platforms where C++14 is supported (SLE-15) +%if 0%{?suse_version} >= 1500 || 0%{?sle_version} >= 150000 +%define tsan_arch x86_64 aarch64 +%else +# Cannot use {nil} here (ifarch doesn't like it) so just make up a fake +# architecture that no build will ever match. +%define tsan_arch openSUSE_FAKE_ARCH +%endif + +# Go has precompiled versions of LLVM's compiler-rt inside their source code. +# We cannot ship pre-compiled binaries so we have to recompile said source, +# however they vendor specific commits from upstream. This value comes from +# src/runtime/race/README (and we verify that it matches in check). +# +# In order to update the TSAN version, modify _service. See boo#1052528 for +# more details. +%define tsan_commit 89f7ccea6f6488c443655880229c54db1f180153 + +# go_api is the major version of Go. +# Used by go1.x packages and go metapackage for: +# RPM Provides: golang(API), RPM Requires: and rpm_vercmp +# as well as derived variables such as go_label. +%define go_api 1.18 + +# go_label is the configurable Go toolchain directory name. +# Used for packaging multiple Go toolchains with the same go_api. +# go_label should be defined as go_api with optional suffix, e.g. +# go_api or go_api-foo +%define go_label %{go_api}-openssl + +# shared library support +%if "%{rpm_vercmp %{go_api} 1.5}" > "0" +%if %{with gccgo} +%define with_shared 1 +%else +%ifarch %ix86 %arm x86_64 aarch64 +%define with_shared 1 +%else +%define with_shared 0 +%endif +%endif +%else +%define with_shared 0 +%endif +%ifarch ppc64 +%define with_shared 0 +%endif +# setup go_arch (BSD-like scheme) +%ifarch %ix86 +%define go_arch 386 +%endif +%ifarch x86_64 +%define go_arch amd64 +# set GOAMD64 consistently +%define go_amd64 v1 +%endif +%ifarch aarch64 +%define go_arch arm64 +%endif +%ifarch %arm +%define go_arch arm +%endif +%ifarch ppc64 +%define go_arch ppc64 +%endif +%ifarch ppc64le +%define go_arch ppc64le +%endif +%ifarch s390x +%define go_arch s390x +%endif +%ifarch riscv64 +%define go_arch riscv64 +%endif + +Name: go1.18-openssl +Version: 1.18.10.1 +Release: 0 +Summary: A compiled, garbage-collected, concurrent programming language +License: BSD-3-Clause +Group: Development/Languages/Go +URL: https://go.dev/ +Source: go%{version}-openssl.src.tar.gz +Source1: go-rpmlintrc +Source4: README.SUSE +Source6: go.gdbinit +# We have to compile TSAN ourselves. boo#1052528 +# Preferred form when all arches share llvm race version +# Source100: llvm-%{tsan_commit}.tar.xz +Source100: llvm-%{tsan_commit}.tar.xz +# PATCH-FIX-OPENSUSE: https://go-review.googlesource.com/c/go/+/391115 +Patch7: dont-force-gold-on-arm64.patch +# PATCH-FIX-UPSTREAM marguerite@opensuse.org - find /usr/bin/go-8 when bootstrapping with gcc8-go +Patch8: gcc-go.patch +Patch9: bsc1208491.patch +Patch10: bsc1208491-41724.patch +Patch11: bsc1208491-41725.patch +BuildRoot: %{_tmppath}/%{name}-%{version}-build +# boostrap +%if %{with gccgo} +BuildRequires: gcc%{gcc_go_version}-go +%else +# no gcc-go +BuildRequires: %{go_bootstrap_version} +%endif +BuildRequires: fdupes +Suggests: %{name}-doc = %{version} +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +Suggests: %{name}-libstd = %{version} +%endif +%ifarch %{tsan_arch} +# Needed to compile compiler-rt/TSAN. +BuildRequires: gcc-c++ +%endif +#BNC#818502 debug edit tool of rpm fails on i586 builds +BuildRequires: rpm >= 4.11.1 +Requires(post): update-alternatives +Requires(postun):update-alternatives +Requires: gcc +BuildRequires: libopenssl-devel +Requires: libopenssl-devel +Provides: go = %{version} +Provides: go-devel = go%{version} +Provides: go-devel-static = go%{version} +Provides: golang(API) = %{go_api} +Obsoletes: go-devel < go%{version} +# go-vim/emacs were separate projects starting from 1.4 +Obsoletes: go-emacs <= 1.3.3 +Obsoletes: go-vim <= 1.3.3 +ExclusiveArch: %ix86 x86_64 %arm aarch64 ppc64 ppc64le s390x riscv64 + +%description +Go is an expressive, concurrent, garbage collected systems programming language +that is type safe and memory safe. It has pointers but no pointer arithmetic. +Go has fast builds, clean syntax, garbage collection, methods for any type, and +run-time reflection. It feels like a dynamic language but has the speed and +safety of a static language. + +%package doc +Summary: Go documentation +Group: Documentation/Other +Provides: go-doc = %{version} + +%description doc +Go examples and documentation. + +%ifarch %{tsan_arch} +# boo#1052528 +%package race +Summary: Go runtime race detector +Group: Development/Languages/Go +URL: https://compiler-rt.llvm.org/ +Requires: %{name} = %{version} +Supplements: %{name} = %{version} +ExclusiveArch: %{tsan_arch} + +%description race +Go runtime race detector libraries. Install this package if you wish to use the +-race option, in order to detect race conditions present in your Go programs. +%endif + +%if %{with_shared} +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +%package libstd +Summary: Go compiled shared library libstd.so +Group: Development/Languages/Go +Provides: go-libstd = %{version} + +%description libstd +Go standard library compiled to a dynamically loadable shared object libstd.so +%endif +%endif + +%prep +%ifarch %{tsan_arch} +# compiler-rt (from LLVM) +%setup -q -T -b 100 -n llvm-%{tsan_commit} +%endif + +# go +%setup -q -n go +# Write go version into VERSION file in go source top level directory. +# Needed for go build scripts to operate without assuming .git/ present. +echo -n "go%{version}" > %{_builddir}/go/VERSION +%patch7 -p1 +%if %{with gccgo} +# Currently gcc-go does not manage an update-alternatives entry and will +# never be symlinked as "go", even if gcc-go is the only installed go toolchain. +# Patch go bootstrap scripts to find hardcoded go-(gcc-go-version) e.g. go-8 +# Substitute defined gcc_go_version into gcc-go.patch +sed -i "s/\$gcc_go_version/%{gcc_go_version}/" $RPM_SOURCE_DIR/gcc-go.patch +%patch8 -p1 +%endif +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 + +cp %{SOURCE4} . + +%build +# Remove the pre-included .sysos, to avoid shipping things we didn't compile +# (which is against the openSUSE guidelines for packaging). +# FIPS: retain boringcrypto .syso for now, not in use case for FIPS mode +# go/src/crypto/internal/boring/nboringcrypto/goboringcrypto_linux_amd64.syso +find . -type f -name '*.syso' ! -name '*boring*.syso' -print -delete +# TODO: Rebuild using +# BuildRequire: boringssl-devel +# GO_LDFLAGS pkg-config(libboringssl1) (spelling TBD) +# boringssl packages are currently present in Factory, not in SLE + +# First, compile LLVM's TSAN, and replace the built-in with it. We can only do +# this for amd64. +%ifarch %{tsan_arch} +TSAN_DIR="../llvm-%{tsan_commit}/compiler-rt/lib/tsan/go" +pushd "$TSAN_DIR" +./buildgo.sh +popd +cp -v "$TSAN_DIR/race_linux_%{go_arch}.syso" src/runtime/race/ +%endif + +# Now, compile Go. +%if %{with gccgo} +export GOROOT_BOOTSTRAP=%{_prefix} +%else +export GOROOT_BOOTSTRAP=%{_libdir}/%{go_bootstrap_version} +%endif +# Ensure ARM arch is set properly - boo#1169832 +%ifarch armv6l armv6hl +export GOARCH=arm +export GOARM=6 +%endif +%ifarch armv7l armv7hl +export GOARCH=arm +export GOARM=7 +%endif +%ifarch x86_64 %{?x86_64} +# use the baseline defined above. Other option is GOAMD64=v3 for x86_64_v3 support +export GOAMD64=%go_amd64 +%endif +export GOROOT="`pwd`" +export GOROOT_FINAL=%{_libdir}/go/%{go_label} +export GOBIN="$GOROOT/bin" +mkdir -p "$GOBIN" +cd src +HOST_EXTRA_CFLAGS="%{optflags} -Wno-error" ./make.bash -v + +cd ../ +%ifarch %{tsan_arch} +# Install TSAN-friendly version of the std libraries. +bin/go install -race std +%endif + +%if %{with_shared} +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +# Compile Go standard library as a dynamically loaded shared object libstd.so +# for inclusion in a subpackage which can be installed standalone. +# Upstream Go binary releases do not ship a compiled libstd.so. +# Standard practice is to build Go binaries as a single executable. +# Upstream Go discussed removing this feature, opted to fix current support: +# Relevant upstream comments on: https://github.com/golang/go/issues/47788 +# +# -buildmode=shared +# Combine all the listed non-main packages into a single shared +# library that will be used when building with the -linkshared +# option. Packages named main are ignored. +# +# -linkshared +# build code that will be linked against shared libraries previously +# created with -buildmode=shared. +bin/go install -buildmode=shared std +%endif +%endif + +%check +%ifarch %{tsan_arch} +# Make sure that we have the right TSAN checked out. +grep "^race_linux_%{go_arch}.syso built with LLVM %{tsan_commit}" src/runtime/race/README +%endif + +%install +export GOROOT="%{buildroot}%{_libdir}/go/%{go_label}" + +# locations for third party libraries, see README-openSUSE for info about locations. +install -d %{buildroot}%{_datadir}/go/%{go_label}/contrib +install -d $GOROOT/contrib/pkg/linux_%{go_arch} +ln -s %{_libdir}/go/%{go_label}/contrib/pkg/ %{buildroot}%{_datadir}/go/%{go_label}/contrib/pkg +install -d %{buildroot}%{_datadir}/go/%{go_label}/contrib/cmd +install -d %{buildroot}%{_datadir}/go/%{go_label}/contrib/src +ln -s %{_datadir}/go/%{go_label}/contrib/src/ %{buildroot}%{_libdir}/go/%{go_label}/contrib/src +install -Dm644 README.SUSE $GOROOT/contrib/ +ln -s %{_libdir}/go/%{go_label}/contrib/README.SUSE %{buildroot}%{_datadir}/go/%{go_label}/contrib/README.SUSE + +# source files for go install, godoc, etc +install -d %{buildroot}%{_datadir}/go/%{go_label} +for ext in *.{go,c,h,s,S,py,syso,bin}; do + find src -name ${ext} -exec install -Dm644 \{\} %{buildroot}%{_datadir}/go/%{go_label}/\{\} \; +done +# executable bash scripts called by go tool, etc +find src -name "*.bash" -exec install -Dm655 \{\} %{buildroot}%{_datadir}/go/%{go_label}/\{\} \; + +mkdir -p $GOROOT/src +for i in $(ls %{buildroot}/usr/share/go/%{go_label}/src);do + ln -s /usr/share/go/%{go_label}/src/$i $GOROOT/src/$i +done +# add lib files that are needed (such as the timezone database). +install -d $GOROOT/lib +find lib -type f -exec install -D -m644 {} $GOROOT/{} \; + +# copy document templates, packages, obj libs and command utilities +mkdir -p $GOROOT/bin +# remove bootstrap +rm -rf pkg/bootstrap +mv pkg $GOROOT +mv bin/* $GOROOT/bin +mkdir -p $GOROOT/misc/trace +mv misc/trace/* $GOROOT/misc/trace +# add wasm (Web Assembly) boo#1139210 +mkdir -p $GOROOT/misc/wasm +mv misc/wasm/* $GOROOT/misc/wasm +rm -f %{buildroot}%{_bindir}/{hgpatch,quietgcc} + +# gdbinit +install -Dm644 %{SOURCE6} $GOROOT/bin/gdbinit.d/go.gdb +%if "%{_lib}" == "lib64" +sed -i "s/lib/lib64/" $GOROOT/bin/gdbinit.d/go.gdb +sed -i "s/\$go_label/%{go_label}/" $GOROOT/bin/gdbinit.d/go.gdb +%endif + +# update-alternatives +mkdir -p %{buildroot}%{_sysconfdir}/alternatives +mkdir -p %{buildroot}%{_bindir} +mkdir -p %{buildroot}%{_sysconfdir}/profile.d +mkdir -p %{buildroot}%{_sysconfdir}/gdbinit.d +touch %{buildroot}%{_sysconfdir}/alternatives/{go,gofmt,go.gdb} +ln -sf %{_sysconfdir}/alternatives/go %{buildroot}%{_bindir}/go +ln -sf %{_sysconfdir}/alternatives/gofmt %{buildroot}%{_bindir}/gofmt +ln -sf %{_sysconfdir}/alternatives/go.gdb %{buildroot}%{_sysconfdir}/gdbinit.d/go.gdb + +# documentation and examples +# fix documetation permissions (rpmlint warning) +find doc/ misc/ -type f -exec chmod 0644 '{}' + +# remove unwanted arch-dependant binaries (rpmlint warning) +rm -rf misc/cgo/test/{_*,*.o,*.out,*.6,*.8} +# prepare go-doc +mkdir -p %{buildroot}%{_docdir}/go/%{go_label} +cp -r AUTHORS CONTRIBUTORS CONTRIBUTING.md LICENSE PATENTS README.md README.boringcrypto.md README.SUSE %{buildroot}%{_docdir}/go/%{go_label} +cp -r doc/* %{buildroot}%{_docdir}/go/%{go_label} + +%fdupes -s %{buildroot}%{_prefix} + +%post + +update-alternatives \ + --install %{_bindir}/go go %{_libdir}/go/%{go_label}/bin/go $((20+$(echo %{go_label} | cut -d. -f2))) \ + --slave %{_bindir}/gofmt gofmt %{_libdir}/go/%{go_label}/bin/gofmt \ + --slave %{_sysconfdir}/gdbinit.d/go.gdb go.gdb %{_libdir}/go/%{go_label}/bin/gdbinit.d/go.gdb + +%postun +if [ $1 -eq 0 ] ; then + update-alternatives --remove go %{_libdir}/go/%{go_label}/bin/go +fi + +%files +%{_bindir}/go +%{_bindir}/gofmt +%dir %{_libdir}/go +%{_libdir}/go/%{go_label} +%dir %{_datadir}/go +%{_datadir}/go/%{go_label} +%dir %{_sysconfdir}/gdbinit.d/ +%config %{_sysconfdir}/gdbinit.d/go.gdb +%ghost %{_sysconfdir}/alternatives/go +%ghost %{_sysconfdir}/alternatives/gofmt +%ghost %{_sysconfdir}/alternatives/go.gdb +%dir %{_docdir}/go +%dir %{_docdir}/go/%{go_label} +%doc %{_docdir}/go/%{go_label}/AUTHORS +%doc %{_docdir}/go/%{go_label}/CONTRIBUTORS +%doc %{_docdir}/go/%{go_label}/CONTRIBUTING.md +%doc %{_docdir}/go/%{go_label}/PATENTS +%doc %{_docdir}/go/%{go_label}/README.md +%doc %{_docdir}/go/%{go_label}/README.boringcrypto.md +%doc %{_docdir}/go/%{go_label}/README.SUSE +%if 0%{?suse_version} < 1500 +%doc %{_docdir}/go/%{go_label}/LICENSE +%else +%license %{_docdir}/go/%{go_label}/LICENSE +%endif + +# We don't include TSAN in the main Go package. +%ifarch %{tsan_arch} +%exclude %{_datadir}/go/%{go_label}/src/runtime/race/race_linux_%{go_arch}.syso +%endif + +# We don't include libstd.so in the main Go package. +%if %{with_shared} +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +# ./go/1.20/pkg/linux_amd64_dynlink/libstd.so +%exclude %{_libdir}/go/%{go_label}/pkg/linux_%{go_arch}_dynlink/libstd.so +%endif +%endif + +%files doc +%doc %{_docdir}/go/%{go_label}/*.html + +%ifarch %{tsan_arch} +%files race +%{_datadir}/go/%{go_label}/src/runtime/race/race_linux_%{go_arch}.syso +%endif + +%if %{with_shared} +%if 0%{?suse_version} > 1500 +# openSUSE Tumbleweed +%files libstd +%{_libdir}/go/%{go_label}/pkg/linux_%{go_arch}_dynlink/libstd.so +%endif +%endif + +%changelog diff --git a/go1.18.10.1-openssl.src.tar.gz b/go1.18.10.1-openssl.src.tar.gz new file mode 100644 index 0000000..ea0287b --- /dev/null +++ b/go1.18.10.1-openssl.src.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86a5d0fd2eb83fd4fc53adb23309bc3b0fd32549b4f167d3f2ebc5814c36efcc +size 24346954 diff --git a/llvm-89f7ccea6f6488c443655880229c54db1f180153.tar.xz b/llvm-89f7ccea6f6488c443655880229c54db1f180153.tar.xz new file mode 100644 index 0000000..9a004c0 --- /dev/null +++ b/llvm-89f7ccea6f6488c443655880229c54db1f180153.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b0f69496fb84ffe7292bb62d668fbc639ad1b89f3255869e2985d6444989454 +size 2197644