diff --git a/0013-drop-hard-code-cert.patch b/0001-drop-hard-code-cert.patch similarity index 100% rename from 0013-drop-hard-code-cert.patch rename to 0001-drop-hard-code-cert.patch diff --git a/0001-release-branch.go1.15-doc-go1.15-mention-1.15.3-cgo-.patch b/0001-release-branch.go1.15-doc-go1.15-mention-1.15.3-cgo-.patch new file mode 100644 index 0000000000000000000000000000000000000000..dfe3597f83f78b4854a3674ee54364d0033ed1c2 --- /dev/null +++ b/0001-release-branch.go1.15-doc-go1.15-mention-1.15.3-cgo-.patch @@ -0,0 +1,52 @@ +From 069f9d96d179becc61231d566c9a75f1ec26e991 Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor +Date: Fri, 11 Dec 2020 19:10:00 -0800 +Subject: [PATCH 01/44] [release-branch.go1.15] doc/go1.15: mention 1.15.3 cgo + restriction on empty structs + +For #40954 + +Change-Id: I6a30aed31a16e820817f4ca5c7f591222e922946 +Reviewed-on: https://go-review.googlesource.com/c/go/+/277432 +Trust: Ian Lance Taylor +Reviewed-by: Keith Randall +(cherry picked from commit 129bb1917b4914f0743ec9b4ef0dfb74df39c07d) +Reviewed-on: https://go-review.googlesource.com/c/go/+/278573 +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/069f9d96d179becc61231d566c9a75f1ec26e991 + +--- + doc/go1.15.html | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/doc/go1.15.html b/doc/go1.15.html +index c691bf3bd5..c9997c0ca3 100644 +--- a/doc/go1.15.html ++++ b/doc/go1.15.html +@@ -397,6 +397,19 @@ Do not send CLs removing the interior tags from such phrases. + documentation for more information. +

+ ++

++ In Go 1.15.3 and later, cgo will not permit Go code to allocate an ++ undefined struct type (a C struct defined as just struct ++ S; or similar) on the stack or heap. ++ Go code will only be permitted to use pointers to those types. ++ Allocating an instance of such a struct and passing a pointer, or a ++ full struct value, to C code was always unsafe and unlikely to work ++ correctly; it is now forbidden. ++ The fix is to either rewrite the Go code to use only pointers, or to ++ ensure that the Go code sees the full definition of the struct by ++ including the appropriate C header file. ++

++ +

X.509 CommonName deprecation

+ +

+-- +2.27.0 + diff --git a/0002-release-branch.go1.15-cmd-go-fix-mod_get_fallback-te.patch b/0002-release-branch.go1.15-cmd-go-fix-mod_get_fallback-te.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b855bac47d78308a130c7c236da89f566d2ac85 --- /dev/null +++ b/0002-release-branch.go1.15-cmd-go-fix-mod_get_fallback-te.patch @@ -0,0 +1,38 @@ +From aaef93bba34740d793e987d95355feb312f01cfd Mon Sep 17 00:00:00 2001 +From: Jay Conrod +Date: Wed, 20 Jan 2021 09:45:03 -0500 +Subject: [PATCH 02/44] [release-branch.go1.15] cmd/go: fix mod_get_fallback + test + +Fixes #43797 + +Change-Id: I3d791d0ac9ce0b523c78c649aaf5e339a7f63b76 +Reviewed-on: https://go-review.googlesource.com/c/go/+/284797 +Trust: Jay Conrod +Run-TryBot: Jay Conrod +Reviewed-by: Bryan C. Mills +TryBot-Result: Go Bot +(cherry picked from commit be28e5abc5ddca0d6b2d8c91b7bb9c05717154e7) +Reviewed-on: https://go-review.googlesource.com/c/go/+/284799 + +Conflict:NA +Reference:https://github.com/golang/go/commit/aaef93bba34740d793e987d95355feb312f01cfd + +--- + src/cmd/go/testdata/script/mod_get_fallback.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cmd/go/testdata/script/mod_get_fallback.txt b/src/cmd/go/testdata/script/mod_get_fallback.txt +index a9834a324e..9733fa366b 100644 +--- a/src/cmd/go/testdata/script/mod_get_fallback.txt ++++ b/src/cmd/go/testdata/script/mod_get_fallback.txt +@@ -6,5 +6,5 @@ env GOPROXY=https://proxy.golang.org,direct + env GOSUMDB=off + + go get -x -v -d golang.org/x/tools/cmd/goimports +-stderr '# get https://proxy.golang.org/golang.org/x/tools/@latest' ++stderr '# get https://proxy.golang.org/golang.org/x/tools/@v/list' + ! stderr '# get https://golang.org' +-- +2.27.0 + diff --git a/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch b/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch deleted file mode 100644 index 072440dd8a5cee630347de795e5ab1f96c2a0e2a..0000000000000000000000000000000000000000 --- a/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 817407fc2d6a861e65086388766f58082d38bc0b Mon Sep 17 00:00:00 2001 -From: Michael Munday -Date: Tue, 17 Jan 2017 11:33:38 -0500 -Subject: [PATCH 2/3] syscall: expose IfInfomsg.X__ifi_pad on s390x - -Exposing this field on s390x improves compatibility with the other -linux architectures, all of which already expose it. - -Fixes #18628 and updates #18632. - -Change-Id: I08e8e1eb705f898cd8822f8bee0d61ce11d514b5 ---- - src/syscall/ztypes_linux_s390x.go | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/syscall/ztypes_linux_s390x.go b/src/syscall/ztypes_linux_s390x.go -index 63c4a83b19..b5894255df 100644 ---- a/src/syscall/ztypes_linux_s390x.go -+++ b/src/syscall/ztypes_linux_s390x.go -@@ -449,12 +449,12 @@ type RtAttr struct { - } - - type IfInfomsg struct { -- Family uint8 -- _ uint8 -- Type uint16 -- Index int32 -- Flags uint32 -- Change uint32 -+ Family uint8 -+ X__ifi_pad uint8 -+ Type uint16 -+ Index int32 -+ Flags uint32 -+ Change uint32 - } - - type IfAddrmsg struct { --- -2.14.3 - diff --git a/0003-golang-delete-pem-files.patch b/0003-golang-delete-pem-files.patch deleted file mode 100644 index a4114a192f5856aababbc7e97cf93fffc0125ed9..0000000000000000000000000000000000000000 --- a/0003-golang-delete-pem-files.patch +++ /dev/null @@ -1,44 +0,0 @@ -From de4a8f2f1c0e7c30dc5f54d19212eb29d01871ed Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 10:46:52 +0800 -Subject: [PATCH 6/6] golang: delete pem files - -Signed-off-by: jingrui ---- - src/crypto/tls/testdata/example-cert.pem | 11 ----------- - src/crypto/tls/testdata/example-key.pem | 5 ----- - 2 files changed, 16 deletions(-) - delete mode 100644 src/crypto/tls/testdata/example-cert.pem - delete mode 100644 src/crypto/tls/testdata/example-key.pem - -diff --git a/src/crypto/tls/testdata/example-cert.pem b/src/crypto/tls/testdata/example-cert.pem -deleted file mode 100644 -index e0bf7db..0000000 ---- a/src/crypto/tls/testdata/example-cert.pem -+++ /dev/null -@@ -1,11 +0,0 @@ -------BEGIN CERTIFICATE----- --MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw --DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow --EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d --7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B --5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr --BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 --NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l --Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc --6MF9+Yw1Yy0t -------END CERTIFICATE----- -diff --git a/src/crypto/tls/testdata/example-key.pem b/src/crypto/tls/testdata/example-key.pem -deleted file mode 100644 -index 104fb09..0000000 ---- a/src/crypto/tls/testdata/example-key.pem -+++ /dev/null -@@ -1,5 +0,0 @@ -------BEGIN EC PRIVATE KEY----- --MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 --AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q --EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== -------END EC PRIVATE KEY----- --- -2.17.1 - diff --git a/0003-release-branch.go1.15-internal-execabs-only-run-test.patch b/0003-release-branch.go1.15-internal-execabs-only-run-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfa22efdc077af7a510c18fe03661b64be14a9e4 --- /dev/null +++ b/0003-release-branch.go1.15-internal-execabs-only-run-test.patch @@ -0,0 +1,54 @@ +From e540758b604dd46b682593e284cf77a61ce3fde6 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Wed, 20 Jan 2021 09:06:12 -0800 +Subject: [PATCH 03/44] [release-branch.go1.15] internal/execabs: only run + tests on platforms that support them + +Fixes #43793 + +Change-Id: I3bf022a28b194f0089ea96d93e56bbd9fb7e0aa8 +Reviewed-on: https://go-review.googlesource.com/c/go/+/285056 +Trust: Roland Shoemaker +Run-TryBot: Roland Shoemaker +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/e540758b604dd46b682593e284cf77a61ce3fde6 + +--- + src/internal/execabs/execabs_test.go | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/internal/execabs/execabs_test.go b/src/internal/execabs/execabs_test.go +index a0b88dd2a0..1a197b8701 100644 +--- a/src/internal/execabs/execabs_test.go ++++ b/src/internal/execabs/execabs_test.go +@@ -7,6 +7,7 @@ package execabs + import ( + "context" + "fmt" ++ "internal/testenv" + "io/ioutil" + "os" + "os/exec" +@@ -30,6 +31,8 @@ func TestFixCmd(t *testing.T) { + } + + func TestCommand(t *testing.T) { ++ testenv.MustHaveExec(t) ++ + for _, cmd := range []func(string) *Cmd{ + func(s string) *Cmd { return Command(s) }, + func(s string) *Cmd { return CommandContext(context.Background(), s) }, +@@ -71,6 +74,8 @@ func TestCommand(t *testing.T) { + } + + func TestLookPath(t *testing.T) { ++ testenv.MustHaveExec(t) ++ + tmpDir, err := ioutil.TempDir("", "execabs-test") + if err != nil { + t.Fatalf("ioutil.TempDir failed: %s", err) +-- +2.27.0 + diff --git a/0004-release-branch.go1.15-cmd-compile-don-t-short-circui.patch b/0004-release-branch.go1.15-cmd-compile-don-t-short-circui.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2211d5fee1929812876453170798551a7a69bd4 --- /dev/null +++ b/0004-release-branch.go1.15-cmd-compile-don-t-short-circui.patch @@ -0,0 +1,154 @@ +From 27d5fccd2119099c70ab6a4418626beac7a97b4b Mon Sep 17 00:00:00 2001 +From: Keith Randall +Date: Thu, 7 Jan 2021 14:57:53 -0800 +Subject: [PATCH 04/44] [release-branch.go1.15] cmd/compile: don't + short-circuit copies whose source is volatile + +Current optimization: When we copy a->b and then b->c, we might as well +copy a->c instead of b->c (then b might be dead and go away). + +*Except* if a is a volatile location (might be clobbered by a call). +In that case, we really do want to copy a immediately, because there +might be a call before we can do the a->c copy. + +User calls can't happen in between, because the rule matches up the +memory states. But calls inserted for memory barriers, particularly +runtime.typedmemmove, can. + +(I guess we could introduce a register-calling-convention version +of runtime.typedmemmove, but that seems a bigger change than this one.) + +Fixes #43575 + +Change-Id: Ifa518bb1a6f3a8dd46c352d4fd54ea9713b3eb1a +Reviewed-on: https://go-review.googlesource.com/c/go/+/282492 +Trust: Keith Randall +Trust: Josh Bleecher Snyder +Run-TryBot: Keith Randall +TryBot-Result: Go Bot +Reviewed-by: Josh Bleecher Snyder +(cherry picked from commit 304f769ffc68e64244266b3aadbf91e6738c0064) +Reviewed-on: https://go-review.googlesource.com/c/go/+/282558 +Trust: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/27d5fccd2119099c70ab6a4418626beac7a97b4b + +--- + .../compile/internal/ssa/gen/generic.rules | 4 +- + .../compile/internal/ssa/rewritegeneric.go | 8 ++-- + test/fixedbugs/issue43570.go | 40 +++++++++++++++++++ + 3 files changed, 46 insertions(+), 6 deletions(-) + create mode 100644 test/fixedbugs/issue43570.go + +diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules +index ed5bfc81fd..8bbe913380 100644 +--- a/src/cmd/compile/internal/ssa/gen/generic.rules ++++ b/src/cmd/compile/internal/ssa/gen/generic.rules +@@ -2404,7 +2404,7 @@ + (Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _)) + && t1.Compare(t2) == types.CMPeq + && isSamePtr(tmp1, tmp2) +- && isStackPtr(src) ++ && isStackPtr(src) && !isVolatile(src) + && disjoint(src, s, tmp2, s) + && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) + => (Move {t1} [s] dst src midmem) +@@ -2413,7 +2413,7 @@ + (Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _))) + && t1.Compare(t2) == types.CMPeq + && isSamePtr(tmp1, tmp2) +- && isStackPtr(src) ++ && isStackPtr(src) && !isVolatile(src) + && disjoint(src, s, tmp2, s) + && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) + => (Move {t1} [s] dst src midmem) +diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go +index 9f4e1b95bd..6a09616aad 100644 +--- a/src/cmd/compile/internal/ssa/rewritegeneric.go ++++ b/src/cmd/compile/internal/ssa/rewritegeneric.go +@@ -13666,7 +13666,7 @@ func rewriteValuegeneric_OpMove(v *Value) bool { + return true + } + // match: (Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _)) +- // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) ++ // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) + // result: (Move {t1} [s] dst src midmem) + for { + s := auxIntToInt64(v.AuxInt) +@@ -13680,7 +13680,7 @@ func rewriteValuegeneric_OpMove(v *Value) bool { + t2 := auxToType(midmem.Aux) + src := midmem.Args[1] + tmp2 := midmem.Args[0] +- if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) { ++ if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) { + break + } + v.reset(OpMove) +@@ -13690,7 +13690,7 @@ func rewriteValuegeneric_OpMove(v *Value) bool { + return true + } + // match: (Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _))) +- // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) ++ // cond: t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config)) + // result: (Move {t1} [s] dst src midmem) + for { + s := auxIntToInt64(v.AuxInt) +@@ -13708,7 +13708,7 @@ func rewriteValuegeneric_OpMove(v *Value) bool { + t2 := auxToType(midmem_0.Aux) + src := midmem_0.Args[1] + tmp2 := midmem_0.Args[0] +- if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) { ++ if !(t1.Compare(t2) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && !isVolatile(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) { + break + } + v.reset(OpMove) +diff --git a/test/fixedbugs/issue43570.go b/test/fixedbugs/issue43570.go +new file mode 100644 +index 0000000000..d073fde5f6 +--- /dev/null ++++ b/test/fixedbugs/issue43570.go +@@ -0,0 +1,40 @@ ++// run ++ ++// Copyright 2021 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 main ++ ++import "fmt" ++ ++type T [8]*int ++ ++//go:noinline ++func f(x int) T { ++ return T{} ++} ++ ++//go:noinline ++func g(x int, t T) { ++ if t != (T{}) { ++ panic(fmt.Sprintf("bad: %v", t)) ++ } ++} ++ ++func main() { ++ const N = 10000 ++ var q T ++ func() { ++ for i := 0; i < N; i++ { ++ q = f(0) ++ g(0, q) ++ sink = make([]byte, 1024) ++ } ++ }() ++ // Note that the closure is a trick to get the write to q to be a ++ // write to a pointer that is known to be non-nil and requires ++ // a write barrier. ++} ++ ++var sink []byte +-- +2.27.0 + diff --git a/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch b/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch deleted file mode 100644 index bb83fced3b9a42c3a75e18d8b7bede43e96eee3d..0000000000000000000000000000000000000000 --- a/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch +++ /dev/null @@ -1,101 +0,0 @@ -From fa95a1d8e7eda9ab90a7fd29785cad0ae7d816e2 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 09:54:22 +0800 -Subject: [PATCH 1/6] syscall: implement rawVforkSyscall for linux/arm64 - -This allows the use of CLONE_VFORK and CLONE_VM for fork/exec, preventing -"fork/exec ...: cannot allocate memory" failures from occuring when attempting -to execute commands from a Go process that has a large memory footprint. -Additionally, this should reduce the latency of fork/exec on linux/arm64. - -With CLONE_VM the child process shares the same memory with the parent -process. On its own this would lead to conflicting use of the same -memory, so CLONE_VFORK is used to suspend the parent process until the -child releases the memory when switching to the new program binary -via the exec syscall. When the parent process continues to run, one -has to consider the changes to memory that the child process did, -namely the return address of the syscall function needs to be restored -from a register. - -exec.Command() callers can start in a faster manner, as child process who -do exec commands job can be cloned faster via vfork than via fork on arm64. - -The same problem was addressed on linux/amd64 via issue #5838. - -Updates #31936 -Contributed by Howard Zhang and Bin Lu - -Change-Id: Ia99d81d877f564ec60d19f17e596276836576eaf -Reviewed-on: https://go-review.googlesource.com/c/go/+/189418 -Run-TryBot: Tobias Klauser -TryBot-Result: Gobot Gobot -Reviewed-by: Tobias Klauser -Reviewed-by: Cherry Zhang ---- - src/syscall/asm_linux_arm64.s | 23 +++++++++++++++++++++++ - src/syscall/exec_linux.go | 2 +- - src/syscall/syscall_linux_arm64.go | 4 +--- - 3 files changed, 25 insertions(+), 4 deletions(-) - -diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s -index 7edeafc..fb22f8d 100644 ---- a/src/syscall/asm_linux_arm64.s -+++ b/src/syscall/asm_linux_arm64.s -@@ -103,6 +103,29 @@ ok: - MOVD ZR, err+72(FP) // errno - RET - -+// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) -+TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 -+ MOVD a1+8(FP), R0 -+ MOVD $0, R1 -+ MOVD $0, R2 -+ MOVD $0, R3 -+ MOVD $0, R4 -+ MOVD $0, R5 -+ MOVD trap+0(FP), R8 // syscall entry -+ SVC -+ CMN $4095, R0 -+ BCC ok -+ MOVD $-1, R4 -+ MOVD R4, r1+16(FP) // r1 -+ NEG R0, R0 -+ MOVD R0, err+24(FP) // errno -+ RET -+ok: -+ MOVD R0, r1+16(FP) // r1 -+ MOVD ZR, err+24(FP) // errno -+ RET -+ -+ - // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); - TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 - MOVD a1+8(FP), R0 -diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go -index a2242b2..3540d51 100644 ---- a/src/syscall/exec_linux.go -+++ b/src/syscall/exec_linux.go -@@ -196,7 +196,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att - } - } - -- hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" -+ hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" - - // About to call fork. - // No more allocation or calls of non-assembly functions. -diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go -index 48ad0bb..89b2ab2 100644 ---- a/src/syscall/syscall_linux_arm64.go -+++ b/src/syscall/syscall_linux_arm64.go -@@ -154,6 +154,4 @@ const ( - SYS_EPOLL_WAIT = 1069 - ) - --func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { -- panic("not implemented") --} -+func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) --- -2.17.1 - diff --git a/0005-release-branch.go1.15-cmd-go-fix-get_update_unknown_.patch b/0005-release-branch.go1.15-cmd-go-fix-get_update_unknown_.patch new file mode 100644 index 0000000000000000000000000000000000000000..7c01a1940ca6c925b6c52ad36cf96a473f93676d --- /dev/null +++ b/0005-release-branch.go1.15-cmd-go-fix-get_update_unknown_.patch @@ -0,0 +1,47 @@ +From 9bb97ea047890e900dae04202a231685492c4b18 Mon Sep 17 00:00:00 2001 +From: Jay Conrod +Date: Fri, 22 Jan 2021 16:59:16 -0500 +Subject: [PATCH 05/44] [release-branch.go1.15] cmd/go: fix + get_update_unknown_protocol test + +This test needs to run in GOPATH mode. It broke when a go.mod file was +added to github.com/golang/example. This change sets GO111MODULE=off, +which matches master since CL 255051. + +Fixes #43861 + +Change-Id: I9ea109a99509fac3185756a0f0d852a84c677bf5 +Reviewed-on: https://go-review.googlesource.com/c/go/+/285956 +Trust: Jay Conrod +Run-TryBot: Jay Conrod +TryBot-Result: Go Bot +Reviewed-by: Bryan C. Mills + +Conflict:NA +Reference:https://github.com/golang/go/commit/9bb97ea047890e900dae04202a231685492c4b18 + +--- + src/cmd/go/testdata/script/get_update_unknown_protocol.txt | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/cmd/go/testdata/script/get_update_unknown_protocol.txt b/src/cmd/go/testdata/script/get_update_unknown_protocol.txt +index 85c2e24bc8..b00adea70b 100644 +--- a/src/cmd/go/testdata/script/get_update_unknown_protocol.txt ++++ b/src/cmd/go/testdata/script/get_update_unknown_protocol.txt +@@ -1,5 +1,6 @@ + [!net] skip + [!exec:git] skip ++env GO111MODULE=off + + # Clone the repo via HTTPS manually. + exec git clone -q https://github.com/golang/example github.com/golang/example +@@ -10,4 +11,4 @@ cd github.com/golang/example + exec git remote set-url origin xyz://github.com/golang/example + exec git config --local url.https://github.com/.insteadOf xyz://github.com/ + +-go get -d -u -f github.com/golang/example/hello +\ No newline at end of file ++go get -d -u -f github.com/golang/example/hello +-- +2.27.0 + diff --git a/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch b/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch deleted file mode 100644 index 5106d5a3b822adfc0c2c36e06eb9275a975a191d..0000000000000000000000000000000000000000 --- a/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 8a755c0f0389dca42ec8caef0efa9b6ebe9d1e3c Mon Sep 17 00:00:00 2001 -From: Yuichi Nishiwaki -Date: Wed, 11 Sep 2019 02:26:02 +0000 -Subject: [PATCH 2/6] runtime: fix crash during VDSO calls on arm - -As discussed in #32912, a crash occurs when go runtime calls a VDSO function (say -__vdso_clock_gettime) and a signal arrives to that thread. -Since VDSO functions temporarily destroy the G register (R10), -Go functions asynchronously executed in that thread (i.e. Go's signal -handler) can try to load data from the destroyed G, which causes -segmentation fault. - -To fix the issue a guard is inserted in front of sigtrampgo, so that the control escapes from -signal handlers without touching G in case the signal occurred in the VDSO context. -The test case included in the patch is take from discussion in a relevant thread on github: -https://github.com/golang/go/issues/32912#issuecomment-517874531. -This patch not only fixes the issue on AArch64 but also that on 32bit ARM. - -Fixes #32912 - -Change-Id: I657472e54b7aa3c617fabc5019ce63aa4105624a -GitHub-Last-Rev: 28ce42c4a02a060f08c1b0dd1c9a392123fd2ee9 -GitHub-Pull-Request: golang/go#34030 -Reviewed-on: https://go-review.googlesource.com/c/go/+/192937 -Run-TryBot: Ian Lance Taylor -TryBot-Result: Gobot Gobot -Reviewed-by: Ian Lance Taylor ---- - src/runtime/crash_test.go | 9 +++++ - src/runtime/signal_unix.go | 27 ++++++++++--- - src/runtime/testdata/testprog/vdso.go | 55 +++++++++++++++++++++++++++ - src/runtime/vdso_linux.go | 1 + - 4 files changed, 86 insertions(+), 6 deletions(-) - create mode 100644 src/runtime/testdata/testprog/vdso.go - -diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go -index c54bb57..c2cab7c 100644 ---- a/src/runtime/crash_test.go -+++ b/src/runtime/crash_test.go -@@ -143,6 +143,15 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) - return exe, nil - } - -+func TestVDSO(t *testing.T) { -+ t.Parallel() -+ output := runTestProg(t, "testprog", "SignalInVDSO") -+ want := "success\n" -+ if output != want { -+ t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want); -+ } -+} -+ - var ( - staleRuntimeOnce sync.Once // guards init of staleRuntimeErr - staleRuntimeErr error -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index ad51dc1..63fb07f 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -274,6 +274,21 @@ func sigpipe() { - dieFromSignal(_SIGPIPE) - } - -+// sigFetchG fetches the value of G safely when running in a signal handler. -+// On some architectures, the g value may be clobbered when running in a VDSO. -+// See issue #32912. -+// -+//go:nosplit -+func sigFetchG(c *sigctxt) *g { -+ switch GOARCH { -+ case "arm", "arm64", "ppc64", "ppc64le": -+ if inVDSOPage(c.sigpc()) { -+ return nil -+ } -+ } -+ return getg() -+} -+ - // sigtrampgo is called from the signal handler function, sigtramp, - // written in assembly code. - // This is called by the signal handler, and the world may be stopped. -@@ -289,9 +304,9 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { - if sigfwdgo(sig, info, ctx) { - return - } -- g := getg() -+ c := &sigctxt{info, ctx} -+ g := sigFetchG(c) - if g == nil { -- c := &sigctxt{info, ctx} - if sig == _SIGPROF { - sigprofNonGoPC(c.sigpc()) - return -@@ -347,7 +362,6 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { - signalDuringFork(sig) - } - -- c := &sigctxt{info, ctx} - c.fixsigcode(sig) - sighandler(sig, info, ctx, g) - setg(g) -@@ -650,9 +664,10 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { - return false - } - // Determine if the signal occurred inside Go code. We test that: -- // (1) we were in a goroutine (i.e., m.curg != nil), and -- // (2) we weren't in CGO. -- g := getg() -+ // (1) we weren't in VDSO page, -+ // (2) we were in a goroutine (i.e., m.curg != nil), and -+ // (3) we weren't in CGO. -+ g := sigFetchG(c) - if g != nil && g.m != nil && g.m.curg != nil && !g.m.incgo { - return false - } -diff --git a/src/runtime/testdata/testprog/vdso.go b/src/runtime/testdata/testprog/vdso.go -new file mode 100644 -index 0000000..6036f45 ---- /dev/null -+++ b/src/runtime/testdata/testprog/vdso.go -@@ -0,0 +1,55 @@ -+// Copyright 2019 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. -+ -+// Invoke signal hander in the VDSO context (see issue 32912). -+ -+package main -+ -+import ( -+ "fmt" -+ "io/ioutil" -+ "os" -+ "runtime/pprof" -+ "time" -+) -+ -+func init() { -+ register("SignalInVDSO", signalInVDSO) -+} -+ -+func signalInVDSO() { -+ f, err := ioutil.TempFile("", "timeprofnow") -+ if err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ if err := pprof.StartCPUProfile(f); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ t0 := time.Now() -+ t1 := t0 -+ // We should get a profiling signal 100 times a second, -+ // so running for 1 second should be sufficient. -+ for t1.Sub(t0) < time.Second { -+ t1 = time.Now() -+ } -+ -+ pprof.StopCPUProfile() -+ -+ name := f.Name() -+ if err := f.Close(); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ if err := os.Remove(name); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ fmt.Println("success"); -+} -diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go -index 71ba4ce..8518276 100644 ---- a/src/runtime/vdso_linux.go -+++ b/src/runtime/vdso_linux.go -@@ -281,6 +281,7 @@ func vdsoauxv(tag, val uintptr) { - } - - // vdsoMarker reports whether PC is on the VDSO page. -+//go:nosplit - func inVDSOPage(pc uintptr) bool { - for _, k := range vdsoSymbolKeys { - if *k.ptr != 0 { --- -2.17.1 - diff --git a/0006-release-branch.go1.15-net-http-update-bundled-x-net-.patch b/0006-release-branch.go1.15-net-http-update-bundled-x-net-.patch new file mode 100644 index 0000000000000000000000000000000000000000..35e6235d3086f30c94a948dca5d669f35e9d36f2 --- /dev/null +++ b/0006-release-branch.go1.15-net-http-update-bundled-x-net-.patch @@ -0,0 +1,106 @@ +From a01db0df00fed281f6a9673eb93fe6acae6197cf Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Fri, 29 Jan 2021 11:01:37 -0800 +Subject: [PATCH 06/44] [release-branch.go1.15] net/http: update bundled + x/net/http2 + +Updates bundled http2 to x/net git rev 16c2bbf55 for: + + http2: send a nil error if we cancel a delayed body write + https://golang.org/cl/288013 + + http2: wait until the request body has been written + https://golang.org/cl/288012 + +Created by: + +go mod edit -replace=golang.org/x/net=golang.org/x/net@release-branch.go1.15-bundle +GOFLAGS='-mod=mod' go generate -run=bundle std +go mod edit -dropreplace=golang.org/x/net +go get -d golang.org/x/net@release-branch.go1.15 +go mod tidy +go mod vendor + +Fixes golang/go#42539 + +Change-Id: I299c6d4a67ebc036e45c978e4d03cba73717b363 +Reviewed-on: https://go-review.googlesource.com/c/go/+/288112 +Trust: Damien Neil +Run-TryBot: Damien Neil +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/a01db0df00fed281f6a9673eb93fe6acae6197cf + +--- + src/net/http/h2_bundle.go | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go +index b03b84d2f3..678c6eb9d4 100644 +--- a/src/net/http/h2_bundle.go ++++ b/src/net/http/h2_bundle.go +@@ -7592,6 +7592,9 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + // we can keep it. + bodyWriter.cancel() + cs.abortRequestBodyWrite(http2errStopReqBodyWrite) ++ if hasBody && !bodyWritten { ++ <-bodyWriter.resc ++ } + } + if re.err != nil { + cc.forgetStreamID(cs.ID) +@@ -7612,6 +7615,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + } else { + bodyWriter.cancel() + cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) ++ <-bodyWriter.resc + } + cc.forgetStreamID(cs.ID) + return nil, cs.getStartedWrite(), http2errTimeout +@@ -7621,6 +7625,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + } else { + bodyWriter.cancel() + cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) ++ <-bodyWriter.resc + } + cc.forgetStreamID(cs.ID) + return nil, cs.getStartedWrite(), ctx.Err() +@@ -7630,6 +7635,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + } else { + bodyWriter.cancel() + cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) ++ <-bodyWriter.resc + } + cc.forgetStreamID(cs.ID) + return nil, cs.getStartedWrite(), http2errRequestCanceled +@@ -7639,6 +7645,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + // forgetStreamID. + return nil, cs.getStartedWrite(), cs.resetErr + case err := <-bodyWriter.resc: ++ bodyWritten = true + // Prefer the read loop's response, if available. Issue 16102. + select { + case re := <-readLoopResCh: +@@ -7649,7 +7656,6 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe + cc.forgetStreamID(cs.ID) + return nil, cs.getStartedWrite(), err + } +- bodyWritten = true + if d := cc.responseHeaderTimeout(); d != 0 { + timer := time.NewTimer(d) + defer timer.Stop() +@@ -9060,7 +9066,9 @@ func (t *http2Transport) getBodyWriterState(cs *http2clientStream, body io.Reade + + func (s http2bodyWriterState) cancel() { + if s.timer != nil { +- s.timer.Stop() ++ if s.timer.Stop() { ++ s.resc <- nil ++ } + } + } + +-- +2.27.0 + diff --git a/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch b/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch deleted file mode 100644 index 717fcd96e70b5c1c5ef1ae804e7c5a042e0bc7f9..0000000000000000000000000000000000000000 --- a/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 4717d9a1a21dfe051a14f033615218d833371d68 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 10:19:13 +0800 -Subject: [PATCH 3/6] runtime: save/fetch g register during VDSO on ARM and - ARM64 - -On ARM and ARM64, during a VDSO call, the g register may be -temporarily clobbered by the VDSO code. If a signal is received -during the execution of VDSO code, we may not find a valid g -reading the g register. In CL 192937, we conservatively assume -g is nil. But this approach has a problem: we cannot handle -the signal in this case. Further, if the signal is not a -profiling signal, we'll call badsignal, which calls needm, which -wants to get an extra m, but we don't have one in a non-cgo -binary, which cuases the program to hang. - -This is even more of a problem with async preemption, where we -will receive more signals than before. I ran into this problem -while working on async preemption support on ARM64. - -In this CL, before making a VDSO call, we save the g on the -gsignal stack. When we receive a signal, we will be running on -the gsignal stack, so we can fetch the g from there and move on. - -We probably want to do the same for PPC64. Currently we rely on -that the VDSO code doesn't actually clobber the g register, but -this is not guaranteed and we don't have control with. - -Idea from discussion with Dan Cross and Austin. - -Should fix #34391. - -Change-Id: Idbefc5e4c2f4373192c2be797be0140ae08b26e3 -Reviewed-on: https://go-review.googlesource.com/c/go/+/202759 -Run-TryBot: Cherry Zhang -Reviewed-by: Austin Clements ---- - src/os/signal/signal_test.go | 49 +++++++++++++++++++++++++++++++++++ - src/runtime/proc.go | 3 +++ - src/runtime/signal_unix.go | 24 ++++++++++++----- - src/runtime/sys_linux_arm.s | 32 +++++++++++++++++++++++ - src/runtime/sys_linux_arm64.s | 28 ++++++++++++++++++++ - 5 files changed, 129 insertions(+), 7 deletions(-) - -diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go -index 6ea59f4..c8274ea 100644 ---- a/src/os/signal/signal_test.go -+++ b/src/os/signal/signal_test.go -@@ -453,3 +453,52 @@ func atomicStopTestProgram() { - - os.Exit(0) - } -+ -+func TestTime(t *testing.T) { -+ // Test that signal works fine when we are in a call to get time, -+ // which on some platforms is using VDSO. See issue #34391. -+ dur := 3 * time.Second -+ if testing.Short() { -+ dur = 100 * time.Millisecond -+ } -+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) -+ done := make(chan bool) -+ finished := make(chan bool) -+ go func() { -+ sig := make(chan os.Signal, 1) -+ Notify(sig, syscall.SIGUSR1) -+ defer Stop(sig) -+ Loop: -+ for { -+ select { -+ case <-sig: -+ case <-done: -+ break Loop -+ } -+ } -+ finished <- true -+ }() -+ go func() { -+ Loop: -+ for { -+ select { -+ case <-done: -+ break Loop -+ default: -+ syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) -+ runtime.Gosched() -+ } -+ } -+ finished <- true -+ }() -+ t0 := time.Now() -+ for t1 := t0; t1.Sub(t0) < dur; t1 = time.Now() { -+ } // hammering on getting time -+ close(done) -+ <-finished -+ <-finished -+ // When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip -+ // into subsequent TestSignal() causing failure. -+ // Sleep for a while to reduce the possibility of the failure. -+ time.Sleep(10 * time.Millisecond) -+} -diff --git a/src/runtime/proc.go b/src/runtime/proc.go -index 93d329d..1487647 100644 ---- a/src/runtime/proc.go -+++ b/src/runtime/proc.go -@@ -3237,6 +3237,9 @@ func malg(stacksize int32) *g { - }) - newg.stackguard0 = newg.stack.lo + _StackGuard - newg.stackguard1 = ^uintptr(0) -+ // Clear the bottom word of the stack. We record g -+ // there on gsignal stack during VDSO on ARM and ARM64. -+ *(*uintptr)(unsafe.Pointer(newg.stack.lo)) = 0 - } - return newg - } -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index 63fb07f..2cf1e3b 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -280,13 +280,23 @@ func sigpipe() { - // - //go:nosplit - func sigFetchG(c *sigctxt) *g { -- switch GOARCH { -- case "arm", "arm64", "ppc64", "ppc64le": -- if inVDSOPage(c.sigpc()) { -- return nil -- } -- } -- return getg() -+ switch GOARCH { -+ case "arm", "arm64": -+ if inVDSOPage(c.sigpc()) { -+ // Before making a VDSO call we save the g to the bottom of the -+ // signal stack. Fetch from there. -+ // TODO: in efence mode, stack is sysAlloc'd, so this wouldn't -+ // work. -+ sp := getcallersp() -+ s := spanOf(sp) -+ if s != nil && s.state == mSpanManual && s.base() < sp && sp < s.limit { -+ gp := *(**g)(unsafe.Pointer(s.base())) -+ return gp -+ } -+ return nil -+ } -+ } -+ return getg() - } - - // sigtrampgo is called from the signal handler function, sigtramp, -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index 9c73984..26e12a8 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -246,7 +246,23 @@ noswitch: - CMP $0, R11 - B.EQ fallback - -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVW m_gsignal(R5), R6 // g.m.gsignal -+ CMP $0, R6 -+ BEQ 3(PC) -+ MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo -+ MOVW g, (R6) -+ - BL (R11) -+ -+ CMP $0, R6 // R6 is unchanged by C code -+ BEQ 3(PC) -+ MOVW $0, R1 -+ MOVW R1, (R6) // clear g slot -+ - JMP finish - - fallback: -@@ -297,7 +313,23 @@ noswitch: - CMP $0, R11 - B.EQ fallback - -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVW m_gsignal(R5), R6 // g.m.gsignal -+ CMP $0, R6 -+ BEQ 3(PC) -+ MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo -+ MOVW g, (R6) -+ - BL (R11) -+ -+ CMP $0, R6 // R6 is unchanged by C code -+ BEQ 3(PC) -+ MOVW $0, R1 -+ MOVW R1, (R6) // clear g slot -+ - JMP finish - - fallback: -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index 2835b6c..fd40bf9 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -207,7 +207,21 @@ noswitch: - MOVW $CLOCK_REALTIME, R0 - MOVD runtime·vdsoClockgettimeSym(SB), R2 - CBZ R2, fallback -+ -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVD m_gsignal(R21), R22 // g.m.gsignal -+ CBZ R22, 3(PC) -+ MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo -+ MOVD g, (R22) -+ - BL (R2) -+ -+ CBZ R22, 2(PC) // R22 is unchanged by C code -+ MOVD ZR, (R22) // clear g slot -+ - B finish - - fallback: -@@ -250,7 +264,21 @@ noswitch: - MOVW $CLOCK_MONOTONIC, R0 - MOVD runtime·vdsoClockgettimeSym(SB), R2 - CBZ R2, fallback -+ -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVD m_gsignal(R21), R22 // g.m.gsignal -+ CBZ R22, 3(PC) -+ MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo -+ MOVD g, (R22) -+ - BL (R2) -+ -+ CBZ R22, 2(PC) // R22 is unchanged by C code -+ MOVD ZR, (R22) // clear g slot -+ - B finish - - fallback: --- -2.17.1 - diff --git a/0007-release-branch.go1.15-cmd-go-don-t-lookup-the-path-f.patch b/0007-release-branch.go1.15-cmd-go-don-t-lookup-the-path-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..69747bbd84412a562953978f29d8d7d1502809a6 --- /dev/null +++ b/0007-release-branch.go1.15-cmd-go-don-t-lookup-the-path-f.patch @@ -0,0 +1,208 @@ +From 4a48a7d7bda25a844a7e597e96041b55c9f32d4d Mon Sep 17 00:00:00 2001 +From: Jay Conrod +Date: Fri, 22 Jan 2021 14:27:24 -0500 +Subject: [PATCH 07/44] [release-branch.go1.15] cmd/go: don't lookup the path + for CC when invoking cgo + +Previously, if CC was a path without separators (like gcc or clang), +we'd look it up in PATH in cmd/go using internal/execabs.LookPath, +then pass the resolved path to cgo in CC. + +This caused a regression: if the directory in PATH containing CC has a +space, cgo splits it and interprets it as multiple arguments. + +With this change, cmd/go no longer resolves CC before invoking +cgo. cgo does the path lookup on each invocation. This reverts the +security fix CL 284780, but that was redundant with the addition of +internal/execabs (CL 955304), which still protects us. + +NOTE: This CL includes a related test fix from CL 286292. + +Fixes #43860 + +Change-Id: I65d91a1e303856df8653881eb6e2e75a3bf95c49 +Reviewed-on: https://go-review.googlesource.com/c/go/+/285873 +Trust: Jay Conrod +Run-TryBot: Jay Conrod +TryBot-Result: Go Bot +Reviewed-by: Bryan C. Mills +(cherry picked from commit a2cef9b544708ecae983ed8836ee2425a28aab68) +Reviewed-on: https://go-review.googlesource.com/c/go/+/285954 +Run-TryBot: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/4a48a7d7bda25a844a7e597e96041b55c9f32d4d + +--- + src/cmd/go/internal/work/action.go | 3 - + src/cmd/go/internal/work/exec.go | 27 ++------- + src/cmd/go/testdata/script/cgo_path.txt | 12 +++- + src/cmd/go/testdata/script/cgo_path_space.txt | 56 +++++++++++++++++++ + 4 files changed, 72 insertions(+), 26 deletions(-) + create mode 100644 src/cmd/go/testdata/script/cgo_path_space.txt + +diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go +index 03ca301bdd..6b5f9e4807 100644 +--- a/src/cmd/go/internal/work/action.go ++++ b/src/cmd/go/internal/work/action.go +@@ -56,9 +56,6 @@ type Builder struct { + id sync.Mutex + toolIDCache map[string]string // tool name -> tool ID + buildIDCache map[string]string // file name -> build ID +- +- cgoEnvOnce sync.Once +- cgoEnvCache []string + } + + // NOTE: Much of Action would not need to be exported if not for test. +diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go +index f5f9951afa..eb1efd9f82 100644 +--- a/src/cmd/go/internal/work/exec.go ++++ b/src/cmd/go/internal/work/exec.go +@@ -1081,7 +1081,10 @@ func (b *Builder) vet(a *Action) error { + } + + // TODO(rsc): Why do we pass $GCCGO to go vet? +- env := b.cgoEnv() ++ env := b.cCompilerEnv() ++ if cfg.BuildToolchainName == "gccgo" { ++ env = append(env, "GCCGO="+BuildToolchain.compiler()) ++ } + + p := a.Package + tool := VetTool +@@ -2015,24 +2018,6 @@ func (b *Builder) cCompilerEnv() []string { + return []string{"TERM=dumb"} + } + +-// cgoEnv returns environment variables to set when running cgo. +-// Some of these pass through to cgo running the C compiler, +-// so it includes cCompilerEnv. +-func (b *Builder) cgoEnv() []string { +- b.cgoEnvOnce.Do(func() { +- cc, err := exec.LookPath(b.ccExe()[0]) +- if err != nil || filepath.Base(cc) == cc { // reject relative path +- cc = "/missing-cc" +- } +- gccgo := GccgoBin +- if filepath.Base(gccgo) == gccgo { // reject relative path +- gccgo = "/missing-gccgo" +- } +- b.cgoEnvCache = append(b.cCompilerEnv(), "CC="+cc, "GCCGO="+gccgo) +- }) +- return b.cgoEnvCache +-} +- + // mkdir makes the named directory. + func (b *Builder) Mkdir(dir string) error { + // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "". +@@ -2622,7 +2607,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo + // along to the host linker. At this point in the code, cgoLDFLAGS + // consists of the original $CGO_LDFLAGS (unchecked) and all the + // flags put together from source code (checked). +- cgoenv := b.cgoEnv() ++ cgoenv := b.cCompilerEnv() + if len(cgoLDFLAGS) > 0 { + flags := make([]string, len(cgoLDFLAGS)) + for i, f := range cgoLDFLAGS { +@@ -2843,7 +2828,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe + if p.Standard && p.ImportPath == "runtime/cgo" { + cgoflags = []string{"-dynlinker"} // record path to dynamic linker + } +- return b.run(a, p.Dir, p.ImportPath, b.cgoEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) ++ return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + } + + // Run SWIG on all SWIG input files. +diff --git a/src/cmd/go/testdata/script/cgo_path.txt b/src/cmd/go/testdata/script/cgo_path.txt +index 0d15998426..3eba71bc15 100644 +--- a/src/cmd/go/testdata/script/cgo_path.txt ++++ b/src/cmd/go/testdata/script/cgo_path.txt +@@ -1,12 +1,20 @@ + [!cgo] skip + ++# Set CC explicitly to something that requires a PATH lookup. ++# Normally, the default is gcc or clang, but if CC was set during make.bash, ++# that becomes the default. ++[exec:clang] env CC=clang ++[exec:gcc] env CC=gcc ++[!exec:clang] [!exec:gcc] skip 'Unknown C compiler' ++ + env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache. + [!windows] env PATH=.:$PATH +-[!windows] chmod 0777 p/gcc p/clang ++[!windows] chmod 0755 p/gcc p/clang + [!windows] exists -exec p/gcc p/clang + [windows] exists -exec p/gcc.bat p/clang.bat + ! exists p/bug.txt +-go build -x ++! go build -x ++stderr '^cgo: exec (clang|gcc): (clang|gcc) resolves to executable in current directory \(.[/\\](clang|gcc)(.bat)?\)$' + ! exists p/bug.txt + + -- go.mod -- +diff --git a/src/cmd/go/testdata/script/cgo_path_space.txt b/src/cmd/go/testdata/script/cgo_path_space.txt +new file mode 100644 +index 0000000000..654295dc69 +--- /dev/null ++++ b/src/cmd/go/testdata/script/cgo_path_space.txt +@@ -0,0 +1,56 @@ ++# Check that if the PATH directory containing the C compiler has a space, ++# we can still use that compiler with cgo. ++# Verifies #43808. ++[!cgo] skip ++ ++# Set CC explicitly to something that requires a PATH lookup. ++# Normally, the default is gcc or clang, but if CC was set during make.bash, ++# that becomes the default. ++[exec:clang] env CC=clang ++[exec:gcc] env CC=gcc ++[!exec:clang] [!exec:gcc] skip 'Unknown C compiler' ++ ++[!windows] chmod 0755 $WORK/'program files'/clang ++[!windows] chmod 0755 $WORK/'program files'/gcc ++[!windows] exists -exec $WORK/'program files'/clang ++[!windows] exists -exec $WORK/'program files'/gcc ++[!windows] env PATH=$WORK/'program files':$PATH ++[windows] exists -exec $WORK/'program files'/gcc.bat ++[windows] exists -exec $WORK/'program files'/clang.bat ++[windows] env PATH=$WORK\'program files';%PATH% ++ ++! exists $WORK/log.txt ++? go build -x ++exists $WORK/log.txt ++rm $WORK/log.txt ++ ++# TODO(#41400, #43078): when CC is set explicitly, it should be allowed to ++# contain spaces separating arguments, and it should be possible to quote ++# arguments with spaces (including the path), as in CGO_CFLAGS and other ++# variables. For now, this doesn't work. ++[!windows] env CC=$WORK/'program files'/gcc ++[windows] env CC=$WORK\'program files'\gcc.bat ++! go build -x ++! exists $WORK/log.txt ++ ++-- go.mod -- ++module m ++ ++-- m.go -- ++package m ++ ++// #define X 1 ++import "C" ++ ++-- $WORK/program files/gcc -- ++#!/bin/sh ++ ++echo ok >$WORK/log.txt ++-- $WORK/program files/clang -- ++#!/bin/sh ++ ++echo ok >$WORK/log.txt ++-- $WORK/program files/gcc.bat -- ++echo ok >%WORK%\log.txt ++-- $WORK/program files/clang.bat -- ++echo ok >%WORK%\log.txt +-- +2.27.0 + diff --git a/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch b/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch deleted file mode 100644 index 0db9c7078fa0d164bd6c235f558e24816342f01c..0000000000000000000000000000000000000000 --- a/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch +++ /dev/null @@ -1,179 +0,0 @@ -From fce0a59fc370634fcd7de8f8691e918cdf122f7d Mon Sep 17 00:00:00 2001 -From: Cherry Zhang -Date: Thu, 31 Oct 2019 10:32:31 -0400 -Subject: [PATCH 4/6] runtime: don't fetch G from signal stack when using cgo - -When using cgo, we save G to TLS, and when a signal happens, we -load G from TLS in sigtramp. This should give us a valid G. Don't -try to fetch from the signal stack. In particular, C code may -change the signal stack or call our signal handler directly (e.g. -TSAN), so we are not necessarily running on the original gsignal -stack where we saved G. - -Also skip saving G on the signal stack when using cgo. - -Updates #35249. - -Change-Id: I40749ce6682709bd4ebfdfd9f23bd0f317fc197d -Reviewed-on: https://go-review.googlesource.com/c/go/+/204519 -Reviewed-by: Ian Lance Taylor ---- - src/runtime/signal_unix.go | 8 +++++--- - src/runtime/sys_linux_arm.s | 30 ++++++++++++++++++++++-------- - src/runtime/sys_linux_arm64.s | 26 ++++++++++++++++++++------ - 3 files changed, 47 insertions(+), 17 deletions(-) - -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index 2cf1e3b..721edb5 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -282,9 +282,11 @@ func sigpipe() { - func sigFetchG(c *sigctxt) *g { - switch GOARCH { - case "arm", "arm64": -- if inVDSOPage(c.sigpc()) { -- // Before making a VDSO call we save the g to the bottom of the -- // signal stack. Fetch from there. -+ if !iscgo && inVDSOPage(c.sigpc()) { -+ // When using cgo, we save the g on TLS and load it from there -+ // in sigtramp. Just use that. -+ // Otherwise, before making a VDSO call we save the g to the -+ // bottom of the signal stack. Fetch from there. - // TODO: in efence mode, stack is sysAlloc'd, so this wouldn't - // work. - sp := getcallersp() -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index 26e12a8..a47ac5f 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -250,21 +250,28 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVB runtime·iscgo(SB), R6 -+ CMP $0, R6 -+ BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 -- BEQ 3(PC) -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - - BL (R11) - -- CMP $0, R6 // R6 is unchanged by C code -- BEQ 3(PC) - MOVW $0, R1 -- MOVW R1, (R6) // clear g slot -+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code - - JMP finish - -+nosaveg: -+ BL (R11) -+ JMP finish -+ - fallback: - MOVW $SYS_clock_gettime, R7 - SWI $0 -@@ -317,21 +324,28 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVB runtime·iscgo(SB), R6 -+ CMP $0, R6 -+ BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 -- BEQ 3(PC) -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - - BL (R11) - -- CMP $0, R6 // R6 is unchanged by C code -- BEQ 3(PC) - MOVW $0, R1 -- MOVW R1, (R6) // clear g slot -+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code - - JMP finish - -+nosaveg: -+ BL (R11) -+ JMP finish -+ - fallback: - MOVW $SYS_clock_gettime, R7 - SWI $0 -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index fd40bf9..94c93ca 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -212,18 +212,25 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVBU runtime·iscgo(SB), R22 -+ CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal -- CBZ R22, 3(PC) -+ CBZ R22, nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - - BL (R2) - -- CBZ R22, 2(PC) // R22 is unchanged by C code -- MOVD ZR, (R22) // clear g slot -+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code - - B finish - -+nosaveg: -+ BL (R2) -+ B finish -+ - fallback: - MOVD $SYS_clock_gettime, R8 - SVC -@@ -269,18 +276,25 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVBU runtime·iscgo(SB), R22 -+ CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal -- CBZ R22, 3(PC) -+ CBZ R22, nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - - BL (R2) - -- CBZ R22, 2(PC) // R22 is unchanged by C code -- MOVD ZR, (R22) // clear g slot -+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code - - B finish - -+nosaveg: -+ BL (R2) -+ B finish -+ - fallback: - MOVD $SYS_clock_gettime, R8 - SVC --- -2.17.1 - diff --git a/0008-release-branch.go1.15-cmd-link-internal-ld-pe-fix-se.patch b/0008-release-branch.go1.15-cmd-link-internal-ld-pe-fix-se.patch new file mode 100644 index 0000000000000000000000000000000000000000..b19737a024cc0b71366c321169b3f5c4982f6d22 --- /dev/null +++ b/0008-release-branch.go1.15-cmd-link-internal-ld-pe-fix-se.patch @@ -0,0 +1,58 @@ +From aa9b48cd1837644a1555fd7a370800924cef627a Mon Sep 17 00:00:00 2001 +From: Derek Parker +Date: Wed, 25 Nov 2020 16:31:57 +0000 +Subject: [PATCH 08/44] [release-branch.go1.15] cmd/link/internal/ld/pe: fix + segfault adding resource section + +The resource symbol may have been copied to the mmap'd +output buffer. If so, certain conditions can cause that +mmap'd output buffer to be munmap'd before we get a chance +to use it. To avoid any issues we copy the data to the heap +when the resource symbol exists. + +Fixes #42384 + +Change-Id: I32ef5420802d7313a3d965b8badfbcfb9f0fba4a +GitHub-Last-Rev: 7b0f43011d06083ee3e871e48a87847636f738f9 +GitHub-Pull-Request: golang/go#42427 +Reviewed-on: https://go-review.googlesource.com/c/go/+/268018 +Run-TryBot: Carlos Amedee +TryBot-Result: Go Bot +Reviewed-by: Russ Cox +Reviewed-by: Cherry Zhang +Reviewed-by: Than McIntosh +Trust: Carlos Amedee + +Conflict:NA +Reference:https://github.com/golang/go/commit/aa9b48cd1837644a1555fd7a370800924cef627a + +--- + src/cmd/link/internal/ld/pe.go | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go +index c9cb25dbe5..5d68ca7d9c 100644 +--- a/src/cmd/link/internal/ld/pe.go ++++ b/src/cmd/link/internal/ld/pe.go +@@ -1515,6 +1515,18 @@ func Asmbpe(ctxt *Link) { + case sys.AMD64, sys.I386, sys.ARM: + } + ++ if rsrcsym != 0 { ++ // The resource symbol may have been copied to the mmap'd ++ // output buffer. If so, certain conditions can cause that ++ // mmap'd output buffer to be munmap'd before we get a chance ++ // to use it. To avoid any issues we copy the data to the heap ++ // when the resource symbol exists. ++ rsrc := ctxt.loader.Syms[rsrcsym] ++ data := make([]byte, len(rsrc.P)) ++ copy(data, rsrc.P) ++ rsrc.P = data ++ } ++ + t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length)) + t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ + if ctxt.LinkMode == LinkExternal { +-- +2.27.0 + diff --git a/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch b/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch deleted file mode 100644 index e71d11fd6dd51b1f63fbdab1b03293b5792021c0..0000000000000000000000000000000000000000 --- a/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch +++ /dev/null @@ -1,107 +0,0 @@ -From e83074ea52287115b85002a6b72137c72f6d7ecc Mon Sep 17 00:00:00 2001 -From: Cherry Zhang -Date: Sun, 10 Nov 2019 13:18:06 -0500 -Subject: [PATCH 5/6] runtime: don't save G during VDSO if we're handling - signal - -On some platforms (currently ARM and ARM64), when calling into -VDSO we store the G to the gsignal stack, if there is one, so if -we receive a signal during VDSO we can find the G. - -If we receive a signal during VDSO, and within the signal handler -we call nanotime again (e.g. when handling profiling signal), -we'll save/clear the G slot on the gsignal stack again, which -clobbers the original saved G. If we receive a second signal -during the same VDSO execution, we will fetch a nil G, which will -lead to bad things such as deadlock. - -Don't save G if we're calling VDSO code from the gsignal stack. -Saving G is not necessary as we won't receive a nested signal. - -Fixes #35473. - -Change-Id: Ibfd8587a3c70c2f1533908b056e81b94d75d65a5 -Reviewed-on: https://go-review.googlesource.com/c/go/+/206397 -Run-TryBot: Cherry Zhang -TryBot-Result: Gobot Gobot -Reviewed-by: Bryan C. Mills ---- - src/runtime/sys_linux_arm.s | 8 ++++++++ - src/runtime/sys_linux_arm64.s | 8 ++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index a47ac5f..577faac 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -252,12 +252,16 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVB runtime·iscgo(SB), R6 - CMP $0, R6 - BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 - BEQ nosaveg -+ CMP g, R6 -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - -@@ -326,12 +330,16 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVB runtime·iscgo(SB), R6 - CMP $0, R6 - BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 - BEQ nosaveg -+ CMP g, R6 -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index 94c93ca..a076744 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -214,10 +214,14 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVBU runtime·iscgo(SB), R22 - CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal - CBZ R22, nosaveg -+ CMP g, R22 -+ BEQ nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - -@@ -278,10 +282,14 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVBU runtime·iscgo(SB), R22 - CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal - CBZ R22, nosaveg -+ CMP g, R22 -+ BEQ nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - --- -2.17.1 - diff --git a/0009-release-branch.go1.15-cmd-internal-goobj2-fix-buglet.patch b/0009-release-branch.go1.15-cmd-internal-goobj2-fix-buglet.patch new file mode 100644 index 0000000000000000000000000000000000000000..97fea5b30aa0c3b07fe7bb2c871521bcb7a352c2 --- /dev/null +++ b/0009-release-branch.go1.15-cmd-internal-goobj2-fix-buglet.patch @@ -0,0 +1,73 @@ +From 58dc4452620ebefa75742661c538b8406b213b4a Mon Sep 17 00:00:00 2001 +From: Than McIntosh +Date: Tue, 15 Dec 2020 15:54:25 -0500 +Subject: [PATCH 09/44] [release-branch.go1.15] cmd/internal/goobj2: fix buglet + in object file reader + +The code in the Go object file reader was casting a pointer to mmaped +memory into a large array prior to performing a read of the +relocations section: + + return (*[1<<20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] + +For very large object files, this artificial array isn't large enough +(that is, there are more than 1048576 relocs to read), so update the +code to use a larger artifical array size. + +Fixes #43214. +Updates #41621. + +Change-Id: Ic047c8aef4f8a3839f2e7e3594bce652ebd6bd5b +Reviewed-on: https://go-review.googlesource.com/c/go/+/278492 +Run-TryBot: Than McIntosh +TryBot-Result: Go Bot +Reviewed-by: Cherry Zhang +Reviewed-by: Jeremy Faller +Trust: Than McIntosh +(cherry picked from commit f4e7a6b905ce60448e506a3f6578d01b60602cdd) +Reviewed-on: https://go-review.googlesource.com/c/go/+/278673 + +Conflict:NA +Reference:https://github.com/golang/go/commit/58dc4452620ebefa75742661c538b8406b213b4a + +--- + src/cmd/internal/goobj2/objfile.go | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/internal/goobj2/objfile.go b/src/cmd/internal/goobj2/objfile.go +index 7f728e4f76..aba9b9856e 100644 +--- a/src/cmd/internal/goobj2/objfile.go ++++ b/src/cmd/internal/goobj2/objfile.go +@@ -379,6 +379,11 @@ func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) } + // for testing + func (a *Aux) fromBytes(b []byte) { copy(a[:], b) } + ++// Used to construct an artifically large array type when reading an ++// item from the object file relocs section or aux sym section (needs ++// to work on 32-bit as well as 64-bit). See issue 41621. ++const huge = (1<<31 - 1) / RelocSize ++ + // Referenced symbol name. + // + // Serialized format: +@@ -652,7 +657,7 @@ func (r *Reader) Reloc(i int, j int) *Reloc { + func (r *Reader) Relocs(i int) []Reloc { + off := r.RelocOff(i, 0) + n := r.NReloc(i) +- return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] ++ return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] + } + + // NAux returns the number of aux symbols of the i-th symbol. +@@ -678,7 +683,7 @@ func (r *Reader) Aux(i int, j int) *Aux { + func (r *Reader) Auxs(i int) []Aux { + off := r.AuxOff(i, 0) + n := r.NAux(i) +- return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n] ++ return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n] + } + + // DataOff returns the offset of the i-th symbol's data. +-- +2.27.0 + diff --git a/0010-release-branch.go1.15-runtime-don-t-adjust-timer-pp-.patch b/0010-release-branch.go1.15-runtime-don-t-adjust-timer-pp-.patch new file mode 100644 index 0000000000000000000000000000000000000000..8484da4f7e0875fd2453c63e9d406cda2203231e --- /dev/null +++ b/0010-release-branch.go1.15-runtime-don-t-adjust-timer-pp-.patch @@ -0,0 +1,72 @@ +From 3171f483775c7eb8d38b68f53d8fd5078db7f967 Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor +Date: Tue, 19 Jan 2021 21:30:36 -0800 +Subject: [PATCH 10/44] [release-branch.go1.15] runtime: don't adjust timer pp + field in timerWaiting status + +Before this CL, the following sequence was possible: + +* GC scavenger starts and sets up scavenge.timer +* GC calls readyForScavenger, but sysmon is sleeping +* program calls runtime.GOMAXPROCS to shrink number of processors +* procresize destroys a P, the one that scavenge.timer is on +* (*pp).destroy calls moveTimers, which gets to the scavenger timer +* scavenger timer is timerWaiting, and moveTimers clears t.pp +* sysmon wakes up and calls wakeScavenger +* wakeScavengers calls stopTimer on scavenger.timer, still timerWaiting +* stopTimer calls deltimer which loads t.pp, which is still nil +* stopTimer tries to increment deletedTimers on nil t.pp, and crashes + +The point of vulnerability is the time that t.pp is set to nil by +moveTimers and the time that t.pp is set to non-nil by moveTimers, +which is a few instructions at most. So it's not likely and in +particular is quite unlikely on x86. But with a more relaxed memory +model the area of vulnerability can be somewhat larger. This appears +to tbe the cause of two builder failures in a few months on linux-mips. + +This CL fixes the problem by making moveTimers change the status from +timerWaiting to timerMoving while t.pp is clear. That will cause +deltimer to wait until the status is back to timerWaiting, at which +point t.pp has been set again. + +For #43712 +Fixes #43833 + +Change-Id: I66838319ecfbf15be66c1fac88d9bd40e2295852 +Reviewed-on: https://go-review.googlesource.com/c/go/+/284775 +Trust: Ian Lance Taylor +Reviewed-by: Michael Knyszek +Reviewed-by: Michael Pratt +(cherry picked from commit d2d155d1ae8c704a37f42fd3ebb1f3846f78e4d4) +Reviewed-on: https://go-review.googlesource.com/c/go/+/287092 +Run-TryBot: Carlos Amedee + +Conflict:NA +Reference:https://github.com/golang/go/commit/3171f483775c7eb8d38b68f53d8fd5078db7f967 + +--- + src/runtime/time.go | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/runtime/time.go b/src/runtime/time.go +index fdb5066b24..ec3eae9cca 100644 +--- a/src/runtime/time.go ++++ b/src/runtime/time.go +@@ -594,8 +594,14 @@ func moveTimers(pp *p, timers []*timer) { + for { + switch s := atomic.Load(&t.status); s { + case timerWaiting: ++ if !atomic.Cas(&t.status, s, timerMoving) { ++ continue ++ } + t.pp = 0 + doaddtimer(pp, t) ++ if !atomic.Cas(&t.status, timerMoving, timerWaiting) { ++ badTimer() ++ } + break loop + case timerModifiedEarlier, timerModifiedLater: + if !atomic.Cas(&t.status, s, timerMoving) { +-- +2.27.0 + diff --git a/0011-release-branch.go1.15-runtime-cgo-fix-Android-build-.patch b/0011-release-branch.go1.15-runtime-cgo-fix-Android-build-.patch new file mode 100644 index 0000000000000000000000000000000000000000..9fe1721db43fdd9818b170faee336b9524f35b83 --- /dev/null +++ b/0011-release-branch.go1.15-runtime-cgo-fix-Android-build-.patch @@ -0,0 +1,82 @@ +From c3e1c3800bfb56bf1b0c3d696f59f42b16bd4fc2 Mon Sep 17 00:00:00 2001 +From: Elias Naur +Date: Fri, 25 Dec 2020 11:14:11 +0100 +Subject: [PATCH 11/44] [release-branch.go1.15] runtime/cgo: fix Android build + with NDK 22 + +Fixes #43406 + +Change-Id: I7d2b70098a4ba4dcb325fb0be076043789b86135 +Reviewed-on: https://go-review.googlesource.com/c/go/+/280312 +Run-TryBot: Elias Naur +TryBot-Result: Go Bot +Reviewed-by: Ian Lance Taylor +Trust: Elias Naur +(cherry picked from commit 1d78139128d6d839d7da0aeb10b3e51b6c7c0749) +Reviewed-on: https://go-review.googlesource.com/c/go/+/289149 + +Conflict:NA +Reference:https://github.com/golang/go/commit/c3e1c3800bfb56bf1b0c3d696f59f42b16bd4fc2 + +--- + src/runtime/cgo/gcc_linux_386.c | 2 +- + src/runtime/cgo/gcc_linux_amd64.c | 2 +- + src/runtime/cgo/gcc_linux_arm.c | 2 +- + src/runtime/cgo/gcc_linux_arm64.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/runtime/cgo/gcc_linux_386.c b/src/runtime/cgo/gcc_linux_386.c +index ece9f933c5..70c942aeb8 100644 +--- a/src/runtime/cgo/gcc_linux_386.c ++++ b/src/runtime/cgo/gcc_linux_386.c +@@ -12,7 +12,7 @@ static void *threadentry(void*); + static void (*setg_gcc)(void*); + + // This will be set in gcc_android.c for android-specific customization. +-void (*x_cgo_inittls)(void **tlsg, void **tlsbase); ++void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); + + void + x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c +index 9134e0df92..f2bf6482cb 100644 +--- a/src/runtime/cgo/gcc_linux_amd64.c ++++ b/src/runtime/cgo/gcc_linux_amd64.c +@@ -14,7 +14,7 @@ static void* threadentry(void*); + static void (*setg_gcc)(void*); + + // This will be set in gcc_android.c for android-specific customization. +-void (*x_cgo_inittls)(void **tlsg, void **tlsbase); ++void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); + + void + x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +diff --git a/src/runtime/cgo/gcc_linux_arm.c b/src/runtime/cgo/gcc_linux_arm.c +index 61855b96b2..5bc0fee90d 100644 +--- a/src/runtime/cgo/gcc_linux_arm.c ++++ b/src/runtime/cgo/gcc_linux_arm.c +@@ -10,7 +10,7 @@ + + static void *threadentry(void*); + +-void (*x_cgo_inittls)(void **tlsg, void **tlsbase); ++void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); + static void (*setg_gcc)(void*); + + void +diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c +index 261c884ac9..17ff274fbb 100644 +--- a/src/runtime/cgo/gcc_linux_arm64.c ++++ b/src/runtime/cgo/gcc_linux_arm64.c +@@ -12,7 +12,7 @@ + + static void *threadentry(void*); + +-void (*x_cgo_inittls)(void **tlsg, void **tlsbase); ++void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); + static void (*setg_gcc)(void*); + + void +-- +2.27.0 + diff --git a/0013-release-branch.go1.15-internal-poll-if-copy_file_ran.patch b/0013-release-branch.go1.15-internal-poll-if-copy_file_ran.patch new file mode 100644 index 0000000000000000000000000000000000000000..6aee0f5a52935d641b9226afb7887b5e31cac7d1 --- /dev/null +++ b/0013-release-branch.go1.15-internal-poll-if-copy_file_ran.patch @@ -0,0 +1,102 @@ +From 023c46676db26e75d244b1d38ccc4a4b8bfe3eef Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor +Date: Sun, 14 Feb 2021 17:14:41 -0800 +Subject: [PATCH 13/44] [release-branch.go1.15] internal/poll: if + copy_file_range returns 0, assume it failed + +On current Linux kernels copy_file_range does not correctly handle +files in certain special file systems, such as /proc. For those file +systems it fails to copy any data and returns zero. This breaks Go's +io.Copy for those files. + +Fix the problem by assuming that if copy_file_range returns 0 the +first time it is called on a file, that that file is not supported. +In that case fall back to just using read. This will force an extra +system call when using io.Copy to copy a zero-sized normal file, +but at least it will work correctly. + +For #36817 +For #44272 +Fixes #44273 + +Change-Id: I02e81872cb70fda0ce5485e2ea712f219132e614 +Reviewed-on: https://go-review.googlesource.com/c/go/+/291989 +Trust: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-by: Russ Cox +(cherry picked from commit 30641e36aa5b547eee48565caa3078b0a2e7c185) +Reviewed-on: https://go-review.googlesource.com/c/go/+/292289 + +Conflict:NA +Reference:https://github.com/golang/go/commit/023c46676db26e75d244b1d38ccc4a4b8bfe3eef + +--- + src/internal/poll/copy_file_range_linux.go | 10 ++++++- + src/os/readfrom_linux_test.go | 32 ++++++++++++++++++++++ + 2 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/src/internal/poll/copy_file_range_linux.go b/src/internal/poll/copy_file_range_linux.go +index fc34aef4cb..01b242a4ea 100644 +--- a/src/internal/poll/copy_file_range_linux.go ++++ b/src/internal/poll/copy_file_range_linux.go +@@ -112,7 +112,15 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err + return 0, false, nil + case nil: + if n == 0 { +- // src is at EOF, which means we are done. ++ // If we did not read any bytes at all, ++ // then this file may be in a file system ++ // where copy_file_range silently fails. ++ // https://lore.kernel.org/linux-fsdevel/20210126233840.GG4626@dread.disaster.area/T/#m05753578c7f7882f6e9ffe01f981bc223edef2b0 ++ if written == 0 { ++ return 0, false, nil ++ } ++ // Otherwise src is at EOF, which means ++ // we are done. + return written, true, nil + } + remain -= n +diff --git a/src/os/readfrom_linux_test.go b/src/os/readfrom_linux_test.go +index 00faf39fe5..aa3f050667 100644 +--- a/src/os/readfrom_linux_test.go ++++ b/src/os/readfrom_linux_test.go +@@ -361,3 +361,35 @@ func (h *copyFileRangeHook) install() { + func (h *copyFileRangeHook) uninstall() { + *PollCopyFileRangeP = h.original + } ++ ++// On some kernels copy_file_range fails on files in /proc. ++func TestProcCopy(t *testing.T) { ++ const cmdlineFile = "/proc/self/cmdline" ++ cmdline, err := ioutil.ReadFile(cmdlineFile) ++ if err != nil { ++ t.Skipf("can't read /proc file: %v", err) ++ } ++ in, err := Open(cmdlineFile) ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer in.Close() ++ outFile := filepath.Join(t.TempDir(), "cmdline") ++ out, err := Create(outFile) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if _, err := io.Copy(out, in); err != nil { ++ t.Fatal(err) ++ } ++ if err := out.Close(); err != nil { ++ t.Fatal(err) ++ } ++ copy, err := ioutil.ReadFile(outFile) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if !bytes.Equal(cmdline, copy) { ++ t.Errorf("copy of %q got %q want %q\n", cmdlineFile, copy, cmdline) ++ } ++} +-- +2.27.0 + diff --git a/0014-release-branch.go1.15-internal-poll-netpollcheckerr-.patch b/0014-release-branch.go1.15-internal-poll-netpollcheckerr-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a9859a80400caf8876cd90f1feb10bd391ac4f1 --- /dev/null +++ b/0014-release-branch.go1.15-internal-poll-netpollcheckerr-.patch @@ -0,0 +1,166 @@ +From 30357d6ef6513b18fade686a629ab8d49987260f Mon Sep 17 00:00:00 2001 +From: Wei Fu +Date: Sun, 24 Jan 2021 18:21:06 +0800 +Subject: [PATCH 14/44] [release-branch.go1.15] internal/poll: netpollcheckerr + before sendfile + +In net/http package, the ServeContent/ServeFile doesn't check the I/O +timeout error from chunkWriter or *net.TCPConn, which means that both +HTTP status and headers might be missing when WriteTimeout happens. If +the poll.SendFile() doesn't check the *poll.FD state before sending +data, the client will only receive the response body with status and +report "malformed http response/status code". + +This patch is to enable netpollcheckerr before sendfile, which should +align with normal *poll.FD.Write() and Splice(). + +For #43822 +Fixes #44294 + +Change-Id: I32517e3f261bab883a58b577b813ef189214b954 +Reviewed-on: https://go-review.googlesource.com/c/go/+/285914 +Reviewed-by: Emmanuel Odeke +Trust: Emmanuel Odeke +Trust: Bryan C. Mills +Run-TryBot: Emmanuel Odeke +(cherry picked from commit f0d23c9dbb2142b975fa8fb13a57213d0c15bdd1) +Reviewed-on: https://go-review.googlesource.com/c/go/+/296530 +Trust: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/30357d6ef6513b18fade686a629ab8d49987260f + +--- + src/internal/poll/sendfile_bsd.go | 4 ++ + src/internal/poll/sendfile_linux.go | 3 ++ + src/internal/poll/sendfile_solaris.go | 3 ++ + src/net/sendfile_test.go | 64 +++++++++++++++++++++++++++ + 4 files changed, 74 insertions(+) + +diff --git a/src/internal/poll/sendfile_bsd.go b/src/internal/poll/sendfile_bsd.go +index a24e41dcaa..66005a9f5c 100644 +--- a/src/internal/poll/sendfile_bsd.go ++++ b/src/internal/poll/sendfile_bsd.go +@@ -18,6 +18,10 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) { + return 0, err + } + defer dstFD.writeUnlock() ++ if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil { ++ return 0, err ++ } ++ + dst := int(dstFD.Sysfd) + var written int64 + var err error +diff --git a/src/internal/poll/sendfile_linux.go b/src/internal/poll/sendfile_linux.go +index d64283007d..d6442e8666 100644 +--- a/src/internal/poll/sendfile_linux.go ++++ b/src/internal/poll/sendfile_linux.go +@@ -16,6 +16,9 @@ func SendFile(dstFD *FD, src int, remain int64) (int64, error) { + return 0, err + } + defer dstFD.writeUnlock() ++ if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil { ++ return 0, err ++ } + + dst := int(dstFD.Sysfd) + var written int64 +diff --git a/src/internal/poll/sendfile_solaris.go b/src/internal/poll/sendfile_solaris.go +index 762992e9eb..748c85131e 100644 +--- a/src/internal/poll/sendfile_solaris.go ++++ b/src/internal/poll/sendfile_solaris.go +@@ -20,6 +20,9 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) { + return 0, err + } + defer dstFD.writeUnlock() ++ if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil { ++ return 0, err ++ } + + dst := int(dstFD.Sysfd) + var written int64 +diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go +index 13842a1261..0e344b3649 100644 +--- a/src/net/sendfile_test.go ++++ b/src/net/sendfile_test.go +@@ -10,6 +10,7 @@ import ( + "bytes" + "crypto/sha256" + "encoding/hex" ++ "errors" + "fmt" + "io" + "io/ioutil" +@@ -314,3 +315,66 @@ func TestSendfilePipe(t *testing.T) { + + wg.Wait() + } ++ ++// Issue 43822: tests that returns EOF when conn write timeout. ++func TestSendfileOnWriteTimeoutExceeded(t *testing.T) { ++ ln, err := newLocalListener("tcp") ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer ln.Close() ++ ++ errc := make(chan error, 1) ++ go func(ln Listener) (retErr error) { ++ defer func() { ++ errc <- retErr ++ close(errc) ++ }() ++ ++ conn, err := ln.Accept() ++ if err != nil { ++ return err ++ } ++ defer conn.Close() ++ ++ // Set the write deadline in the past(1h ago). It makes ++ // sure that it is always write timeout. ++ if err := conn.SetWriteDeadline(time.Now().Add(-1 * time.Hour)); err != nil { ++ return err ++ } ++ ++ f, err := os.Open(newton) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ _, err = io.Copy(conn, f) ++ if errors.Is(err, os.ErrDeadlineExceeded) { ++ return nil ++ } ++ ++ if err == nil { ++ err = fmt.Errorf("expected ErrDeadlineExceeded, but got nil") ++ } ++ return err ++ }(ln) ++ ++ conn, err := Dial("tcp", ln.Addr().String()) ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer conn.Close() ++ ++ n, err := io.Copy(ioutil.Discard, conn) ++ if err != nil { ++ t.Fatalf("expected nil error, but got %v", err) ++ } ++ if n != 0 { ++ t.Fatalf("expected receive zero, but got %d byte(s)", n) ++ } ++ ++ if err := <-errc; err != nil { ++ t.Fatal(err) ++ } ++} +-- +2.27.0 + diff --git a/0015-release-branch.go1.15-cmd-compile-do-not-assume-TST-.patch b/0015-release-branch.go1.15-cmd-compile-do-not-assume-TST-.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab3e6dac0cc88ace5fcf0929ec6569a1b8e06cdb --- /dev/null +++ b/0015-release-branch.go1.15-cmd-compile-do-not-assume-TST-.patch @@ -0,0 +1,1281 @@ +From d9b4ef591c2b058004545eccf10a538aa7597adb Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Mon, 30 Nov 2020 10:41:46 +0100 +Subject: [PATCH 15/44] [release-branch.go1.15] cmd/compile: do not assume TST + and TEQ set V on arm + +These replacement rules assume that TST and TEQ set V. But TST and +TEQ do not set V. This is a problem because instructions like LT are +actually checking for N!=V. But with TST and TEQ not setting V, LT +doesn't do anything meaningful. It's possible to construct trivial +miscompilations from this, such as: + + package main + + var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4} + + func main() { + if x[0] > x[1] { + panic("fail 1") + } + if x[2]&x[3] < 0 { + panic("fail 2") // Fails here + } + } + +That first comparison sets V, via the CMP that subtracts the values +causing the overflow. Then the second comparison operation thinks that +it uses the result of TST, when it actually uses the V from CMP. + +Before this fix: + + TST R0, R1 + BLT loc_6C164 + +After this fix: + + TST R0, R1 + BMI loc_6C164 + +The BMI instruction checks the N flag, which TST sets. This commit +fixes the issue by using [LG][TE]noov instead of vanilla [LG][TE], and +also adds a test case for the direct issue. + +Updates #42876. +Fixes #42930. + +Change-Id: I13c62c88d18574247ad002b671b38d2d0b0fc6fa +Reviewed-on: https://go-review.googlesource.com/c/go/+/282432 +Trust: Jason A. Donenfeld +Run-TryBot: Jason A. Donenfeld +TryBot-Result: Go Bot +Reviewed-by: Cherry Zhang + +Conflict:NA +Reference:https://github.com/golang/go/commit/d9b4ef591c2b058004545eccf10a538aa7597adb + +--- + src/cmd/compile/internal/ssa/gen/ARM.rules | 128 ++++----- + src/cmd/compile/internal/ssa/rewriteARM.go | 306 ++++++++++----------- + test/fixedbugs/issue42876.go | 18 ++ + 3 files changed, 235 insertions(+), 217 deletions(-) + create mode 100644 test/fixedbugs/issue42876.go + +diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules +index ab8bd0e81e..c69084a701 100644 +--- a/src/cmd/compile/internal/ssa/gen/ARM.rules ++++ b/src/cmd/compile/internal/ssa/gen/ARM.rules +@@ -1369,38 +1369,38 @@ + (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no) + (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no) + (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no) +-(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no) +-(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no) +-(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no) +-(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRL x y [c]) yes no) +-(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRA x y [c]) yes no) +-(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftLLreg x y z) yes no) +-(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRLreg x y z) yes no) +-(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRAreg x y z) yes no) +-(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LE (TST x y) yes no) +-(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LE (TSTconst [c] x) yes no) +-(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftLL x y [c]) yes no) +-(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRL x y [c]) yes no) +-(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRA x y [c]) yes no) +-(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftLLreg x y z) yes no) +-(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRLreg x y z) yes no) +-(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRAreg x y z) yes no) +-(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LT (TEQ x y) yes no) +-(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LT (TEQconst [c] x) yes no) +-(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftLL x y [c]) yes no) +-(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRL x y [c]) yes no) +-(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRA x y [c]) yes no) +-(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftLLreg x y z) yes no) +-(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRLreg x y z) yes no) +-(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRAreg x y z) yes no) +-(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LE (TEQ x y) yes no) +-(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LE (TEQconst [c] x) yes no) +-(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftLL x y [c]) yes no) +-(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRL x y [c]) yes no) +-(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRA x y [c]) yes no) +-(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no) +-(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no) +-(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no) ++(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LTnoov (TST x y) yes no) ++(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (TSTconst [c] x) yes no) ++(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftLL x y [c]) yes no) ++(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRL x y [c]) yes no) ++(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRA x y [c]) yes no) ++(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftLLreg x y z) yes no) ++(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRLreg x y z) yes no) ++(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRAreg x y z) yes no) ++(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LEnoov (TST x y) yes no) ++(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (TSTconst [c] x) yes no) ++(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftLL x y [c]) yes no) ++(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRL x y [c]) yes no) ++(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRA x y [c]) yes no) ++(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftLLreg x y z) yes no) ++(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRLreg x y z) yes no) ++(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRAreg x y z) yes no) ++(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LTnoov (TEQ x y) yes no) ++(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (TEQconst [c] x) yes no) ++(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftLL x y [c]) yes no) ++(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRL x y [c]) yes no) ++(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRA x y [c]) yes no) ++(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftLLreg x y z) yes no) ++(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRLreg x y z) yes no) ++(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRAreg x y z) yes no) ++(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LEnoov (TEQ x y) yes no) ++(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (TEQconst [c] x) yes no) ++(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftLL x y [c]) yes no) ++(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRL x y [c]) yes no) ++(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRA x y [c]) yes no) ++(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftLLreg x y z) yes no) ++(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRLreg x y z) yes no) ++(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRAreg x y z) yes no) + (GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no) + (GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL x y)) yes no) + (GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no) +@@ -1436,39 +1436,39 @@ + (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no) + (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no) + (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no) +-(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no) + (GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL x y)) yes no) +-(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no) +-(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no) +-(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no) +-(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRA x y [c]) yes no) +-(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftLLreg x y z) yes no) +-(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRLreg x y z) yes no) +-(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRAreg x y z) yes no) +-(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GE (TST x y) yes no) +-(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GE (TSTconst [c] x) yes no) +-(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftLL x y [c]) yes no) +-(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRL x y [c]) yes no) +-(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRA x y [c]) yes no) +-(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftLLreg x y z) yes no) +-(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRLreg x y z) yes no) +-(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRAreg x y z) yes no) +-(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GT (TEQ x y) yes no) +-(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GT (TEQconst [c] x) yes no) +-(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftLL x y [c]) yes no) +-(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRL x y [c]) yes no) +-(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRA x y [c]) yes no) +-(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftLLreg x y z) yes no) +-(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRLreg x y z) yes no) +-(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRAreg x y z) yes no) +-(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GE (TEQ x y) yes no) +-(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GE (TEQconst [c] x) yes no) +-(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftLL x y [c]) yes no) +-(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRL x y [c]) yes no) +-(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRA x y [c]) yes no) +-(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftLLreg x y z) yes no) +-(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRLreg x y z) yes no) +-(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRAreg x y z) yes no) ++(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GTnoov (TST x y) yes no) ++(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (TSTconst [c] x) yes no) ++(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftLL x y [c]) yes no) ++(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRL x y [c]) yes no) ++(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRA x y [c]) yes no) ++(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftLLreg x y z) yes no) ++(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRLreg x y z) yes no) ++(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRAreg x y z) yes no) ++(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GEnoov (TST x y) yes no) ++(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (TSTconst [c] x) yes no) ++(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftLL x y [c]) yes no) ++(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRL x y [c]) yes no) ++(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRA x y [c]) yes no) ++(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftLLreg x y z) yes no) ++(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRLreg x y z) yes no) ++(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRAreg x y z) yes no) ++(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GTnoov (TEQ x y) yes no) ++(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (TEQconst [c] x) yes no) ++(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftLL x y [c]) yes no) ++(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRL x y [c]) yes no) ++(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRA x y [c]) yes no) ++(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftLLreg x y z) yes no) ++(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRLreg x y z) yes no) ++(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRAreg x y z) yes no) ++(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GEnoov (TEQ x y) yes no) ++(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (TEQconst [c] x) yes no) ++(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftLL x y [c]) yes no) ++(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRL x y [c]) yes no) ++(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRA x y [c]) yes no) ++(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftLLreg x y z) yes no) ++(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRLreg x y z) yes no) ++(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRAreg x y z) yes no) + + (MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read8(sym, off))]) + (MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read16(sym, off, config.ctxt.Arch.ByteOrder))]) +diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go +index f55e542505..07653b78f8 100644 +--- a/src/cmd/compile/internal/ssa/rewriteARM.go ++++ b/src/cmd/compile/internal/ssa/rewriteARM.go +@@ -17278,7 +17278,7 @@ func rewriteBlockARM(b *Block) bool { + } + // match: (GE (CMPconst [0] l:(AND x y)) yes no) + // cond: l.Uses==1 +- // result: (GE (TST x y) yes no) ++ // result: (GEnoov (TST x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17299,14 +17299,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + break + } + // match: (GE (CMPconst [0] l:(ANDconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTconst [c] x) yes no) ++ // result: (GEnoov (TSTconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17324,12 +17324,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftLL x y [c]) yes no) ++ // result: (GEnoov (TSTshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17348,12 +17348,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftRL x y [c]) yes no) ++ // result: (GEnoov (TSTshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17372,12 +17372,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftRA x y [c]) yes no) ++ // result: (GEnoov (TSTshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17396,12 +17396,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftLLreg x y z) yes no) ++ // result: (GEnoov (TSTshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17419,12 +17419,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftRLreg x y z) yes no) ++ // result: (GEnoov (TSTshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17442,12 +17442,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TSTshiftRAreg x y z) yes no) ++ // result: (GEnoov (TSTshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17465,12 +17465,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XOR x y)) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQ x y) yes no) ++ // result: (GEnoov (TEQ x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17491,14 +17491,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + break + } + // match: (GE (CMPconst [0] l:(XORconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQconst [c] x) yes no) ++ // result: (GEnoov (TEQconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17516,12 +17516,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftLL x y [c]) yes no) ++ // result: (GEnoov (TEQshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17540,12 +17540,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftRL x y [c]) yes no) ++ // result: (GEnoov (TEQshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17564,12 +17564,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftRA x y [c]) yes no) ++ // result: (GEnoov (TEQshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17588,12 +17588,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftLLreg x y z) yes no) ++ // result: (GEnoov (TEQshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17611,12 +17611,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftRLreg x y z) yes no) ++ // result: (GEnoov (TEQshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17634,12 +17634,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + // match: (GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GE (TEQshiftRAreg x y z) yes no) ++ // result: (GEnoov (TEQshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -17657,7 +17657,7 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGE, v0) ++ b.resetWithControl(BlockARMGEnoov, v0) + return true + } + case BlockARMGEnoov: +@@ -18131,9 +18131,34 @@ func rewriteBlockARM(b *Block) bool { + b.resetWithControl(BlockARMGTnoov, v0) + return true + } ++ // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) ++ // cond: l.Uses==1 ++ // result: (GTnoov (CMN a (MUL x y)) yes no) ++ for b.Controls[0].Op == OpARMCMPconst { ++ v_0 := b.Controls[0] ++ if v_0.AuxInt != 0 { ++ break ++ } ++ l := v_0.Args[0] ++ if l.Op != OpARMMULA { ++ break ++ } ++ a := l.Args[2] ++ x := l.Args[0] ++ y := l.Args[1] ++ if !(l.Uses == 1) { ++ break ++ } ++ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) ++ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) ++ v1.AddArg2(x, y) ++ v0.AddArg2(a, v1) ++ b.resetWithControl(BlockARMGTnoov, v0) ++ return true ++ } + // match: (GT (CMPconst [0] l:(AND x y)) yes no) + // cond: l.Uses==1 +- // result: (GT (TST x y) yes no) ++ // result: (GTnoov (TST x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18154,39 +18179,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + break + } +- // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) +- // cond: l.Uses==1 +- // result: (GTnoov (CMN a (MUL x y)) yes no) +- for b.Controls[0].Op == OpARMCMPconst { +- v_0 := b.Controls[0] +- if v_0.AuxInt != 0 { +- break +- } +- l := v_0.Args[0] +- if l.Op != OpARMMULA { +- break +- } +- a := l.Args[2] +- x := l.Args[0] +- y := l.Args[1] +- if !(l.Uses == 1) { +- break +- } +- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) +- v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) +- v1.AddArg2(x, y) +- v0.AddArg2(a, v1) +- b.resetWithControl(BlockARMGTnoov, v0) +- return true +- } + // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTconst [c] x) yes no) ++ // result: (GTnoov (TSTconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18204,12 +18204,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftLL x y [c]) yes no) ++ // result: (GTnoov (TSTshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18228,12 +18228,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftRL x y [c]) yes no) ++ // result: (GTnoov (TSTshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18252,12 +18252,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftRA x y [c]) yes no) ++ // result: (GTnoov (TSTshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18276,12 +18276,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftLLreg x y z) yes no) ++ // result: (GTnoov (TSTshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18299,12 +18299,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftRLreg x y z) yes no) ++ // result: (GTnoov (TSTshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18322,12 +18322,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TSTshiftRAreg x y z) yes no) ++ // result: (GTnoov (TSTshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18345,12 +18345,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XOR x y)) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQ x y) yes no) ++ // result: (GTnoov (TEQ x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18371,14 +18371,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + break + } + // match: (GT (CMPconst [0] l:(XORconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQconst [c] x) yes no) ++ // result: (GTnoov (TEQconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18396,12 +18396,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftLL x y [c]) yes no) ++ // result: (GTnoov (TEQshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18420,12 +18420,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftRL x y [c]) yes no) ++ // result: (GTnoov (TEQshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18444,12 +18444,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftRA x y [c]) yes no) ++ // result: (GTnoov (TEQshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18468,12 +18468,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftLLreg x y z) yes no) ++ // result: (GTnoov (TEQshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18491,12 +18491,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftRLreg x y z) yes no) ++ // result: (GTnoov (TEQshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18514,12 +18514,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + // match: (GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (GT (TEQshiftRAreg x y z) yes no) ++ // result: (GTnoov (TEQshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -18537,7 +18537,7 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMGT, v0) ++ b.resetWithControl(BlockARMGTnoov, v0) + return true + } + case BlockARMGTnoov: +@@ -19129,7 +19129,7 @@ func rewriteBlockARM(b *Block) bool { + } + // match: (LE (CMPconst [0] l:(AND x y)) yes no) + // cond: l.Uses==1 +- // result: (LE (TST x y) yes no) ++ // result: (LEnoov (TST x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19150,14 +19150,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + break + } + // match: (LE (CMPconst [0] l:(ANDconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTconst [c] x) yes no) ++ // result: (LEnoov (TSTconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19175,12 +19175,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftLL x y [c]) yes no) ++ // result: (LEnoov (TSTshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19199,12 +19199,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftRL x y [c]) yes no) ++ // result: (LEnoov (TSTshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19223,12 +19223,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftRA x y [c]) yes no) ++ // result: (LEnoov (TSTshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19247,12 +19247,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftLLreg x y z) yes no) ++ // result: (LEnoov (TSTshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19270,12 +19270,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftRLreg x y z) yes no) ++ // result: (LEnoov (TSTshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19293,12 +19293,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TSTshiftRAreg x y z) yes no) ++ // result: (LEnoov (TSTshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19316,12 +19316,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XOR x y)) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQ x y) yes no) ++ // result: (LEnoov (TEQ x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19342,14 +19342,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + break + } + // match: (LE (CMPconst [0] l:(XORconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQconst [c] x) yes no) ++ // result: (LEnoov (TEQconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19367,12 +19367,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftLL x y [c]) yes no) ++ // result: (LEnoov (TEQshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19391,12 +19391,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftRL x y [c]) yes no) ++ // result: (LEnoov (TEQshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19415,12 +19415,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftRA x y [c]) yes no) ++ // result: (LEnoov (TEQshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19439,12 +19439,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftLLreg x y z) yes no) ++ // result: (LEnoov (TEQshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19462,12 +19462,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftRLreg x y z) yes no) ++ // result: (LEnoov (TEQshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19485,12 +19485,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + // match: (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LE (TEQshiftRAreg x y z) yes no) ++ // result: (LEnoov (TEQshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -19508,7 +19508,7 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLE, v0) ++ b.resetWithControl(BlockARMLEnoov, v0) + return true + } + case BlockARMLEnoov: +@@ -20009,7 +20009,7 @@ func rewriteBlockARM(b *Block) bool { + } + // match: (LT (CMPconst [0] l:(AND x y)) yes no) + // cond: l.Uses==1 +- // result: (LT (TST x y) yes no) ++ // result: (LTnoov (TST x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20030,14 +20030,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + break + } + // match: (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTconst [c] x) yes no) ++ // result: (LTnoov (TSTconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20055,12 +20055,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftLL x y [c]) yes no) ++ // result: (LTnoov (TSTshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20079,12 +20079,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftRL x y [c]) yes no) ++ // result: (LTnoov (TSTshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20103,12 +20103,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftRA x y [c]) yes no) ++ // result: (LTnoov (TSTshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20127,12 +20127,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftLLreg x y z) yes no) ++ // result: (LTnoov (TSTshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20150,12 +20150,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftRLreg x y z) yes no) ++ // result: (LTnoov (TSTshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20173,12 +20173,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TSTshiftRAreg x y z) yes no) ++ // result: (LTnoov (TSTshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20196,12 +20196,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XOR x y)) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQ x y) yes no) ++ // result: (LTnoov (TEQ x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20222,14 +20222,14 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + break + } + // match: (LT (CMPconst [0] l:(XORconst [c] x)) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQconst [c] x) yes no) ++ // result: (LTnoov (TEQconst [c] x) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20247,12 +20247,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) + v0.AuxInt = c + v0.AddArg(x) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftLL x y [c]) yes no) ++ // result: (LTnoov (TEQshiftLL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20271,12 +20271,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftRL x y [c]) yes no) ++ // result: (LTnoov (TEQshiftRL x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20295,12 +20295,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftRA x y [c]) yes no) ++ // result: (LTnoov (TEQshiftRA x y [c]) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20319,12 +20319,12 @@ func rewriteBlockARM(b *Block) bool { + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) + v0.AuxInt = c + v0.AddArg2(x, y) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftLLreg x y z) yes no) ++ // result: (LTnoov (TEQshiftLLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20342,12 +20342,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftRLreg x y z) yes no) ++ // result: (LTnoov (TEQshiftRLreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20365,12 +20365,12 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + // match: (LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) + // cond: l.Uses==1 +- // result: (LT (TEQshiftRAreg x y z) yes no) ++ // result: (LTnoov (TEQshiftRAreg x y z) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if v_0.AuxInt != 0 { +@@ -20388,7 +20388,7 @@ func rewriteBlockARM(b *Block) bool { + } + v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) + v0.AddArg3(x, y, z) +- b.resetWithControl(BlockARMLT, v0) ++ b.resetWithControl(BlockARMLTnoov, v0) + return true + } + case BlockARMLTnoov: +diff --git a/test/fixedbugs/issue42876.go b/test/fixedbugs/issue42876.go +new file mode 100644 +index 0000000000..67cf4919ac +--- /dev/null ++++ b/test/fixedbugs/issue42876.go +@@ -0,0 +1,18 @@ ++// run ++ ++// Copyright 2020 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 main ++ ++var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4} ++ ++func main() { ++ if x[0] > x[1] { ++ panic("fail 1") ++ } ++ if x[2]&x[3] < 0 { ++ panic("fail 2") // Fails here ++ } ++} +-- +2.27.0 + diff --git a/0016-release-branch.go1.15-syscall-do-not-overflow-key-me.patch b/0016-release-branch.go1.15-syscall-do-not-overflow-key-me.patch new file mode 100644 index 0000000000000000000000000000000000000000..08f29f32a988eea5b3a81fb28ab12b584fd86ff6 --- /dev/null +++ b/0016-release-branch.go1.15-syscall-do-not-overflow-key-me.patch @@ -0,0 +1,115 @@ +From 4fda89d4201fc9f0c1e192bbcc95dd8d660e9122 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Tue, 23 Feb 2021 13:29:40 +0100 +Subject: [PATCH 16/44] [release-branch.go1.15] syscall: do not overflow key + memory in GetQueuedCompletionStatus + +The third argument to GetQueuedCompletionStatus is a pointer to a +uintptr, not a uint32. Users of this functions have therefore been +corrupting their memory every time they used it. Either that memory +corruption was silent (dangerous), or their programs didn't work so they +chose a different API to use. + +This fixes the problem by passing through an intermediate buffer. + +Updates #44538. +Fixes #44592. + +Change-Id: Icacd71f705b36e41e52bd8c4d74898559a27522f +Reviewed-on: https://go-review.googlesource.com/c/go/+/296151 +Trust: Jason A. Donenfeld +Run-TryBot: Jason A. Donenfeld +TryBot-Result: Go Bot +Reviewed-by: Bryan C. Mills + +Conflict:NA +Reference:https://github.com/golang/go/commit/4fda89d4201fc9f0c1e192bbcc95dd8d660e9122 + +--- + src/syscall/syscall_windows.go | 34 ++++++++++++++++++++++++++++++--- + src/syscall/zsyscall_windows.go | 6 +++--- + 2 files changed, 34 insertions(+), 6 deletions(-) + +diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go +index f62c00d72f..fbb11a89ca 100644 +--- a/src/syscall/syscall_windows.go ++++ b/src/syscall/syscall_windows.go +@@ -213,9 +213,9 @@ func NewCallbackCDecl(fn interface{}) uintptr { + //sys SetEndOfFile(handle Handle) (err error) + //sys GetSystemTimeAsFileTime(time *Filetime) + //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] +-//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) +-//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) +-//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) ++//sys createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort ++//sys getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus ++//sys postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus + //sys CancelIo(s Handle) (err error) + //sys CancelIoEx(s Handle, o *Overlapped) (err error) + //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW +@@ -1209,3 +1209,31 @@ func Readlink(path string, buf []byte) (n int, err error) { + + return n, nil + } ++ ++// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort. ++func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) { ++ return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt) ++} ++ ++// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus. ++func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error { ++ var ukey uintptr ++ var pukey *uintptr ++ if key != nil { ++ ukey = uintptr(*key) ++ pukey = &ukey ++ } ++ err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout) ++ if key != nil { ++ *key = uint32(ukey) ++ if uintptr(*key) != ukey && err == nil { ++ err = errorspkg.New("GetQueuedCompletionStatus returned key overflow") ++ } ++ } ++ return err ++} ++ ++// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus. ++func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error { ++ return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped) ++} +diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go +index 2348f6534f..2762fb3b74 100644 +--- a/src/syscall/zsyscall_windows.go ++++ b/src/syscall/zsyscall_windows.go +@@ -539,7 +539,7 @@ func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { + return + } + +-func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { ++func createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) { + r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) + handle = Handle(r0) + if handle == 0 { +@@ -552,7 +552,7 @@ func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, thre + return + } + +-func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { ++func getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) { + r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { +@@ -564,7 +564,7 @@ func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overla + return + } + +-func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { ++func postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) { + r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) + if r1 == 0 { + if e1 != 0 { +-- +2.27.0 + diff --git a/0017-release-branch.go1.15-time-correct-unusual-extension.patch b/0017-release-branch.go1.15-time-correct-unusual-extension.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c58dc79a18b3edb587511e2e49335aa607f4c8e --- /dev/null +++ b/0017-release-branch.go1.15-time-correct-unusual-extension.patch @@ -0,0 +1,150 @@ +From 6bb96000b3215a84d0a5193e387cf809d2fa2800 Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor +Date: Thu, 25 Feb 2021 10:01:56 -0800 +Subject: [PATCH 17/44] [release-branch.go1.15] time: correct unusual extension + string cases + +This fixes two uncommon cases. + +First, the tzdata code permits timezone offsets up to 24 * 7, although +the POSIX TZ parsing does not. The tzdata code uses this to specify a +day of week in some cases. + +Second, we incorrectly rejected a negative time offset for when a time +zone change comes into effect. + +For #44385 +Fixes #44617 + +Change-Id: I5f2efc1d385e9bfa974a0de3fa81e7a94b827602 +Reviewed-on: https://go-review.googlesource.com/c/go/+/296392 +Trust: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-by: Tobias Klauser +(cherry picked from commit d9fd38e68ba00a51c2c7363150688d0e7687ef84) +Reviewed-on: https://go-review.googlesource.com/c/go/+/297229 + +Conflict:NA +Reference:https://github.com/golang/go/commit/6bb96000b3215a84d0a5193e387cf809d2fa2800 + +--- + src/time/zoneinfo.go | 6 ++-- + src/time/zoneinfo_test.go | 60 +++++++++++++++++++++++++++++---------- + 2 files changed, 49 insertions(+), 17 deletions(-) + +diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go +index c3662297c7..6db9443474 100644 +--- a/src/time/zoneinfo.go ++++ b/src/time/zoneinfo.go +@@ -377,8 +377,10 @@ func tzsetOffset(s string) (offset int, rest string, ok bool) { + neg = true + } + ++ // The tzdata code permits values up to 24 * 7 here, ++ // although POSIX does not. + var hours int +- hours, s, ok = tzsetNum(s, 0, 24) ++ hours, s, ok = tzsetNum(s, 0, 24*7) + if !ok { + return 0, "", false + } +@@ -487,7 +489,7 @@ func tzsetRule(s string) (rule, string, bool) { + } + + offset, s, ok := tzsetOffset(s[1:]) +- if !ok || offset < 0 { ++ if !ok { + return rule{}, "", false + } + r.time = offset +diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go +index 277b68f798..d043e1e9f1 100644 +--- a/src/time/zoneinfo_test.go ++++ b/src/time/zoneinfo_test.go +@@ -183,22 +183,50 @@ func TestMalformedTZData(t *testing.T) { + } + } + +-func TestLoadLocationFromTZDataSlim(t *testing.T) { +- // A 2020b slim tzdata for Europe/Berlin +- tzData := "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3<-02>,M3.5.0/-2,M10.5.0/-1\n", ++ wantName: "-03", ++ wantOffset: -10800, ++ }, ++ { ++ // 2021a slim tzdata for Asia/Gaza. ++ zoneName: "Asia/Gaza", ++ tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\n", ++ wantName: "EET", ++ wantOffset: 7200, ++ }, ++} + +- reference, err := time.LoadLocationFromTZData("Europe/Berlin", []byte(tzData)) +- if err != nil { +- t.Fatal(err) +- } ++func TestLoadLocationFromTZDataSlim(t *testing.T) { ++ for _, test := range slimTests { ++ reference, err := time.LoadLocationFromTZData(test.zoneName, []byte(test.tzData)) ++ if err != nil { ++ t.Fatal(err) ++ } + +- d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference) +- tzName, tzOffset := d.Zone() +- if want := "CET"; tzName != want { +- t.Errorf("Zone name == %s, want %s", tzName, want) +- } +- if want := 3600; tzOffset != want { +- t.Errorf("Zone offset == %d, want %d", tzOffset, want) ++ d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference) ++ tzName, tzOffset := d.Zone() ++ if tzName != test.wantName { ++ t.Errorf("Zone name == %s, want %s", tzName, test.wantName) ++ } ++ if tzOffset != test.wantOffset { ++ t.Errorf("Zone offset == %d, want %d", tzOffset, test.wantOffset) ++ } + } + } + +@@ -263,7 +291,8 @@ func TestTzsetOffset(t *testing.T) { + {"+08", 8 * 60 * 60, "", true}, + {"-01:02:03", -1*60*60 - 2*60 - 3, "", true}, + {"01", 1 * 60 * 60, "", true}, +- {"100", 0, "", false}, ++ {"100", 100 * 60 * 60, "", true}, ++ {"1000", 0, "", false}, + {"8PDT", 8 * 60 * 60, "PDT", true}, + } { + off, out, ok := time.TzsetOffset(test.in) +@@ -288,6 +317,7 @@ func TestTzsetRule(t *testing.T) { + {"30/03:00:00", time.Rule{Kind: time.RuleDOY, Day: 30, Time: 3 * 60 * 60}, "", true}, + {"M4.5.6/03:00:00", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: 3 * 60 * 60}, "", true}, + {"M4.5.7/03:00:00", time.Rule{}, "", false}, ++ {"M4.5.6/-04", time.Rule{Kind: time.RuleMonthWeekDay, Mon: 4, Week: 5, Day: 6, Time: -4 * 60 * 60}, "", true}, + } { + r, out, ok := time.TzsetRule(test.in) + if r != test.r || out != test.out || ok != test.ok { +-- +2.27.0 + diff --git a/0018-release-branch.go1.15-cmd-compile-fix-escape-analysi.patch b/0018-release-branch.go1.15-cmd-compile-fix-escape-analysi.patch new file mode 100644 index 0000000000000000000000000000000000000000..e13076f4d3921c04fb65f93955890b66b4eb2455 --- /dev/null +++ b/0018-release-branch.go1.15-cmd-compile-fix-escape-analysi.patch @@ -0,0 +1,87 @@ +From f75ab2d5a61f1a5aabaffe7752110e2dcd581236 Mon Sep 17 00:00:00 2001 +From: Matthew Dempsky +Date: Sat, 27 Feb 2021 09:41:19 -0800 +Subject: [PATCH 18/44] [release-branch.go1.15] cmd/compile: fix escape + analysis of heap-allocated results + +One of escape analysis's responsibilities is to summarize whether/how +each function parameter flows to the heap so we can correctly +incorporate those flows into callers' escape analysis data flow +graphs. + +As an optimization, we separately record when parameters flow to +result parameters, so that we can more precisely analyze parameter +flows based on how the results are used at the call site. However, if +a named result parameter itself needs to be heap allocated, this +optimization isn't safe and the parameter needs to be recorded as +flowing to heap rather than flowing to result. + +Escape analysis used to get this correct because it conservatively +rewalked the data-flow graph multiple times. So even though it would +incorrectly record the result parameter flow, it would separately find +a flow to the heap. However, CL 196811 (specifically, case 3) +optimized the walking logic to reduce unnecessary rewalks causing us +to stop finding the extra heap flow. + +This CL fixes the issue by correcting location.leakTo to be sensitive +to sink.escapes and not record result-flows when the result parameter +escapes to the heap. + +Fixes #44658. + +Change-Id: I48742ed35a6cab591094e2d23a439e205bd65c50 +Reviewed-on: https://go-review.googlesource.com/c/go/+/297289 +Trust: Matthew Dempsky +Run-TryBot: Matthew Dempsky +TryBot-Result: Go Bot +Reviewed-by: Keith Randall +Reviewed-on: https://go-review.googlesource.com/c/go/+/297291 + +Conflict:NA +Reference:https://github.com/golang/go/commit/f75ab2d5a61f1a5aabaffe7752110e2dcd581236 + +--- + src/cmd/compile/internal/gc/escape.go | 7 ++++--- + test/escape5.go | 11 +++++++++++ + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go +index 08000dd374..2c55163100 100644 +--- a/src/cmd/compile/internal/gc/escape.go ++++ b/src/cmd/compile/internal/gc/escape.go +@@ -1379,9 +1379,10 @@ func containsClosure(f, c *Node) bool { + + // leak records that parameter l leaks to sink. + func (l *EscLocation) leakTo(sink *EscLocation, derefs int) { +- // If sink is a result parameter and we can fit return bits +- // into the escape analysis tag, then record a return leak. +- if sink.isName(PPARAMOUT) && sink.curfn == l.curfn { ++ // If sink is a result parameter that doesn't escape (#44614) ++ // and we can fit return bits into the escape analysis tag, ++ // then record as a result leak. ++ if !sink.escapes && sink.isName(PPARAMOUT) && sink.curfn == l.curfn { + // TODO(mdempsky): Eliminate dependency on Vargen here. + ri := int(sink.n.Name.Vargen) - 1 + if ri < numEscResults { +diff --git a/test/escape5.go b/test/escape5.go +index 061e57a069..145c5dd900 100644 +--- a/test/escape5.go ++++ b/test/escape5.go +@@ -262,3 +262,14 @@ func f28369(n int) int { + + return 1 + f28369(n-1) + } ++ ++// Issue 44614: parameters that flow to a heap-allocated result ++// parameter must be recorded as a heap-flow rather than a ++// result-flow. ++ ++// N.B., must match "leaking param: p", ++// but *not* "leaking param: p to result r level=0". ++func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r" ++ sink4 = &r ++ return p ++} +-- +2.27.0 + diff --git a/0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch b/0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch deleted file mode 100644 index b265af09603fdd8591b98ff6839502171d0551bf..0000000000000000000000000000000000000000 --- a/0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch +++ /dev/null @@ -1,363 +0,0 @@ -From 2ad2c042555908cfd791b7e6a3318c1d3df10aeb Mon Sep 17 00:00:00 2001 -From: Roberto Clapis -Date: Wed, 26 Aug 2020 08:53:03 +0200 -Subject: [PATCH] net/http/cgi,net/http/fcgi: add Content-Type detection - -This CL ensures that responses served via CGI and FastCGI -have a Content-Type header based on the content of the -response if not explicitly set by handlers. - -If the implementers of the handler did not explicitly -specify a Content-Type both CGI implementations would default -to "text/html", potentially causing cross-site scripting. - -Thanks to RedTeam Pentesting GmbH for reporting this. - -Fixes #40928 -Fixes CVE-2020-24553 - -Change-Id: I82cfc396309b5ab2e8d6e9a87eda8ea7e3799473 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/823217 -Reviewed-by: Russ Cox -Reviewed-on: https://go-review.googlesource.com/c/go/+/252179 -Run-TryBot: Filippo Valsorda -TryBot-Result: Go Bot -Reviewed-by: Katie Hockman ---- - src/net/http/cgi/child.go | 36 ++++++++++++------ - src/net/http/cgi/child_test.go | 58 +++++++++++++++++++++++++++++ - src/net/http/cgi/matryoshka_test.go | 8 +++- - src/net/http/fcgi/child.go | 39 ++++++++++++++----- - src/net/http/fcgi/fcgi_test.go | 52 ++++++++++++++++++++++++++ - 5 files changed, 171 insertions(+), 22 deletions(-) - -diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go -index cb140f8f2f..2b210ea4a1 100644 ---- a/src/net/http/cgi/child.go -+++ b/src/net/http/cgi/child.go -@@ -165,10 +165,12 @@ func Serve(handler http.Handler) error { - } - - type response struct { -- req *http.Request -- header http.Header -- bufw *bufio.Writer -- headerSent bool -+ req *http.Request -+ header http.Header -+ code int -+ wroteHeader bool -+ wroteCGIHeader bool -+ bufw *bufio.Writer - } - - func (r *response) Flush() { -@@ -180,26 +182,38 @@ func (r *response) Header() http.Header { - } - - func (r *response) Write(p []byte) (n int, err error) { -- if !r.headerSent { -+ if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } -+ if !r.wroteCGIHeader { -+ r.writeCGIHeader(p) -+ } - return r.bufw.Write(p) - } - - func (r *response) WriteHeader(code int) { -- if r.headerSent { -+ if r.wroteHeader { - // Note: explicitly using Stderr, as Stdout is our HTTP output. - fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL) - return - } -- r.headerSent = true -- fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code)) -+ r.wroteHeader = true -+ r.code = code -+} - -- // Set a default Content-Type -+// writeCGIHeader finalizes the header sent to the client and writes it to the output. -+// p is not written by writeHeader, but is the first chunk of the body -+// that will be written. It is sniffed for a Content-Type if none is -+// set explicitly. -+func (r *response) writeCGIHeader(p []byte) { -+ if r.wroteCGIHeader { -+ return -+ } -+ r.wroteCGIHeader = true -+ fmt.Fprintf(r.bufw, "Status: %d %s\r\n", r.code, http.StatusText(r.code)) - if _, hasType := r.header["Content-Type"]; !hasType { -- r.header.Add("Content-Type", "text/html; charset=utf-8") -+ r.header.Set("Content-Type", http.DetectContentType(p)) - } -- - r.header.Write(r.bufw) - r.bufw.WriteString("\r\n") - r.bufw.Flush() -diff --git a/src/net/http/cgi/child_test.go b/src/net/http/cgi/child_test.go -index 14e0af475f..18cf789bd5 100644 ---- a/src/net/http/cgi/child_test.go -+++ b/src/net/http/cgi/child_test.go -@@ -7,6 +7,11 @@ - package cgi - - import ( -+ "bufio" -+ "bytes" -+ "net/http" -+ "net/http/httptest" -+ "strings" - "testing" - ) - -@@ -148,3 +153,56 @@ func TestRequestWithoutRemotePort(t *testing.T) { - t.Errorf("RemoteAddr: got %q; want %q", g, e) - } - } -+ -+func TestResponse(t *testing.T) { -+ var tests = []struct { -+ name string -+ body string -+ wantCT string -+ }{ -+ { -+ name: "no body", -+ wantCT: "text/plain; charset=utf-8", -+ }, -+ { -+ name: "html", -+ body: "test pageThis is a body", -+ wantCT: "text/html; charset=utf-8", -+ }, -+ { -+ name: "text", -+ body: strings.Repeat("gopher", 86), -+ wantCT: "text/plain; charset=utf-8", -+ }, -+ { -+ name: "jpg", -+ body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024), -+ wantCT: "image/jpeg", -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ var buf bytes.Buffer -+ resp := response{ -+ req: httptest.NewRequest("GET", "/", nil), -+ header: http.Header{}, -+ bufw: bufio.NewWriter(&buf), -+ } -+ n, err := resp.Write([]byte(tt.body)) -+ if err != nil { -+ t.Errorf("Write: unexpected %v", err) -+ } -+ if want := len(tt.body); n != want { -+ t.Errorf("reported short Write: got %v want %v", n, want) -+ } -+ resp.writeCGIHeader(nil) -+ resp.Flush() -+ if got := resp.Header().Get("Content-Type"); got != tt.wantCT { -+ t.Errorf("wrong content-type: got %q, want %q", got, tt.wantCT) -+ } -+ if !bytes.HasSuffix(buf.Bytes(), []byte(tt.body)) { -+ t.Errorf("body was not correctly written") -+ } -+ }) -+ } -+} -diff --git a/src/net/http/cgi/matryoshka_test.go b/src/net/http/cgi/matryoshka_test.go -index 32d59c09a3..41a27889f2 100644 ---- a/src/net/http/cgi/matryoshka_test.go -+++ b/src/net/http/cgi/matryoshka_test.go -@@ -16,7 +16,9 @@ import ( - "io" - "net/http" - "net/http/httptest" -+ "net/url" - "os" -+ "strings" - "testing" - "time" - ) -@@ -52,7 +54,7 @@ func TestHostingOurselves(t *testing.T) { - } - replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap) - -- if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected { -+ if expected, got := "text/plain; charset=utf-8", replay.Header().Get("Content-Type"); got != expected { - t.Errorf("got a Content-Type of %q; expected %q", got, expected) - } - if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected { -@@ -203,6 +205,10 @@ func TestBeChildCGIProcess(t *testing.T) { - if req.FormValue("no-body") == "1" { - return - } -+ if eb, ok := req.Form["exact-body"]; ok { -+ io.WriteString(rw, eb[0]) -+ return -+ } - if req.FormValue("write-forever") == "1" { - io.Copy(rw, neverEnding('a')) - for { -diff --git a/src/net/http/fcgi/child.go b/src/net/http/fcgi/child.go -index 30a6b2ce2d..a31273b3ec 100644 ---- a/src/net/http/fcgi/child.go -+++ b/src/net/http/fcgi/child.go -@@ -74,10 +74,12 @@ func (r *request) parseParams() { - - // response implements http.ResponseWriter. - type response struct { -- req *request -- header http.Header -- w *bufWriter -- wroteHeader bool -+ req *request -+ header http.Header -+ code int -+ wroteHeader bool -+ wroteCGIHeader bool -+ w *bufWriter - } - - func newResponse(c *child, req *request) *response { -@@ -92,11 +94,14 @@ func (r *response) Header() http.Header { - return r.header - } - --func (r *response) Write(data []byte) (int, error) { -+func (r *response) Write(p []byte) (n int, err error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } -- return r.w.Write(data) -+ if !r.wroteCGIHeader { -+ r.writeCGIHeader(p) -+ } -+ return r.w.Write(p) - } - - func (r *response) WriteHeader(code int) { -@@ -104,22 +109,34 @@ func (r *response) WriteHeader(code int) { - return - } - r.wroteHeader = true -+ r.code = code - if code == http.StatusNotModified { - // Must not have body. - r.header.Del("Content-Type") - r.header.Del("Content-Length") - r.header.Del("Transfer-Encoding") -- } else if r.header.Get("Content-Type") == "" { -- r.header.Set("Content-Type", "text/html; charset=utf-8") - } -- - if r.header.Get("Date") == "" { - r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat)) - } -+} - -- fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code)) -+// writeCGIHeader finalizes the header sent to the client and writes it to the output. -+// p is not written by writeHeader, but is the first chunk of the body -+// that will be written. It is sniffed for a Content-Type if none is -+// set explicitly. -+func (r *response) writeCGIHeader(p []byte) { -+ if r.wroteCGIHeader { -+ return -+ } -+ r.wroteCGIHeader = true -+ fmt.Fprintf(r.w, "Status: %d %s\r\n", r.code, http.StatusText(r.code)) -+ if _, hasType := r.header["Content-Type"]; r.code != http.StatusNotModified && !hasType { -+ r.header.Set("Content-Type", http.DetectContentType(p)) -+ } - r.header.Write(r.w) - r.w.WriteString("\r\n") -+ r.w.Flush() - } - - func (r *response) Flush() { -@@ -290,6 +307,8 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) { - httpReq = httpReq.WithContext(envVarCtx) - c.handler.ServeHTTP(r, httpReq) - } -+ // Make sure we serve something even if nothing was written to r -+ r.Write(nil) - r.Close() - c.mu.Lock() - delete(c.requests, req.reqId) -diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go -index e9d2b34023..4a27a12c35 100644 ---- a/src/net/http/fcgi/fcgi_test.go -+++ b/src/net/http/fcgi/fcgi_test.go -@@ -10,6 +10,7 @@ import ( - "io" - "io/ioutil" - "net/http" -+ "strings" - "testing" - ) - -@@ -344,3 +345,54 @@ func TestChildServeReadsEnvVars(t *testing.T) { - <-done - } - } -+ -+func TestResponseWriterSniffsContentType(t *testing.T) { -+ var tests = []struct { -+ name string -+ body string -+ wantCT string -+ }{ -+ { -+ name: "no body", -+ wantCT: "text/plain; charset=utf-8", -+ }, -+ { -+ name: "html", -+ body: "test pageThis is a body", -+ wantCT: "text/html; charset=utf-8", -+ }, -+ { -+ name: "text", -+ body: strings.Repeat("gopher", 86), -+ wantCT: "text/plain; charset=utf-8", -+ }, -+ { -+ name: "jpg", -+ body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024), -+ wantCT: "image/jpeg", -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ input := make([]byte, len(streamFullRequestStdin)) -+ copy(input, streamFullRequestStdin) -+ rc := nopWriteCloser{bytes.NewBuffer(input)} -+ done := make(chan bool) -+ var resp *response -+ c := newChild(rc, http.HandlerFunc(func( -+ w http.ResponseWriter, -+ r *http.Request, -+ ) { -+ io.WriteString(w, tt.body) -+ resp = w.(*response) -+ done <- true -+ })) -+ defer c.cleanUp() -+ go c.serve() -+ <-done -+ if got := resp.Header().Get("Content-Type"); got != tt.wantCT { -+ t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT) -+ } -+ }) -+ } -+} --- -2.17.1 - diff --git a/0019-release-branch.go1.15-net-http-ignore-connection-clo.patch b/0019-release-branch.go1.15-net-http-ignore-connection-clo.patch new file mode 100644 index 0000000000000000000000000000000000000000..38b1bc7c774101e7df5a165f2fed7e01a7689985 --- /dev/null +++ b/0019-release-branch.go1.15-net-http-ignore-connection-clo.patch @@ -0,0 +1,124 @@ +From 5de8d3bfcb060bbc61b9b9c945055fd3fb5b9607 Mon Sep 17 00:00:00 2001 +From: Michael Fraenkel +Date: Sat, 26 Sep 2020 09:20:16 -0600 +Subject: [PATCH 19/44] [release-branch.go1.15] net/http: ignore connection + closes once done with the connection + +Once the connection is put back into the idle pool, the request should +not take any action if the connection is closed. + +For #42935. +Updates #41600. + +Change-Id: I5e4ddcdc03cd44f5197ecfbe324638604961de84 +Reviewed-on: https://go-review.googlesource.com/c/go/+/257818 +Reviewed-by: Brad Fitzpatrick +Trust: Damien Neil +(cherry picked from commit 212d385a2f723a8dd5e7d2e83efb478ddd139349) +Reviewed-on: https://go-review.googlesource.com/c/go/+/297909 +Trust: Dmitri Shuralyov +Run-TryBot: Dmitri Shuralyov +Reviewed-by: Damien Neil + +Conflict:NA +Reference:https://github.com/golang/go/commit/5de8d3bfcb060bbc61b9b9c945055fd3fb5b9607 + +--- + src/net/http/transport.go | 13 ++++++--- + src/net/http/transport_test.go | 51 ++++++++++++++++++++++++++++++++++ + 2 files changed, 60 insertions(+), 4 deletions(-) + +diff --git a/src/net/http/transport.go b/src/net/http/transport.go +index d37b52b13d..6fb2ea5663 100644 +--- a/src/net/http/transport.go ++++ b/src/net/http/transport.go +@@ -2560,6 +2560,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err + var respHeaderTimer <-chan time.Time + cancelChan := req.Request.Cancel + ctxDoneChan := req.Context().Done() ++ pcClosed := pc.closech + for { + testHookWaitResLoop() + select { +@@ -2579,11 +2580,15 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err + defer timer.Stop() // prevent leaks + respHeaderTimer = timer.C + } +- case <-pc.closech: +- if debugRoundTrip { +- req.logf("closech recv: %T %#v", pc.closed, pc.closed) ++ case <-pcClosed: ++ pcClosed = nil ++ // check if we are still using the connection ++ if pc.t.replaceReqCanceler(req.cancelKey, nil) { ++ if debugRoundTrip { ++ req.logf("closech recv: %T %#v", pc.closed, pc.closed) ++ } ++ return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed) + } +- return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed) + case <-respHeaderTimer: + if debugRoundTrip { + req.logf("timeout waiting for response headers.") +diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go +index 0a47687d9a..3c7b9eb4de 100644 +--- a/src/net/http/transport_test.go ++++ b/src/net/http/transport_test.go +@@ -6289,3 +6289,54 @@ func TestTransportRejectsSignInContentLength(t *testing.T) { + t.Fatalf("Error mismatch\nGot: %q\nWanted substring: %q", got, want) + } + } ++ ++// Issue 41600 ++// Test that a new request which uses the connection of an active request ++// cannot cause it to be canceled as well. ++func TestCancelRequestWhenSharingConnection(t *testing.T) { ++ if testing.Short() { ++ t.Skip("skipping in short mode") ++ } ++ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) { ++ w.Header().Add("Content-Length", "0") ++ })) ++ defer ts.Close() ++ ++ client := ts.Client() ++ transport := client.Transport.(*Transport) ++ transport.MaxIdleConns = 1 ++ transport.MaxConnsPerHost = 1 ++ ++ var wg sync.WaitGroup ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ++ ++ for i := 0; i < 10; i++ { ++ wg.Add(1) ++ go func() { ++ defer wg.Done() ++ for ctx.Err() == nil { ++ reqctx, reqcancel := context.WithCancel(ctx) ++ go reqcancel() ++ req, _ := NewRequestWithContext(reqctx, "GET", ts.URL, nil) ++ res, err := client.Do(req) ++ if err == nil { ++ res.Body.Close() ++ } ++ } ++ }() ++ } ++ ++ for ctx.Err() == nil { ++ req, _ := NewRequest("GET", ts.URL, nil) ++ if res, err := client.Do(req); err != nil { ++ t.Errorf("unexpected: %p %v", req, err) ++ break ++ } else { ++ res.Body.Close() ++ } ++ } ++ ++ cancel() ++ wg.Wait() ++} +-- +2.27.0 + diff --git a/0020-golang-fix-CVE-2020-28366.patch b/0020-golang-fix-CVE-2020-28366.patch deleted file mode 100644 index dfc8941d19641fbb69751f73fb13ad445dac7f08..0000000000000000000000000000000000000000 --- a/0020-golang-fix-CVE-2020-28366.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 24fb490f5c5ba855ad9feba179f820a835f68d66 Mon Sep 17 00:00:00 2001 -From: liuzekun -Date: Tue, 1 Dec 2020 22:50:08 -0500 -Subject: [PATCH] golang: fix CVE-2020-28366 - -Upstream: https://github.com/golang/go/commit/062e0e5ce6df339dc26732438ad771f73dbf2292 -cmd/go, cmd/cgo: don't let bogus symbol set cgo_ldflag - -A hand-edited object file can have a symbol name that uses newline and -other normally invalid characters. The cgo tool will generate Go files -containing symbol names, unquoted. That can permit those symbol names -to inject Go code into a cgo-generated file. If that Go code uses the -//go:cgo_ldflag pragma, it can cause the C linker to run arbitrary -code when building a package. If you build an imported package we -permit arbitrary code at run time, but we don't want to permit it at -package build time. This CL prevents this in two ways. - -In cgo, reject invalid symbols that contain non-printable or space -characters, or that contain anything that looks like a Go comment. - -In the go tool, double check all //go:cgo_ldflag directives in -generated code, to make sure they follow the existing LDFLAG restrictions. - -Thanks to Imre Rad / https://www.linkedin.com/in/imre-rad-2358749b for -reporting this. - -Fixes CVE-2020-28367 - -Change-Id: Ia1ad8f3791ea79612690fa7d26ac451d0f6df7c1 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/895832 -Reviewed-by: Than McIntosh -Reviewed-by: Cherry Zhang -Reviewed-on: https://go-review.googlesource.com/c/go/+/269658 -Trust: Katie Hockman -Trust: Roland Shoemaker -Run-TryBot: Katie Hockman -TryBot-Result: Go Bot -Reviewed-by: Roland Shoemaker - -Signed-off-by: liuzekun ---- - misc/cgo/errors/badsym_test.go | 216 +++++++++++++++++++++++++++++++ - src/cmd/cgo/out.go | 24 ++++ - src/cmd/go/internal/work/exec.go | 60 +++++++++ - 3 files changed, 300 insertions(+) - create mode 100644 misc/cgo/errors/badsym_test.go - -diff --git a/misc/cgo/errors/badsym_test.go b/misc/cgo/errors/badsym_test.go -new file mode 100644 -index 0000000..b2701bf ---- /dev/null -+++ b/misc/cgo/errors/badsym_test.go -@@ -0,0 +1,216 @@ -+// Copyright 2020 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 errorstest -+ -+import ( -+ "bytes" -+ "io/ioutil" -+ "os" -+ "os/exec" -+ "path/filepath" -+ "strings" -+ "testing" -+ "unicode" -+) -+ -+// A manually modified object file could pass unexpected characters -+// into the files generated by cgo. -+ -+const magicInput = "abcdefghijklmnopqrstuvwxyz0123" -+const magicReplace = "\n//go:cgo_ldflag \"-badflag\"\n//" -+ -+const cSymbol = "BadSymbol" + magicInput + "Name" -+const cDefSource = "int " + cSymbol + " = 1;" -+const cRefSource = "extern int " + cSymbol + "; int F() { return " + cSymbol + "; }" -+ -+// goSource is the source code for the trivial Go file we use. -+// We will replace TMPDIR with the temporary directory name. -+const goSource = ` -+package main -+ -+// #cgo LDFLAGS: TMPDIR/cbad.o TMPDIR/cbad.so -+// extern int F(); -+import "C" -+ -+func main() { -+ println(C.F()) -+} -+` -+ -+func TestBadSymbol(t *testing.T) { -+ dir := t.TempDir() -+ -+ mkdir := func(base string) string { -+ ret := filepath.Join(dir, base) -+ if err := os.Mkdir(ret, 0755); err != nil { -+ t.Fatal(err) -+ } -+ return ret -+ } -+ -+ cdir := mkdir("c") -+ godir := mkdir("go") -+ -+ makeFile := func(mdir, base, source string) string { -+ ret := filepath.Join(mdir, base) -+ if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil { -+ t.Fatal(err) -+ } -+ return ret -+ } -+ -+ cDefFile := makeFile(cdir, "cdef.c", cDefSource) -+ cRefFile := makeFile(cdir, "cref.c", cRefSource) -+ -+ ccCmd := cCompilerCmd(t) -+ -+ cCompile := func(arg, base, src string) string { -+ out := filepath.Join(cdir, base) -+ run := append(ccCmd, arg, "-o", out, src) -+ output, err := exec.Command(run[0], run[1:]...).CombinedOutput() -+ if err != nil { -+ t.Log(run) -+ t.Logf("%s", output) -+ t.Fatal(err) -+ } -+ if err := os.Remove(src); err != nil { -+ t.Fatal(err) -+ } -+ return out -+ } -+ -+ // Build a shared library that defines a symbol whose name -+ // contains magicInput. -+ -+ cShared := cCompile("-shared", "c.so", cDefFile) -+ -+ // Build an object file that refers to the symbol whose name -+ // contains magicInput. -+ -+ cObj := cCompile("-c", "c.o", cRefFile) -+ -+ // Rewrite the shared library and the object file, replacing -+ // magicInput with magicReplace. This will have the effect of -+ // introducing a symbol whose name looks like a cgo command. -+ // The cgo tool will use that name when it generates the -+ // _cgo_import.go file, thus smuggling a magic //go:cgo_ldflag -+ // pragma into a Go file. We used to not check the pragmas in -+ // _cgo_import.go. -+ -+ rewrite := func(from, to string) { -+ obj, err := ioutil.ReadFile(from) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if bytes.Count(obj, []byte(magicInput)) == 0 { -+ t.Fatalf("%s: did not find magic string", from) -+ } -+ -+ if len(magicInput) != len(magicReplace) { -+ t.Fatalf("internal test error: different magic lengths: %d != %d", len(magicInput), len(magicReplace)) -+ } -+ -+ obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace)) -+ -+ if err := ioutil.WriteFile(to, obj, 0644); err != nil { -+ t.Fatal(err) -+ } -+ } -+ -+ cBadShared := filepath.Join(godir, "cbad.so") -+ rewrite(cShared, cBadShared) -+ -+ cBadObj := filepath.Join(godir, "cbad.o") -+ rewrite(cObj, cBadObj) -+ -+ goSourceBadObject := strings.ReplaceAll(goSource, "TMPDIR", godir) -+ makeFile(godir, "go.go", goSourceBadObject) -+ -+ makeFile(godir, "go.mod", "module badsym") -+ -+ // Try to build our little package. -+ cmd := exec.Command("go", "build", "-ldflags=-v") -+ cmd.Dir = godir -+ output, err := cmd.CombinedOutput() -+ -+ // The build should fail, but we want it to fail because we -+ // detected the error, not because we passed a bad flag to the -+ // C linker. -+ -+ if err == nil { -+ t.Errorf("go build succeeded unexpectedly") -+ } -+ -+ t.Logf("%s", output) -+ -+ for _, line := range bytes.Split(output, []byte("\n")) { -+ if bytes.Contains(line, []byte("dynamic symbol")) && bytes.Contains(line, []byte("contains unsupported character")) { -+ // This is the error from cgo. -+ continue -+ } -+ -+ // We passed -ldflags=-v to see the external linker invocation, -+ // which should not include -badflag. -+ if bytes.Contains(line, []byte("-badflag")) { -+ t.Error("output should not mention -badflag") -+ } -+ -+ // Also check for compiler errors, just in case. -+ // GCC says "unrecognized command line option". -+ // clang says "unknown argument". -+ if bytes.Contains(line, []byte("unrecognized")) || bytes.Contains(output, []byte("unknown")) { -+ t.Error("problem should have been caught before invoking C linker") -+ } -+ } -+} -+ -+func cCompilerCmd(t *testing.T) []string { -+ cc := []string{goEnv(t, "CC")} -+ -+ out := goEnv(t, "GOGCCFLAGS") -+ quote := '\000' -+ start := 0 -+ lastSpace := true -+ backslash := false -+ s := string(out) -+ for i, c := range s { -+ if quote == '\000' && unicode.IsSpace(c) { -+ if !lastSpace { -+ cc = append(cc, s[start:i]) -+ lastSpace = true -+ } -+ } else { -+ if lastSpace { -+ start = i -+ lastSpace = false -+ } -+ if quote == '\000' && !backslash && (c == '"' || c == '\'') { -+ quote = c -+ backslash = false -+ } else if !backslash && quote == c { -+ quote = '\000' -+ } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { -+ backslash = true -+ } else { -+ backslash = false -+ } -+ } -+ } -+ if !lastSpace { -+ cc = append(cc, s[start:]) -+ } -+ return cc -+} -+ -+func goEnv(t *testing.T, key string) string { -+ out, err := exec.Command("go", "env", key).CombinedOutput() -+ if err != nil { -+ t.Logf("go env %s\n", key) -+ t.Logf("%s", out) -+ t.Fatal(err) -+ } -+ return strings.TrimSpace(string(out)) -+} -diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go -index 1fddbb6..65a8d66 100644 ---- a/src/cmd/cgo/out.go -+++ b/src/cmd/cgo/out.go -@@ -22,6 +22,7 @@ import ( - "regexp" - "sort" - "strings" -+ "unicode" - ) - - var ( -@@ -325,6 +326,8 @@ func dynimport(obj string) { - if s.Version != "" { - targ += "#" + s.Version - } -+ checkImportSymName(s.Name) -+ checkImportSymName(targ) - fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) - } - lib, _ := f.ImportedLibraries() -@@ -340,6 +343,7 @@ func dynimport(obj string) { - if len(s) > 0 && s[0] == '_' { - s = s[1:] - } -+ checkImportSymName(s) - fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "") - } - lib, _ := f.ImportedLibraries() -@@ -354,6 +358,8 @@ func dynimport(obj string) { - for _, s := range sym { - ss := strings.Split(s, ":") - name := strings.Split(ss[0], "@")[0] -+ checkImportSymName(name) -+ checkImportSymName(ss[0]) - fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) - } - return -@@ -371,6 +377,7 @@ func dynimport(obj string) { - // Go symbols. - continue - } -+ checkImportSymName(s.Name) - fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library) - } - lib, err := f.ImportedLibraries() -@@ -386,6 +393,23 @@ func dynimport(obj string) { - fatalf("cannot parse %s as ELF, Mach-O, PE or XCOFF", obj) - } - -+// checkImportSymName checks a symbol name we are going to emit as part -+// of a //go:cgo_import_dynamic pragma. These names come from object -+// files, so they may be corrupt. We are going to emit them unquoted, -+// so while they don't need to be valid symbol names (and in some cases, -+// involving symbol versions, they won't be) they must contain only -+// graphic characters and must not contain Go comments. -+func checkImportSymName(s string) { -+ for _, c := range s { -+ if !unicode.IsGraphic(c) || unicode.IsSpace(c) { -+ fatalf("dynamic symbol %q contains unsupported character", s) -+ } -+ } -+ if strings.Index(s, "//") >= 0 || strings.Index(s, "/*") >= 0 { -+ fatalf("dynamic symbol %q contains Go comment") -+ } -+} -+ - // Construct a gcc struct matching the gc argument frame. - // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. - // These assumptions are checked by the gccProlog. -diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go -index 7dd9a90..0e5c34f 100644 ---- a/src/cmd/go/internal/work/exec.go -+++ b/src/cmd/go/internal/work/exec.go -@@ -2630,6 +2630,66 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo - noCompiler() - } - -+ // Double check the //go:cgo_ldflag comments in the generated files. -+ // The compiler only permits such comments in files whose base name -+ // starts with "_cgo_". Make sure that the comments in those files -+ // are safe. This is a backstop against people somehow smuggling -+ // such a comment into a file generated by cgo. -+ if cfg.BuildToolchainName == "gc" && !cfg.BuildN { -+ var flags []string -+ for _, f := range outGo { -+ if !strings.HasPrefix(filepath.Base(f), "_cgo_") { -+ continue -+ } -+ -+ src, err := ioutil.ReadFile(f) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ const cgoLdflag = "//go:cgo_ldflag" -+ idx := bytes.Index(src, []byte(cgoLdflag)) -+ for idx >= 0 { -+ // We are looking at //go:cgo_ldflag. -+ // Find start of line. -+ start := bytes.LastIndex(src[:idx], []byte("\n")) -+ if start == -1 { -+ start = 0 -+ } -+ -+ // Find end of line. -+ end := bytes.Index(src[idx:], []byte("\n")) -+ if end == -1 { -+ end = len(src) -+ } else { -+ end += idx -+ } -+ -+ // Check for first line comment in line. -+ // We don't worry about /* */ comments, -+ // which normally won't appear in files -+ // generated by cgo. -+ commentStart := bytes.Index(src[start:], []byte("//")) -+ commentStart += start -+ // If that line comment is //go:cgo_ldflag, -+ // it's a match. -+ if bytes.HasPrefix(src[commentStart:], []byte(cgoLdflag)) { -+ // Pull out the flag, and unquote it. -+ // This is what the compiler does. -+ flag := string(src[idx+len(cgoLdflag) : end]) -+ flag = strings.TrimSpace(flag) -+ flag = strings.Trim(flag, `"`) -+ flags = append(flags, flag) -+ } -+ src = src[end:] -+ idx = bytes.Index(src, []byte(cgoLdflag)) -+ } -+ } -+ if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil { -+ return nil, nil, err -+ } -+ } -+ - return outGo, outObj, nil - } - --- -2.19.1 - diff --git a/0020-release-branch.go1.15-net-http-add-connections-back-.patch b/0020-release-branch.go1.15-net-http-add-connections-back-.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3b0198bc2a528fa9a23436fd422092107db2197 --- /dev/null +++ b/0020-release-branch.go1.15-net-http-add-connections-back-.patch @@ -0,0 +1,129 @@ +From 1c60e0d928764b1b755c494d4a760eb51b99bc90 Mon Sep 17 00:00:00 2001 +From: Michael Fraenkel +Date: Wed, 2 Dec 2020 17:07:27 -0700 +Subject: [PATCH 20/44] [release-branch.go1.15] net/http: add connections back + that haven't been canceled + +Issue #41600 fixed the issue when a second request canceled a connection +while the first request was still in roundTrip. +This uncovered a second issue where a request was being canceled (in +roundtrip) but the connection was put back into the idle pool for a +subsequent request. +The fix is the similar except its now in readLoop instead of roundTrip. +A persistent connection is only added back if it successfully removed +the cancel function; otherwise we know the roundTrip has started +cancelRequest. + +Fixes #42935. +Updates #42942. + +Change-Id: Ia56add20880ccd0c1ab812d380d8628e45f6f44c +Reviewed-on: https://go-review.googlesource.com/c/go/+/274973 +Trust: Dmitri Shuralyov +Trust: Damien Neil +Reviewed-by: Damien Neil +(cherry picked from commit 854a2f8e01a554d8052445563863775406a04b71) +Reviewed-on: https://go-review.googlesource.com/c/go/+/297910 +Run-TryBot: Dmitri Shuralyov +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/1c60e0d928764b1b755c494d4a760eb51b99bc90 + +--- + src/net/http/transport.go | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/src/net/http/transport.go b/src/net/http/transport.go +index 6fb2ea5663..6e430b9885 100644 +--- a/src/net/http/transport.go ++++ b/src/net/http/transport.go +@@ -766,7 +766,8 @@ func (t *Transport) CancelRequest(req *Request) { + } + + // Cancel an in-flight request, recording the error value. +-func (t *Transport) cancelRequest(key cancelKey, err error) { ++// Returns whether the request was canceled. ++func (t *Transport) cancelRequest(key cancelKey, err error) bool { + t.reqMu.Lock() + cancel := t.reqCanceler[key] + delete(t.reqCanceler, key) +@@ -774,6 +775,8 @@ func (t *Transport) cancelRequest(key cancelKey, err error) { + if cancel != nil { + cancel(err) + } ++ ++ return cancel != nil + } + + // +@@ -2087,18 +2090,17 @@ func (pc *persistConn) readLoop() { + } + + if !hasBody || bodyWritable { +- pc.t.setReqCanceler(rc.cancelKey, nil) ++ replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) + + // Put the idle conn back into the pool before we send the response + // so if they process it quickly and make another request, they'll + // get this same conn. But we use the unbuffered channel 'rc' + // to guarantee that persistConn.roundTrip got out of its select + // potentially waiting for this persistConn to close. +- // but after + alive = alive && + !pc.sawEOF && + pc.wroteRequest() && +- tryPutIdleConn(trace) ++ replaced && tryPutIdleConn(trace) + + if bodyWritable { + closeErr = errCallerOwnsConn +@@ -2160,12 +2162,12 @@ func (pc *persistConn) readLoop() { + // reading the response body. (or for cancellation or death) + select { + case bodyEOF := <-waitForBodyRead: +- pc.t.setReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool ++ replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool + alive = alive && + bodyEOF && + !pc.sawEOF && + pc.wroteRequest() && +- tryPutIdleConn(trace) ++ replaced && tryPutIdleConn(trace) + if bodyEOF { + eofc <- struct{}{} + } +@@ -2561,6 +2563,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err + cancelChan := req.Request.Cancel + ctxDoneChan := req.Context().Done() + pcClosed := pc.closech ++ canceled := false + for { + testHookWaitResLoop() + select { +@@ -2582,8 +2585,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err + } + case <-pcClosed: + pcClosed = nil +- // check if we are still using the connection +- if pc.t.replaceReqCanceler(req.cancelKey, nil) { ++ if canceled || pc.t.replaceReqCanceler(req.cancelKey, nil) { + if debugRoundTrip { + req.logf("closech recv: %T %#v", pc.closed, pc.closed) + } +@@ -2607,10 +2609,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err + } + return re.res, nil + case <-cancelChan: +- pc.t.cancelRequest(req.cancelKey, errRequestCanceled) ++ canceled = pc.t.cancelRequest(req.cancelKey, errRequestCanceled) + cancelChan = nil + case <-ctxDoneChan: +- pc.t.cancelRequest(req.cancelKey, req.Context().Err()) ++ canceled = pc.t.cancelRequest(req.cancelKey, req.Context().Err()) + cancelChan = nil + ctxDoneChan = nil + } +-- +2.27.0 + diff --git a/0021-golang-fix-CVE-2020-28367.patch b/0021-golang-fix-CVE-2020-28367.patch deleted file mode 100644 index a5ca6edc2c76be026951c98269da14a39e2cd74d..0000000000000000000000000000000000000000 --- a/0021-golang-fix-CVE-2020-28367.patch +++ /dev/null @@ -1,67 +0,0 @@ -From ac9a264a575bbbc9de2374a65a6c8fd50c32000d Mon Sep 17 00:00:00 2001 -From: liuzekun -Date: Mon, 30 Nov 2020 22:18:43 -0500 -Subject: [PATCH] golang: fix CVE-2020-28367 - -Upstream: https://github.com/golang/go/commit/da7aa86917811a571e6634b45a457f918b8e6561 -cmd/go: in cgoflags, permit -DX1, prohibit -Wp,-D,opt - -Restrict -D and -U to ASCII C identifiers, but do permit trailing digits. -When using -Wp, prohibit commas in -D values. - -Change-Id: Ibfc4dfdd6e6c258e131448e7682610c44eee9492 -Reviewed-on: https://go-review.googlesource.com/c/go/+/267277 -Trust: Ian Lance Taylor -Run-TryBot: Ian Lance Taylor -TryBot-Result: Go Bot -Reviewed-by: Bryan C. Mills ---- - src/cmd/go/internal/work/security.go | 4 ++-- - src/cmd/go/internal/work/security_test.go | 2 ++ - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go -index 0d8da21..b00c21e 100644 ---- a/src/cmd/go/internal/work/security.go -+++ b/src/cmd/go/internal/work/security.go -@@ -42,7 +42,7 @@ import ( - var re = lazyregexp.New - - var validCompilerFlags = []*lazyregexp.Regexp{ -- re(`-D([A-Za-z_].*)`), -+ re(`-D([A-Za-z_][A-Za-z0-9_]*)(=[^@\-]*)?`), - re(`-F([^@\-].*)`), - re(`-I([^@\-].*)`), - re(`-O`), -@@ -50,7 +50,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{ - re(`-W`), - re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. - re(`-Wa,-mbig-obj`), -- re(`-Wp,-D([A-Za-z_].*)`), -+ re(`-Wp,-D([A-Za-z_][A-Za-z0-9_]*)(=[^@,\-]*)?`), - re(`-ansi`), - re(`-f(no-)?asynchronous-unwind-tables`), - re(`-f(no-)?blocks`), -diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go -index fd8caea..eac029d 100644 ---- a/src/cmd/go/internal/work/security_test.go -+++ b/src/cmd/go/internal/work/security_test.go -@@ -21,6 +21,7 @@ var goodCompilerFlags = [][]string{ - {"-Osmall"}, - {"-W"}, - {"-Wall"}, -+ {"-Wp,-Dfoo1"}, - {"-fobjc-arc"}, - {"-fno-objc-arc"}, - {"-fomit-frame-pointer"}, -@@ -70,6 +71,7 @@ var badCompilerFlags = [][]string{ - {"-I-dir"}, - {"-O@1"}, - {"-Wa,-foo"}, -+ {"-Wp,-DX,-D@X"}, - {"-W@foo"}, - {"-g@gdb"}, - {"-g-gdb"}, --- -2.19.1 - diff --git a/0021-release-branch.go1.15-security-encoding-xml-prevent-.patch b/0021-release-branch.go1.15-security-encoding-xml-prevent-.patch new file mode 100644 index 0000000000000000000000000000000000000000..294539e68dc268a9e50c930cd9b4eb83898d44a6 --- /dev/null +++ b/0021-release-branch.go1.15-security-encoding-xml-prevent-.patch @@ -0,0 +1,189 @@ +From 91062c2e4cbbf78a108919f6ed3ded1173937cf3 Mon Sep 17 00:00:00 2001 +From: Katie Hockman +Date: Mon, 1 Mar 2021 09:54:00 -0500 +Subject: [PATCH 21/44] [release-branch.go1.15-security] encoding/xml: prevent + infinite loop while decoding + +This change properly handles a TokenReader which +returns an EOF in the middle of an open XML +element. + +Thanks to Sam Whited for reporting this. + +Fixes CVE-2021-27918 + +Change-Id: Id02a3f3def4a1b415fa2d9a8e3b373eb6cb0f433 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1004594 +Reviewed-by: Russ Cox +Reviewed-by: Roland Shoemaker +Reviewed-by: Filippo Valsorda +(cherry picked from commit e7ce1f6746223ec7b4caa3b1ece25d9be3864710) +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1014236 + +Conflict:NA +Reference:https://github.com/golang/go/commit/91062c2e4cbbf78a108919f6ed3ded1173937cf3 + +--- + src/encoding/xml/xml.go | 19 ++++--- + src/encoding/xml/xml_test.go | 104 +++++++++++++++++++++++++++-------- + 2 files changed, 92 insertions(+), 31 deletions(-) + +diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go +index adaf4daf19..6f9594d7ba 100644 +--- a/src/encoding/xml/xml.go ++++ b/src/encoding/xml/xml.go +@@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder { + // it will return an error. + // + // Token implements XML name spaces as described by +-// https://www.w3.org/TR/REC-xml-names/. Each of the ++// https://www.w3.org/TR/REC-xml-names/. Each of the + // Name structures contained in the Token has the Space + // set to the URL identifying its name space when known. + // If Token encounters an unrecognized name space prefix, +@@ -285,16 +285,17 @@ func (d *Decoder) Token() (Token, error) { + if d.nextToken != nil { + t = d.nextToken + d.nextToken = nil +- } else if t, err = d.rawToken(); err != nil { +- switch { +- case err == io.EOF && d.t != nil: +- err = nil +- case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF: +- err = d.syntaxError("unexpected EOF") ++ } else { ++ if t, err = d.rawToken(); t == nil && err != nil { ++ if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF { ++ err = d.syntaxError("unexpected EOF") ++ } ++ return nil, err + } +- return t, err ++ // We still have a token to process, so clear any ++ // errors (e.g. EOF) and proceed. ++ err = nil + } +- + if !d.Strict { + if t1, ok := d.autoClose(t); ok { + d.nextToken = t +diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go +index efddca43e9..5672ebb375 100644 +--- a/src/encoding/xml/xml_test.go ++++ b/src/encoding/xml/xml_test.go +@@ -33,30 +33,90 @@ func (t *toks) Token() (Token, error) { + + func TestDecodeEOF(t *testing.T) { + start := StartElement{Name: Name{Local: "test"}} +- t.Run("EarlyEOF", func(t *testing.T) { +- d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{ +- start, +- start.End(), +- }}) +- err := d.Decode(&struct { +- XMLName Name `xml:"test"` +- }{}) +- if err != nil { +- t.Error(err) ++ tests := []struct { ++ name string ++ tokens []Token ++ ok bool ++ }{ ++ { ++ name: "OK", ++ tokens: []Token{ ++ start, ++ start.End(), ++ }, ++ ok: true, ++ }, ++ { ++ name: "Malformed", ++ tokens: []Token{ ++ start, ++ StartElement{Name: Name{Local: "bad"}}, ++ start.End(), ++ }, ++ ok: false, ++ }, ++ } ++ for _, tc := range tests { ++ for _, eof := range []bool{true, false} { ++ name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof) ++ t.Run(name, func(t *testing.T) { ++ d := NewTokenDecoder(&toks{ ++ earlyEOF: eof, ++ t: tc.tokens, ++ }) ++ err := d.Decode(&struct { ++ XMLName Name `xml:"test"` ++ }{}) ++ if tc.ok && err != nil { ++ t.Fatalf("d.Decode: expected nil error, got %v", err) ++ } ++ if _, ok := err.(*SyntaxError); !tc.ok && !ok { ++ t.Errorf("d.Decode: expected syntax error, got %v", err) ++ } ++ }) + } +- }) +- t.Run("LateEOF", func(t *testing.T) { +- d := NewTokenDecoder(&toks{t: []Token{ +- start, +- start.End(), +- }}) +- err := d.Decode(&struct { +- XMLName Name `xml:"test"` +- }{}) +- if err != nil { +- t.Error(err) ++ } ++} ++ ++type toksNil struct { ++ returnEOF bool ++ t []Token ++} ++ ++func (t *toksNil) Token() (Token, error) { ++ if len(t.t) == 0 { ++ if !t.returnEOF { ++ // Return nil, nil before returning an EOF. It's legal, but ++ // discouraged. ++ t.returnEOF = true ++ return nil, nil + } +- }) ++ return nil, io.EOF ++ } ++ var tok Token ++ tok, t.t = t.t[0], t.t[1:] ++ return tok, nil ++} ++ ++func TestDecodeNilToken(t *testing.T) { ++ for _, strict := range []bool{true, false} { ++ name := fmt.Sprintf("Strict=%v", strict) ++ t.Run(name, func(t *testing.T) { ++ start := StartElement{Name: Name{Local: "test"}} ++ bad := StartElement{Name: Name{Local: "bad"}} ++ d := NewTokenDecoder(&toksNil{ ++ // Malformed ++ t: []Token{start, bad, start.End()}, ++ }) ++ d.Strict = strict ++ err := d.Decode(&struct { ++ XMLName Name `xml:"test"` ++ }{}) ++ if _, ok := err.(*SyntaxError); !ok { ++ t.Errorf("d.Decode: expected syntax error, got %v", err) ++ } ++ }) ++ } + } + + const testInput = ` +-- +2.27.0 + diff --git a/0022-fix-CVE-2020-29509-CVE-2020-29511.patch b/0022-fix-CVE-2020-29509-CVE-2020-29511.patch deleted file mode 100644 index a64000bf5875cc04b9fc686ad42c2230ce149d92..0000000000000000000000000000000000000000 --- a/0022-fix-CVE-2020-29509-CVE-2020-29511.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 96ffe2941c07e4a6b92357b6eb8739304f839bef Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 23 Dec 2020 15:58:14 +0800 -Subject: [PATCH 1/2] encoding/xml: handle leading, trailing, or double colons - in names - -Before this change, <:name> would parse as , which could cause -issues in applications that rely on the parse-encode cycle to -round-trip. Similarly, would parse as expected but then -have the attribute dropped when serializing because its name was empty. -Finally, would parse and get serialized incorrectly. All these -values are invalid XML, but to minimize the impact of this change, we -parse them whole into Name.Local. - -This issue was reported by Juho Nurminen of Mattermost as it leads to -round-trip mismatches. See #43168. It's not being fixed in a security -release because round-trip stability is not a currently supported -security property of encoding/xml, and we don't believe these fixes -would be sufficient to reliably guarantee it in the future. - -Fixes CVE-2020-29509 -Fixes CVE-2020-29511 -Updates #43168 -Conflict: NA -Reference: https://go-review.googlesource.com/c/go/+/277892 -Change-Id: I68321c4d867305046f664347192948a889af3c7f - -Signed-off-by: jingrui ---- - src/encoding/xml/xml.go | 5 ++-- - src/encoding/xml/xml_test.go | 58 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 61 insertions(+), 2 deletions(-) - -diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go -index ca059440a1..073ceee1b2 100644 ---- a/src/encoding/xml/xml.go -+++ b/src/encoding/xml/xml.go -@@ -1152,8 +1152,9 @@ func (d *Decoder) nsname() (name Name, ok bool) { - if !ok { - return - } -- i := strings.Index(s, ":") -- if i < 0 { -+ if strings.Count(s, ":") > 1 { -+ name.Local = s -+ } else if i := strings.Index(s, ":"); i < 1 || i > len(s)-2 { - name.Local = s - } else { - name.Space = s[0:i] -diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go -index ee4ffa2420..eef4dc3001 100644 ---- a/src/encoding/xml/xml_test.go -+++ b/src/encoding/xml/xml_test.go -@@ -898,3 +898,61 @@ func TestTokenUnmarshaler(t *testing.T) { - d := NewTokenDecoder(tokReader{}) - d.Decode(&Failure{}) - } -+ -+func testRoundTrip(t *testing.T, input string) { -+ t.Logf("input: %q", input) -+ d := NewDecoder(strings.NewReader(input)) -+ var tokens []Token -+ var buf bytes.Buffer -+ e := NewEncoder(&buf) -+ for { -+ tok, err := d.Token() -+ if err == io.EOF { -+ break -+ } -+ if err != nil { -+ t.Fatalf("invalid input: %v", err) -+ } -+ if err := e.EncodeToken(tok); err != nil { -+ t.Fatalf("failed to re-encode input: %v", err) -+ } -+ tokens = append(tokens, CopyToken(tok)) -+ } -+ if err := e.Flush(); err != nil { -+ t.Fatal(err) -+ } -+ t.Logf("output: %q", buf.String()) -+ -+ d = NewDecoder(&buf) -+ for { -+ tok, err := d.Token() -+ if err == io.EOF { -+ break -+ } -+ if err != nil { -+ t.Fatalf("failed to decode output: %v", err) -+ } -+ if len(tokens) == 0 { -+ t.Fatalf("unexpected token: %#v", tok) -+ } -+ a, b := tokens[0], tok -+ if !reflect.DeepEqual(a, b) { -+ t.Fatalf("token mismatch: %#v vs %#v", a, b) -+ } -+ tokens = tokens[1:] -+ } -+ if len(tokens) > 0 { -+ t.Fatalf("lost tokens: %#v", tokens) -+ } -+} -+ -+func TestRoundTrip(t *testing.T) { -+ tests := map[string]string{ -+ "leading colon": `<::Test ::foo="bar"><:::Hello>`, -+ "trailing colon": ``, -+ "double colon": ``, -+ } -+ for name, input := range tests { -+ t.Run(name, func(t *testing.T) { testRoundTrip(t, input) }) -+ } -+} --- -2.17.1 - diff --git a/0023-fix-CVE-2020-29510.patch b/0023-fix-CVE-2020-29510.patch deleted file mode 100644 index 0f8298a3b00946233a7b85b13b1d8dc6a1ce4e28..0000000000000000000000000000000000000000 --- a/0023-fix-CVE-2020-29510.patch +++ /dev/null @@ -1,62 +0,0 @@ -From e2710c3983b3249ba30f2d21802c984aef5fb163 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 23 Dec 2020 16:03:15 +0800 -Subject: [PATCH 2/2] encoding/xml: replace comments inside directives with a - space - -A Directive (like ) can't have other nodes nested inside -it (in our data structure representation), so there is no way to -preserve comments. The previous behavior was to just elide them, which -however might change the semantic meaning of the surrounding markup. -Instead, replace them with a space which hopefully has the same semantic -effect of the comment. - -Directives are not actually a node type in the XML spec, which instead -specifies each of them separately ( ---- - src/encoding/xml/xml.go | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go -index 073ceee1b2..3746018613 100644 ---- a/src/encoding/xml/xml.go -+++ b/src/encoding/xml/xml.go -@@ -764,6 +764,12 @@ func (d *Decoder) rawToken() (Token, error) { - } - b0, b1 = b1, b - } -+ -+ // Replace the comment with a space in the returned Directive -+ // body, so that markup parts that were separated by the comment -+ // (like a "<" and a "!") don't get joined when re-encoding the -+ // Directive, taking new semantic meaning. -+ d.buf.WriteByte(' ') - } - } - return Directive(d.buf.Bytes()), nil --- -2.17.1 - diff --git a/0023-release-branch.go1.15-cmd-go-don-t-report-missing-st.patch b/0023-release-branch.go1.15-cmd-go-don-t-report-missing-st.patch new file mode 100644 index 0000000000000000000000000000000000000000..71642c7754b2049564dd838a781afd07bc682cbd --- /dev/null +++ b/0023-release-branch.go1.15-cmd-go-don-t-report-missing-st.patch @@ -0,0 +1,121 @@ +From ba3dc70dc5c9f2162024b09d6b13bda1f4575b01 Mon Sep 17 00:00:00 2001 +From: Jay Conrod +Date: Thu, 4 Mar 2021 11:50:31 -0500 +Subject: [PATCH 23/44] [release-branch.go1.15] cmd/go: don't report missing + std import errors for tidy and vendor + +'go mod tidy' and 'go mod vendor' normally report errors when a +package can't be imported, even if the import appears in a file that +wouldn't be compiled by the current version of Go. These errors are +common for packages introduced in higher versions of Go, like "embed" +in 1.16. + +This change causes 'go mod tidy' and 'go mod vendor' to ignore +missing package errors if the import path appears to come from the +standard library because it lacks a dot in the first path element. + +NOTE: This change is not a clean cherry-pick of CL 298749 because +parts of modload were substantially rewritten after 1.15. + +Fixes #44792 +Updates #27063 + +Change-Id: I61d6443e77ab95fd8c0d1514f57ef4c8885a77cc +Reviewed-on: https://go-review.googlesource.com/c/go/+/298749 +Trust: Jay Conrod +Run-TryBot: Jay Conrod +Reviewed-by: Bryan C. Mills +TryBot-Result: Go Bot +(cherry picked from commit 56d52e661114be60fb1893b034ac0c5976b622af) +Reviewed-on: https://go-review.googlesource.com/c/go/+/298950 + +Conflict:NA +Reference:https://github.com/golang/go/commit/ba3dc70dc5c9f2162024b09d6b13bda1f4575b01 + +--- + src/cmd/go/internal/modcmd/tidy.go | 1 + + src/cmd/go/internal/modcmd/vendor.go | 1 + + src/cmd/go/internal/modload/init.go | 6 ++++++ + src/cmd/go/internal/modload/load.go | 5 +++++ + src/cmd/go/testdata/script/mod_tidy_error.txt | 4 ++-- + 5 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go +index af2b04c0c2..5ff847485c 100644 +--- a/src/cmd/go/internal/modcmd/tidy.go ++++ b/src/cmd/go/internal/modcmd/tidy.go +@@ -42,6 +42,7 @@ func runTidy(cmd *base.Command, args []string) { + base.Fatalf("go mod tidy: no arguments allowed") + } + ++ modload.SilenceMissingStdImports = true + modload.LoadALL() + modload.TidyBuildList() + modTidyGoSum() // updates memory copy; WriteGoMod on next line flushes it out +diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go +index 8509ceb7a8..5a5bb943a5 100644 +--- a/src/cmd/go/internal/modcmd/vendor.go ++++ b/src/cmd/go/internal/modcmd/vendor.go +@@ -47,6 +47,7 @@ func runVendor(cmd *base.Command, args []string) { + if len(args) != 0 { + base.Fatalf("go mod vendor: vendor takes no arguments") + } ++ modload.SilenceMissingStdImports = true + pkgs := modload.LoadVendor() + + vdir := filepath.Join(modload.ModRoot(), "vendor") +diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go +index 664a2a1594..2360feef04 100644 +--- a/src/cmd/go/internal/modload/init.go ++++ b/src/cmd/go/internal/modload/init.go +@@ -56,6 +56,12 @@ var ( + CmdModModule string // module argument for 'go mod init' + + allowMissingModuleImports bool ++ ++ // SilenceMissingStdImports indicates that LoadALL should not print an error ++ // or terminate the process if an imported package is missing, and the import ++ // path looks like it might be in the standard library (perhaps in a future ++ // Go version). ++ SilenceMissingStdImports bool + ) + + // ModFile returns the parsed go.mod file. +diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go +index 30992e0cc2..e5ea1a6c23 100644 +--- a/src/cmd/go/internal/modload/load.go ++++ b/src/cmd/go/internal/modload/load.go +@@ -433,6 +433,11 @@ func loadAll(testAll bool) []string { + var paths []string + for _, pkg := range loaded.pkgs { + if pkg.err != nil { ++ if impErr := (*ImportMissingError)(nil); SilenceMissingStdImports && ++ errors.As(pkg.err, &impErr) && ++ search.IsStandardImportPath(impErr.Path) { ++ continue ++ } + base.Errorf("%s: %v", pkg.stackText(), pkg.err) + continue + } +diff --git a/src/cmd/go/testdata/script/mod_tidy_error.txt b/src/cmd/go/testdata/script/mod_tidy_error.txt +index b6c24ceaf7..395537b1a7 100644 +--- a/src/cmd/go/testdata/script/mod_tidy_error.txt ++++ b/src/cmd/go/testdata/script/mod_tidy_error.txt +@@ -4,12 +4,12 @@ env GO111MODULE=on + # 'go mod tidy' and 'go mod vendor' should not hide loading errors. + + ! go mod tidy +-stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)' ++! stderr 'package nonexist is not in GOROOT' + stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com' + stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist' + + ! go mod vendor +-stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)' ++! stderr 'package nonexist is not in GOROOT' + stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com' + stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist' + +-- +2.27.0 + diff --git a/0025-release-branch.go1.15-cmd-go-internal-modfetch-detec.patch b/0025-release-branch.go1.15-cmd-go-internal-modfetch-detec.patch new file mode 100644 index 0000000000000000000000000000000000000000..9cf8ece8a9977690bf4cb9ecb8940397779d3f13 --- /dev/null +++ b/0025-release-branch.go1.15-cmd-go-internal-modfetch-detec.patch @@ -0,0 +1,310 @@ +From 7038a380bcd0183842471c1984da491e044d3d34 Mon Sep 17 00:00:00 2001 +From: Jay Conrod +Date: Wed, 3 Mar 2021 16:30:22 -0500 +Subject: [PATCH 25/44] [release-branch.go1.15] cmd/go/internal/modfetch: + detect and recover from missing ziphash file + +Previously, if an extracted module directory existed in the module +cache, but the corresponding ziphash file did not, if the sum was +missing from go.sum, we would not verify the sum. This caused 'go get' +not to write missing sums. 'go build' in readonly mode (now the +default) checks for missing sums and doesn't attempt to fetch modules +that can't be verified against go.sum. + +With this change, when requesting the module directory with +modfetch.DownloadDir, if the ziphash file is missing, the go command +will re-hash the zip without downloading or re-extracting it again. + +Note that the go command creates the ziphash file before the module +directory, but another program could remove it separately, and it +might not be present after a crash. + +Fixes #44872 + +Change-Id: I64551e048a3ba17d069de1ec123d5b8b2757543c +Reviewed-on: https://go-review.googlesource.com/c/go/+/298352 +Trust: Jay Conrod +Run-TryBot: Jay Conrod +TryBot-Result: Go Bot +Reviewed-by: Bryan C. Mills +(cherry picked from commit 302a400316319501748c0f034464fa70e7815272) +Reviewed-on: https://go-review.googlesource.com/c/go/+/299830 + +Conflict:NA +Reference:https://github.com/golang/go/commit/7038a380bcd0183842471c1984da491e044d3d34 + +--- + src/cmd/go/internal/modfetch/cache.go | 17 ++++ + src/cmd/go/internal/modfetch/fetch.go | 77 ++++++++++++------- + .../script/mod_get_missing_ziphash.txt | 55 +++++++++++++ + src/cmd/go/testdata/script/mod_verify.txt | 7 +- + 4 files changed, 125 insertions(+), 31 deletions(-) + create mode 100644 src/cmd/go/testdata/script/mod_get_missing_ziphash.txt + +diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go +index e3074b775e..0b64a6943b 100644 +--- a/src/cmd/go/internal/modfetch/cache.go ++++ b/src/cmd/go/internal/modfetch/cache.go +@@ -83,6 +83,7 @@ func DownloadDir(m module.Version) (string, error) { + return "", err + } + ++ // Check whether the directory itself exists. + dir := filepath.Join(cfg.GOMODCACHE, enc+"@"+encVer) + if fi, err := os.Stat(dir); os.IsNotExist(err) { + return dir, err +@@ -91,6 +92,9 @@ func DownloadDir(m module.Version) (string, error) { + } else if !fi.IsDir() { + return dir, &DownloadDirPartialError{dir, errors.New("not a directory")} + } ++ ++ // Check if a .partial file exists. This is created at the beginning of ++ // a download and removed after the zip is extracted. + partialPath, err := CachePath(m, "partial") + if err != nil { + return dir, err +@@ -100,6 +104,19 @@ func DownloadDir(m module.Version) (string, error) { + } else if !os.IsNotExist(err) { + return dir, err + } ++ ++ // Check if a .ziphash file exists. It should be created before the ++ // zip is extracted, but if it was deleted (by another program?), we need ++ // to re-calculate it. ++ ziphashPath, err := CachePath(m, "ziphash") ++ if err != nil { ++ return dir, err ++ } ++ if _, err := os.Stat(ziphashPath); os.IsNotExist(err) { ++ return dir, &DownloadDirPartialError{dir, errors.New("ziphash file is missing")} ++ } else if err != nil { ++ return dir, err ++ } + return dir, nil + } + +diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go +index fd7a5cef83..6a6c972157 100644 +--- a/src/cmd/go/internal/modfetch/fetch.go ++++ b/src/cmd/go/internal/modfetch/fetch.go +@@ -206,13 +206,16 @@ func DownloadZip(mod module.Version) (zipfile string, err error) { + if err != nil { + return cached{"", err} + } ++ ziphashfile := zipfile + "hash" + +- // Skip locking if the zipfile already exists. ++ // Return without locking if the zip and ziphash files exist. + if _, err := os.Stat(zipfile); err == nil { +- return cached{zipfile, nil} ++ if _, err := os.Stat(ziphashfile); err == nil { ++ return cached{zipfile, nil} ++ } + } + +- // The zip file does not exist. Acquire the lock and create it. ++ // The zip or ziphash file does not exist. Acquire the lock and create them. + if cfg.CmdName != "mod download" { + fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version) + } +@@ -222,14 +225,6 @@ func DownloadZip(mod module.Version) (zipfile string, err error) { + } + defer unlock() + +- // Double-check that the zipfile was not created while we were waiting for +- // the lock. +- if _, err := os.Stat(zipfile); err == nil { +- return cached{zipfile, nil} +- } +- if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil { +- return cached{"", err} +- } + if err := downloadZip(mod, zipfile); err != nil { + return cached{"", err} + } +@@ -239,6 +234,25 @@ func DownloadZip(mod module.Version) (zipfile string, err error) { + } + + func downloadZip(mod module.Version, zipfile string) (err error) { ++ // Double-check that the zipfile was not created while we were waiting for ++ // the lock in DownloadZip. ++ ziphashfile := zipfile + "hash" ++ var zipExists, ziphashExists bool ++ if _, err := os.Stat(zipfile); err == nil { ++ zipExists = true ++ } ++ if _, err := os.Stat(ziphashfile); err == nil { ++ ziphashExists = true ++ } ++ if zipExists && ziphashExists { ++ return nil ++ } ++ ++ // Create parent directories. ++ if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil { ++ return err ++ } ++ + // Clean up any remaining tempfiles from previous runs. + // This is only safe to do because the lock file ensures that their + // writers are no longer active. +@@ -250,6 +264,12 @@ func downloadZip(mod module.Version, zipfile string) (err error) { + } + } + ++ // If the zip file exists, the ziphash file must have been deleted ++ // or lost after a file system crash. Re-hash the zip without downloading. ++ if zipExists { ++ return hashZip(mod, zipfile, ziphashfile) ++ } ++ + // From here to the os.Rename call below is functionally almost equivalent to + // renameio.WriteToFile, with one key difference: we want to validate the + // contents of the file (by hashing it) before we commit it. Because the file +@@ -306,15 +326,7 @@ func downloadZip(mod module.Version, zipfile string) (err error) { + } + + // Hash the zip file and check the sum before renaming to the final location. +- hash, err := dirhash.HashZip(f.Name(), dirhash.DefaultHash) +- if err != nil { +- return err +- } +- if err := checkModSum(mod, hash); err != nil { +- return err +- } +- +- if err := renameio.WriteFile(zipfile+"hash", []byte(hash), 0666); err != nil { ++ if err := hashZip(mod, f.Name(), ziphashfile); err != nil { + return err + } + if err := os.Rename(f.Name(), zipfile); err != nil { +@@ -326,6 +338,22 @@ func downloadZip(mod module.Version, zipfile string) (err error) { + return nil + } + ++// hashZip reads the zip file opened in f, then writes the hash to ziphashfile, ++// overwriting that file if it exists. ++// ++// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns ++// an error and does not write ziphashfile. ++func hashZip(mod module.Version, zipfile, ziphashfile string) error { ++ hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash) ++ if err != nil { ++ return err ++ } ++ if err := checkModSum(mod, hash); err != nil { ++ return err ++ } ++ return renameio.WriteFile(ziphashfile, []byte(hash), 0666) ++} ++ + // makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir + // and its transitive contents. + func makeDirsReadOnly(dir string) { +@@ -457,11 +485,6 @@ func readGoSum(dst map[module.Version][]string, file string, data []byte) error + + // checkMod checks the given module's checksum. + func checkMod(mod module.Version) { +- if cfg.GOMODCACHE == "" { +- // Do not use current directory. +- return +- } +- + // Do the file I/O before acquiring the go.sum lock. + ziphash, err := CachePath(mod, "ziphash") + if err != nil { +@@ -469,10 +492,6 @@ func checkMod(mod module.Version) { + } + data, err := renameio.ReadFile(ziphash) + if err != nil { +- if errors.Is(err, os.ErrNotExist) { +- // This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes. +- return +- } + base.Fatalf("verifying %v", module.VersionError(mod, err)) + } + h := strings.TrimSpace(string(data)) +diff --git a/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt +new file mode 100644 +index 0000000000..afb5d2e844 +--- /dev/null ++++ b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt +@@ -0,0 +1,55 @@ ++# Test that if the module cache contains an extracted source directory but not ++# a ziphash, 'go build' complains about a missing sum, and 'go get' adds ++# the sum. Verifies #44749. ++ ++# With a tidy go.sum, go build succeeds. This also populates the module cache. ++cp go.sum.tidy go.sum ++go build -n use ++env GOPROXY=off ++env GOSUMDB=off ++ ++# Control case: if we delete the hash for rsc.io/quote v1.5.2, ++# 'go build' reports an error. 'go get' adds the sum. ++cp go.sum.bug go.sum ++! go build -n -mod=readonly use ++stderr '^go: updates to go.sum needed, disabled by -mod=readonly$' ++go get -d use ++cmp go.sum go.sum.tidy ++go build -n use ++ ++# If we delete the hash *and* the ziphash file, we should see the same behavior. ++cp go.sum.bug go.sum ++rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash ++! go build -n -mod=readonly use ++stderr '^go: updates to go.sum needed, disabled by -mod=readonly$' ++go get -d use ++cmp go.sum go.sum.tidy ++go build -n use ++ ++-- go.mod -- ++module use ++ ++go 1.17 ++ ++require rsc.io/quote v1.5.2 ++-- go.sum.tidy -- ++golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= ++golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= ++rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= ++rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= ++rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= ++rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= ++rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= ++rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= ++-- go.sum.bug -- ++golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= ++golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= ++rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= ++rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= ++rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= ++rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= ++rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= ++-- use.go -- ++package use ++ ++import _ "rsc.io/quote" +diff --git a/src/cmd/go/testdata/script/mod_verify.txt b/src/cmd/go/testdata/script/mod_verify.txt +index 646bc62bb7..7163d1a64b 100644 +--- a/src/cmd/go/testdata/script/mod_verify.txt ++++ b/src/cmd/go/testdata/script/mod_verify.txt +@@ -50,10 +50,13 @@ go mod tidy + grep '^rsc.io/quote v1.1.0/go.mod ' go.sum + grep '^rsc.io/quote v1.1.0 ' go.sum + +-# sync should ignore missing ziphash; verify should not ++# verify should fail on a missing ziphash. tidy should restore it. + rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash +-go mod tidy + ! go mod verify ++stderr '^rsc.io/quote v1.1.0: missing ziphash: open '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]rsc.io[/\\]quote[/\\]@v[/\\]v1.1.0.ziphash' ++go mod tidy ++exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash ++go mod verify + + # Packages below module root should not be mentioned in go.sum. + rm go.sum +-- +2.27.0 + diff --git a/0026-release-branch.go1.15-cmd-link-generate-trampoline-f.patch b/0026-release-branch.go1.15-cmd-link-generate-trampoline-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a6ef3e1bd21455e52c202c17cfe25b02076c724 --- /dev/null +++ b/0026-release-branch.go1.15-cmd-link-generate-trampoline-f.patch @@ -0,0 +1,133 @@ +From 7c88ae4117c16c1e5b80189b81d67845e1c40d9d Mon Sep 17 00:00:00 2001 +From: Cherry Zhang +Date: Tue, 16 Feb 2021 10:20:58 -0500 +Subject: [PATCH 26/44] [release-branch.go1.15] cmd/link: generate trampoline + for inter-dependent packages + +Currently, in the trampoline generation pass we expect packages +are laid out in dependency order, so a cross-package jump always +has a known target address so we can check if a trampoline is +needed. With linknames, there can be cycles in the package +dependency graph, making this algorithm no longer work. For them, +as the target address is unkown we conservatively generate a +trampoline. This may generate unnecessary trampolines (if the +packages turn out laid together), but package cycles are extremely +rare so this is fine. + +Updates #44639. +Fixes #44748. + +Change-Id: I2dc2998edacbda27d726fc79452313a21d07787a +Reviewed-on: https://go-review.googlesource.com/c/go/+/292490 +Trust: Cherry Zhang +Reviewed-by: Than McIntosh +(cherry picked from commit 098504c73ff6ece19566a1ac811ceed73be7c81d) +Reviewed-on: https://go-review.googlesource.com/c/go/+/298030 +Run-TryBot: Cherry Zhang +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/7c88ae4117c16c1e5b80189b81d67845e1c40d9d + +--- + src/cmd/link/internal/arm/asm.go | 16 +++++++++++----- + src/cmd/link/internal/ld/data.go | 12 +++++------- + src/cmd/link/internal/ppc64/asm.go | 12 +++++++++--- + 3 files changed, 25 insertions(+), 15 deletions(-) + +diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go +index 903e62108e..43643341d2 100644 +--- a/src/cmd/link/internal/arm/asm.go ++++ b/src/cmd/link/internal/arm/asm.go +@@ -373,10 +373,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { + r := relocs.At2(ri) + switch r.Type() { + case objabi.R_CALLARM: +- // r.Add is the instruction +- // low 24-bit encodes the target address +- t := (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4 +- if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { ++ var t int64 ++ // ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet ++ // laid out. Conservatively use a trampoline. This should be rare, as we lay out packages ++ // in dependency order. ++ if ldr.SymValue(rs) != 0 { ++ // r.Add is the instruction ++ // low 24-bit encodes the target address ++ t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4 ++ } ++ if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { + // direct call too far, need to insert trampoline. + // look up existing trampolines first. if we found one within the range + // of direct call, we can reuse it. otherwise create a new one. +@@ -447,7 +453,7 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *l + arch.ByteOrder.PutUint32(P[8:], o3) + tramp.SetData(P) + +- if linkmode == ld.LinkExternal { ++ if linkmode == ld.LinkExternal || ldr.SymValue(target) == 0 { + r := loader.Reloc{ + Off: 8, + Type: objabi.R_ADDR, +diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go +index d3f308c8fa..2b55a5f6fc 100644 +--- a/src/cmd/link/internal/ld/data.go ++++ b/src/cmd/link/internal/ld/data.go +@@ -105,14 +105,12 @@ func trampoline(ctxt *Link, s loader.Sym) { + } + rs = ldr.ResolveABIAlias(rs) + if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) { +- if ldr.SymPkg(rs) != ldr.SymPkg(s) { +- if !isRuntimeDepPkg(ldr.SymPkg(s)) || !isRuntimeDepPkg(ldr.SymPkg(rs)) { +- ctxt.Errorf(s, "unresolved inter-package jump to %s(%s) from %s", ldr.SymName(rs), ldr.SymPkg(rs), ldr.SymPkg(s)) +- } +- // runtime and its dependent packages may call to each other. +- // they are fine, as they will be laid down together. ++ if ldr.SymPkg(rs) == ldr.SymPkg(s) { ++ continue // symbols in the same package are laid out together ++ } ++ if isRuntimeDepPkg(ldr.SymPkg(s)) && isRuntimeDepPkg(ldr.SymPkg(rs)) { ++ continue // runtime packages are laid out together + } +- continue + } + + thearch.Trampoline(ctxt, ldr, ri, rs, s) +diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go +index b1c0873d7a..a3ecd43f89 100644 +--- a/src/cmd/link/internal/ppc64/asm.go ++++ b/src/cmd/link/internal/ppc64/asm.go +@@ -672,13 +672,19 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { + + relocs := ldr.Relocs(s) + r := relocs.At2(ri) +- t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) ++ var t int64 ++ // ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet ++ // laid out. Conservatively use a trampoline. This should be rare, as we lay out packages ++ // in dependency order. ++ if ldr.SymValue(rs) != 0 { ++ t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) ++ } + switch r.Type() { + case objabi.R_CALLPOWER: + + // If branch offset is too far then create a trampoline. + +- if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { ++ if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { + var tramp loader.Sym + for i := 0; ; i++ { + +@@ -769,7 +775,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta + + // With external linking, the target address must be + // relocated using LO and HA +- if ctxt.IsExternal() { ++ if ctxt.IsExternal() || ldr.SymValue(target) == 0 { + r := loader.Reloc{ + Off: 0, + Type: objabi.R_ADDRPOWER, +-- +2.27.0 + diff --git a/0027-release-branch.go1.15-net-http-update-bundled-x-net-.patch b/0027-release-branch.go1.15-net-http-update-bundled-x-net-.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6196290d6d9d2208dd93a4a153e444521f788b7 --- /dev/null +++ b/0027-release-branch.go1.15-net-http-update-bundled-x-net-.patch @@ -0,0 +1,49 @@ +From 69b943102868747ff2b62d9ada02c464d9984aef Mon Sep 17 00:00:00 2001 +From: Dmitri Shuralyov +Date: Mon, 29 Mar 2021 11:19:23 -0400 +Subject: [PATCH 27/44] [release-branch.go1.15] net/http: update bundled + x/net/http2 + +Bring in the change in CL 304309 with: + + go mod edit -replace=golang.org/x/net=golang.org/x/net@release-branch.go1.15-bundle + GOFLAGS='-mod=mod' go generate -run=bundle std + go mod edit -dropreplace=golang.org/x/net + go get -d golang.org/x/net@release-branch.go1.15 + go mod tidy + go mod vendor + +For #45076. +Updates #40213. + +Change-Id: I68d5e1f2394508c9cf8627fb852dd9e906d45016 +Reviewed-on: https://go-review.googlesource.com/c/go/+/305489 +Trust: Dmitri Shuralyov +Trust: Emmanuel Odeke +Run-TryBot: Dmitri Shuralyov +Reviewed-by: Emmanuel Odeke +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/69b943102868747ff2b62d9ada02c464d9984aef + +--- + src/net/http/h2_bundle.go | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go +index 678c6eb9d4..3d83084702 100644 +--- a/src/net/http/h2_bundle.go ++++ b/src/net/http/h2_bundle.go +@@ -8985,6 +8985,8 @@ func http2strSliceContains(ss []string, s string) bool { + + type http2erringRoundTripper struct{ err error } + ++func (rt http2erringRoundTripper) RoundTripErr() error { return rt.err } ++ + func (rt http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { return nil, rt.err } + + // gzipReader wraps a response body so it can lazily +-- +2.27.0 + diff --git a/0028-release-branch.go1.15-net-http-fix-detection-of-Roun.patch b/0028-release-branch.go1.15-net-http-fix-detection-of-Roun.patch new file mode 100644 index 0000000000000000000000000000000000000000..ecd987ac95779268059a530e49ff52765ec4515f --- /dev/null +++ b/0028-release-branch.go1.15-net-http-fix-detection-of-Roun.patch @@ -0,0 +1,81 @@ +From be872812063f29e9c0d280fb37289d40330d96db Mon Sep 17 00:00:00 2001 +From: Michael Fraenkel +Date: Thu, 16 Jul 2020 21:30:12 -0600 +Subject: [PATCH 28/44] [release-branch.go1.15] net/http: fix detection of + Roundtrippers that always error + +CL 220905 added code to identify alternate transports that always error +by using http2erringRoundTripper. This does not work when the transport +is from another package, e.g., http2.erringRoundTripper. +Expose a new method that allow detection of such a RoundTripper. +Switch to an interface that is both a RoundTripper and can return the +underlying error. + +Fixes #45076. +Updates #40213. + +Change-Id: I170739857ab9e99dffb5fa55c99b24b23c2f9c54 +Reviewed-on: https://go-review.googlesource.com/c/go/+/243258 +Reviewed-by: Emmanuel Odeke +Run-TryBot: Emmanuel Odeke +TryBot-Result: Gobot Gobot +Reviewed-on: https://go-review.googlesource.com/c/go/+/304210 +Trust: Dmitri Shuralyov +Trust: Emmanuel Odeke +Run-TryBot: Dmitri Shuralyov +TryBot-Result: Go Bot +Reviewed-by: Emmanuel Odeke + +Conflict:NA +Reference:https://github.com/golang/go/commit/be872812063f29e9c0d280fb37289d40330d96db + +--- + src/net/http/omithttp2.go | 4 ---- + src/net/http/transport.go | 8 ++++++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/net/http/omithttp2.go b/src/net/http/omithttp2.go +index 7e2f492579..c8f5c28a59 100644 +--- a/src/net/http/omithttp2.go ++++ b/src/net/http/omithttp2.go +@@ -32,10 +32,6 @@ type http2Transport struct { + func (*http2Transport) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) } + func (*http2Transport) CloseIdleConnections() {} + +-type http2erringRoundTripper struct{ err error } +- +-func (http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) } +- + type http2noDialH2RoundTripper struct{} + + func (http2noDialH2RoundTripper) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) } +diff --git a/src/net/http/transport.go b/src/net/http/transport.go +index 6e430b9885..88d15a5919 100644 +--- a/src/net/http/transport.go ++++ b/src/net/http/transport.go +@@ -1531,6 +1531,10 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro + return nil + } + ++type erringRoundTripper interface { ++ RoundTripErr() error ++} ++ + func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *persistConn, err error) { + pconn = &persistConn{ + t: t, +@@ -1697,9 +1701,9 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers + if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" { + if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok { + alt := next(cm.targetAddr, pconn.conn.(*tls.Conn)) +- if e, ok := alt.(http2erringRoundTripper); ok { ++ if e, ok := alt.(erringRoundTripper); ok { + // pconn.conn was closed by next (http2configureTransport.upgradeFn). +- return nil, e.err ++ return nil, e.RoundTripErr() + } + return &persistConn{t: t, cacheKey: pconn.cacheKey, alt: alt}, nil + } +-- +2.27.0 + diff --git a/0029-release-branch.go1.15-build-set-GOPATH-consistently-.patch b/0029-release-branch.go1.15-build-set-GOPATH-consistently-.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0a7d65710220c71eebe65c149e9d0bc7e842679 --- /dev/null +++ b/0029-release-branch.go1.15-build-set-GOPATH-consistently-.patch @@ -0,0 +1,105 @@ +From 6df5d3a581380a85183c591d1fd9063a5e8e4b23 Mon Sep 17 00:00:00 2001 +From: Russ Cox +Date: Tue, 26 Jan 2021 21:14:43 -0500 +Subject: [PATCH 29/44] [release-branch.go1.15] build: set GOPATH consistently + in run.bash, run.bat, run.rc + +We used to clear GOPATH in all the build scripts. +Clearing GOPATH is misleading at best, since you just end up +with the default GOPATH (%USERPROFILE%\go on Windows). +Unless that's your GOROOT, in which case you end up with a +fatal error from the go command (#43938). + +run.bash changed to setting GOPATH=/dev/null, which has no +clear analogue on Windows. + +run.rc still clears GOPATH. + +Change them all to set GOPATH to a non-existent directory +/nonexist-gopath or c:\nonexist-gopath. + +For #45238. +Fixes #45239. + +Change-Id: I51edd66d37ff6a891b0d0541d91ecba97fbbb03d +Reviewed-on: https://go-review.googlesource.com/c/go/+/288818 +Trust: Russ Cox +Trust: Jason A. Donenfeld +Reviewed-by: Cherry Zhang +Reviewed-by: Alex Brainman +Reviewed-by: Jason A. Donenfeld +(cherry picked from commit bb6efb96092cc8ae398c29e3b052a0051c746f88) +Reviewed-on: https://go-review.googlesource.com/c/go/+/304773 +Run-TryBot: Dmitri Shuralyov +TryBot-Result: Go Bot +Reviewed-by: Alexander Rakoczy +Reviewed-by: Carlos Amedee +Trust: Carlos Amedee + +Conflict:NA +Reference:https://github.com/golang/go/commit/6df5d3a581380a85183c591d1fd9063a5e8e4b23 + +--- + src/run.bash | 10 +--------- + src/run.bat | 4 +--- + src/run.rc | 9 ++++----- + 3 files changed, 6 insertions(+), 17 deletions(-) + +diff --git a/src/run.bash b/src/run.bash +index 706b4b60ee..2123c509f8 100755 +--- a/src/run.bash ++++ b/src/run.bash +@@ -23,15 +23,7 @@ fi + + eval $(../bin/go env) + export GOROOT # The api test requires GOROOT to be set, so set it to match ../bin/go. +- +-# We disallow local import for non-local packages, if $GOROOT happens +-# to be under $GOPATH, then some tests below will fail. $GOPATH needs +-# to be set to a non-empty string, else Go will set a default value +-# that may also conflict with $GOROOT. The $GOPATH value doesn't need +-# to point to an actual directory, it just needs to pass the semantic +-# checks performed by Go. Use $GOROOT to define $GOPATH so that we +-# don't blunder into a user-defined symbolic link. +-export GOPATH=/dev/null ++export GOPATH=/nonexist-gopath + + unset CDPATH # in case user has it set + export GOBIN=$GOROOT/bin # Issue 14340 +diff --git a/src/run.bat b/src/run.bat +index c299671c13..edcaf52659 100644 +--- a/src/run.bat ++++ b/src/run.bat +@@ -18,9 +18,7 @@ setlocal + + set GOBUILDFAIL=0 + +-:: we disallow local import for non-local packages, if %GOROOT% happens +-:: to be under %GOPATH%, then some tests below will fail +-set GOPATH= ++set GOPATH=c:\nonexist-gopath + :: Issue 14340: ignore GOBIN during all.bat. + set GOBIN= + set GOFLAGS= +diff --git a/src/run.rc b/src/run.rc +index ab7abfa991..a7b4801207 100755 +--- a/src/run.rc ++++ b/src/run.rc +@@ -12,10 +12,9 @@ if(! test -f ../bin/go){ + + eval `{../bin/go env} + +-GOPATH = () # we disallow local import for non-local packages, if $GOROOT happens +- # to be under $GOPATH, then some tests below will fail +-GOBIN = () # Issue 14340 +-GOFLAGS = () +-GO111MODULE = () ++GOPATH=/nonexist-gopath ++GOBIN=() # Issue 14340 ++GOFLAGS=() ++GO111MODULE=() + + exec ../bin/go tool dist test -rebuild $* +-- +2.27.0 + diff --git a/0030-release-branch.go1.15-database-sql-fix-tx-stmt-deadl.patch b/0030-release-branch.go1.15-database-sql-fix-tx-stmt-deadl.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d1c4ea520131417e0afae93f0555b402414ef8b --- /dev/null +++ b/0030-release-branch.go1.15-database-sql-fix-tx-stmt-deadl.patch @@ -0,0 +1,134 @@ +From c77418f4cac41c42566ca90921a1f928995cfba2 Mon Sep 17 00:00:00 2001 +From: Emmanuel T Odeke +Date: Mon, 18 Jan 2021 16:18:11 -0800 +Subject: [PATCH 30/44] [release-branch.go1.15] database/sql: fix tx stmt + deadlock when rollback + +Tx acquires tx.closemu W-lock and then acquires stmt.closemu.W-lock +to fully close the transaction and associated prepared statement. +Stmt query and execution run in reverse ways - acquires +stmt.closemu.R-lock and then acquires tx.closemu.R-lock to grab tx +connection, which may cause deadlock. + +Prevent the lock is held around tx.closePrepared to ensure no +deadlock happens. + +Includes a test fix from CL 266097. +Fixes #42884 +Updates #40985 +Updates #42259 + +Change-Id: Id52737660ada3cebdfff6efc23366cdc3224b8e8 +Reviewed-on: https://go-review.googlesource.com/c/go/+/250178 +Run-TryBot: Emmanuel Odeke +TryBot-Result: Go Bot +Reviewed-by: Daniel Theophanes +Trust: Emmanuel Odeke +(cherry picked from commit d4c1ad882973e407ff85b977f4ce5b9435451190) +Reviewed-on: https://go-review.googlesource.com/c/go/+/284513 +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/c77418f4cac41c42566ca90921a1f928995cfba2 + +--- + src/database/sql/sql.go | 14 +++++++------- + src/database/sql/sql_test.go | 28 ++++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 7 deletions(-) + +diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go +index b3d0653f5c..3d1367d28f 100644 +--- a/src/database/sql/sql.go ++++ b/src/database/sql/sql.go +@@ -2080,10 +2080,10 @@ func (tx *Tx) isDone() bool { + // that has already been committed or rolled back. + var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back") + +-// closeLocked returns the connection to the pool and ++// close returns the connection to the pool and + // must only be called by Tx.rollback or Tx.Commit while +-// closemu is Locked and tx already canceled. +-func (tx *Tx) closeLocked(err error) { ++// tx is already canceled and won't be executed concurrently. ++func (tx *Tx) close(err error) { + tx.releaseConn(err) + tx.dc = nil + tx.txi = nil +@@ -2157,7 +2157,7 @@ func (tx *Tx) Commit() error { + // to ensure no other connection has an active query. + tx.cancel() + tx.closemu.Lock() +- defer tx.closemu.Unlock() ++ tx.closemu.Unlock() + + var err error + withLock(tx.dc, func() { +@@ -2166,7 +2166,7 @@ func (tx *Tx) Commit() error { + if err != driver.ErrBadConn { + tx.closePrepared() + } +- tx.closeLocked(err) ++ tx.close(err) + return err + } + +@@ -2189,7 +2189,7 @@ func (tx *Tx) rollback(discardConn bool) error { + // to ensure no other connection has an active query. + tx.cancel() + tx.closemu.Lock() +- defer tx.closemu.Unlock() ++ tx.closemu.Unlock() + + var err error + withLock(tx.dc, func() { +@@ -2201,7 +2201,7 @@ func (tx *Tx) rollback(discardConn bool) error { + if discardConn { + err = driver.ErrBadConn + } +- tx.closeLocked(err) ++ tx.close(err) + return err + } + +diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go +index 5727f0d8aa..d7d4642608 100644 +--- a/src/database/sql/sql_test.go ++++ b/src/database/sql/sql_test.go +@@ -2810,6 +2810,34 @@ func TestTxCannotCommitAfterRollback(t *testing.T) { + } + } + ++// Issue 40985 transaction statement deadlock while context cancel. ++func TestTxStmtDeadlock(t *testing.T) { ++ db := newTestDB(t, "people") ++ defer closeDB(t, db) ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) ++ defer cancel() ++ tx, err := db.BeginTx(ctx, nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ stmt, err := tx.Prepare("SELECT|people|name,age|age=?") ++ if err != nil { ++ t.Fatal(err) ++ } ++ // Run number of stmt queries to reproduce deadlock from context cancel ++ for i := 0; i < 1e3; i++ { ++ // Encounter any close related errors (e.g.. ErrTxDone, stmt is closed) ++ // is expected due to context cancel. ++ _, err = stmt.Query(1) ++ if err != nil { ++ break ++ } ++ } ++ _ = tx.Rollback() ++} ++ + // Issue32530 encounters an issue where a connection may + // expire right after it comes out of a used connection pool + // even when a new connection is requested. +-- +2.27.0 + diff --git a/0031-release-branch.go1.15-cmd-compile-disable-shortcircu.patch b/0031-release-branch.go1.15-cmd-compile-disable-shortcircu.patch new file mode 100644 index 0000000000000000000000000000000000000000..fda0c965c47f0ec413492e77fe6c0d5844a44535 --- /dev/null +++ b/0031-release-branch.go1.15-cmd-compile-disable-shortcircu.patch @@ -0,0 +1,107 @@ +From f17b659d0a9a43235f67c155b08023124b3fc35b Mon Sep 17 00:00:00 2001 +From: Keith Randall +Date: Tue, 23 Mar 2021 14:48:47 -0700 +Subject: [PATCH 31/44] [release-branch.go1.15] cmd/compile: disable + shortcircuit optimization for intertwined phi values + +We need to be careful that when doing value graph surgery, we not +re-substitute a value that has already been substituted. That can lead +to confusing a previous iteration's value with the current iteration's +value. + +The simple fix in this CL just aborts the optimization if it detects +intertwined phis (a phi which is the argument to another phi). It +might be possible to keep the optimization with a more complicated +CL, but: + 1) This CL is clearly safe to backport. + 2) There were no instances of this abort triggering in + all.bash, prior to the test introduced in this CL. + +Fixes #45187 + +Change-Id: I2411dca03948653c053291f6829a76bec0c32330 +Reviewed-on: https://go-review.googlesource.com/c/go/+/304251 +Trust: Keith Randall +Trust: Josh Bleecher Snyder +Run-TryBot: Keith Randall +TryBot-Result: Go Bot +Reviewed-by: Josh Bleecher Snyder +(cherry picked from commit 771c57e68ed5ef2bbb0eafc0d48419f59d143932) +Reviewed-on: https://go-review.googlesource.com/c/go/+/304529 + +Conflict:NA +Reference:https://github.com/golang/go/commit/f17b659d0a9a43235f67c155b08023124b3fc35b + +--- + src/cmd/compile/internal/ssa/shortcircuit.go | 18 ++++++++++++ + test/fixedbugs/issue45175.go | 29 ++++++++++++++++++++ + 2 files changed, 47 insertions(+) + create mode 100644 test/fixedbugs/issue45175.go + +diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go +index c5df457c4e..9cf29fe413 100644 +--- a/src/cmd/compile/internal/ssa/shortcircuit.go ++++ b/src/cmd/compile/internal/ssa/shortcircuit.go +@@ -138,6 +138,24 @@ func shortcircuitBlock(b *Block) bool { + if len(b.Values) != nval+nOtherPhi { + return false + } ++ if nOtherPhi > 0 { ++ // Check for any phi which is the argument of another phi. ++ // These cases are tricky, as substitutions done by replaceUses ++ // are no longer trivial to do in any ordering. See issue 45175. ++ m := make(map[*Value]bool, 1+nOtherPhi) ++ for _, v := range b.Values { ++ if v.Op == OpPhi { ++ m[v] = true ++ } ++ } ++ for v := range m { ++ for _, a := range v.Args { ++ if a != v && m[a] { ++ return false ++ } ++ } ++ } ++ } + + // Locate index of first const phi arg. + cidx := -1 +diff --git a/test/fixedbugs/issue45175.go b/test/fixedbugs/issue45175.go +new file mode 100644 +index 0000000000..02dfe8a0a9 +--- /dev/null ++++ b/test/fixedbugs/issue45175.go +@@ -0,0 +1,29 @@ ++// run ++ ++// Copyright 2021 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 main ++ ++//go:noinline ++func f(c bool) int { ++ b := true ++ x := 0 ++ y := 1 ++ for b { ++ b = false ++ y = x ++ x = 2 ++ if c { ++ return 3 ++ } ++ } ++ return y ++} ++ ++func main() { ++ if got := f(false); got != 0 { ++ panic(got) ++ } ++} +-- +2.27.0 + diff --git a/0032-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch b/0032-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch new file mode 100644 index 0000000000000000000000000000000000000000..58ee86968d78f89cde41cd25d32a8f0c209f278a --- /dev/null +++ b/0032-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch @@ -0,0 +1,157 @@ +From a07f9d2f82598d2f5cc0df0e813a6a2309cb96e6 Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Thu, 11 Mar 2021 12:28:45 -0500 +Subject: [PATCH 32/44] [release-branch.go1.15] runtime: non-strict + InlTreeIndex lookup in Frames.Next + +When using cgo, some of the frames can be provided by cgoTraceback, a +cgo-provided function to generate C tracebacks. Unlike Go tracebacks, +cgoTraceback has no particular guarantees that it produces valid +tracebacks. + +If one of the (invalid) frames happens to put the PC in the alignment +region at the end of a function (filled with int 3's on amd64), then +Frames.Next will find a valid funcInfo for the PC, but pcdatavalue will +panic because PCDATA doesn't cover this PC. + +Tolerate this case by doing a non-strict PCDATA lookup. We'll still show +a bogus frame, but at least avoid throwing. + +For #44971 +Fixes #45302 + +Change-Id: I9eed728470d6f264179a7615bd19845c941db78c +Reviewed-on: https://go-review.googlesource.com/c/go/+/301369 +Trust: Michael Pratt +Run-TryBot: Michael Pratt +TryBot-Result: Go Bot +Reviewed-by: Cherry Zhang +(cherry picked from commit e4a4161f1f3157550846e1b6bd4fe83aae15778e) +Reviewed-on: https://go-review.googlesource.com/c/go/+/305890 + +Conflict:NA +Reference:https://github.com/golang/go/commit/a07f9d2f82598d2f5cc0df0e813a6a2309cb96e6 + +--- + src/runtime/symtab.go | 4 +- + src/runtime/symtab_test.go | 85 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+), 1 deletion(-) + +diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go +index 1e86662adc..c77d513e74 100644 +--- a/src/runtime/symtab.go ++++ b/src/runtime/symtab.go +@@ -102,7 +102,9 @@ func (ci *Frames) Next() (frame Frame, more bool) { + name := funcname(funcInfo) + if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil { + inltree := (*[1 << 20]inlinedCall)(inldata) +- ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil) ++ // Non-strict as cgoTraceback may have added bogus PCs ++ // with a valid funcInfo but invalid PCDATA. ++ ix := pcdatavalue1(funcInfo, _PCDATA_InlTreeIndex, pc, nil, false) + if ix >= 0 { + // Note: entry is not modified. It always refers to a real frame, not an inlined one. + f = nil +diff --git a/src/runtime/symtab_test.go b/src/runtime/symtab_test.go +index 01e5002659..ffa07c7f3a 100644 +--- a/src/runtime/symtab_test.go ++++ b/src/runtime/symtab_test.go +@@ -8,6 +8,7 @@ import ( + "runtime" + "strings" + "testing" ++ "unsafe" + ) + + func TestCaller(t *testing.T) { +@@ -165,3 +166,87 @@ func TestNilName(t *testing.T) { + t.Errorf("Name() = %q, want %q", got, "") + } + } ++ ++var dummy int ++ ++func inlined() { ++ // Side effect to prevent elimination of this entire function. ++ dummy = 42 ++} ++ ++// A function with an InlTree. Returns a PC within the function body. ++// ++// No inline to ensure this complete function appears in output. ++// ++//go:noinline ++func tracebackFunc(t *testing.T) uintptr { ++ // This body must be more complex than a single call to inlined to get ++ // an inline tree. ++ inlined() ++ inlined() ++ ++ // Acquire a PC in this function. ++ pc, _, _, ok := runtime.Caller(0) ++ if !ok { ++ t.Fatalf("Caller(0) got ok false, want true") ++ } ++ ++ return pc ++} ++ ++// Test that CallersFrames handles PCs in the alignment region between ++// functions (int 3 on amd64) without crashing. ++// ++// Go will never generate a stack trace containing such an address, as it is ++// not a valid call site. However, the cgo traceback function passed to ++// runtime.SetCgoTraceback may not be completely accurate and may incorrect ++// provide PCs in Go code or the alignement region between functions. ++// ++// Go obviously doesn't easily expose the problematic PCs to running programs, ++// so this test is a bit fragile. Some details: ++// ++// * tracebackFunc is our target function. We want to get a PC in the ++// alignment region following this function. This function also has other ++// functions inlined into it to ensure it has an InlTree (this was the source ++// of the bug in issue 44971). ++// ++// * We acquire a PC in tracebackFunc, walking forwards until FuncForPC says ++// we're in a new function. The last PC of the function according to FuncForPC ++// should be in the alignment region (assuming the function isn't already ++// perfectly aligned). ++// ++// This is a regression test for issue 44971. ++func TestFunctionAlignmentTraceback(t *testing.T) { ++ pc := tracebackFunc(t) ++ ++ // Double-check we got the right PC. ++ f := runtime.FuncForPC(pc) ++ if !strings.HasSuffix(f.Name(), "tracebackFunc") { ++ t.Fatalf("Caller(0) = %+v, want tracebackFunc", f) ++ } ++ ++ // Iterate forward until we find a different function. Back up one ++ // instruction is (hopefully) an alignment instruction. ++ for runtime.FuncForPC(pc) == f { ++ pc++ ++ } ++ pc-- ++ ++ // Is this an alignment region filler instruction? We only check this ++ // on amd64 for simplicity. If this function has no filler, then we may ++ // get a false negative, but will never get a false positive. ++ if runtime.GOARCH == "amd64" { ++ code := *(*uint8)(unsafe.Pointer(pc)) ++ if code != 0xcc { // INT $3 ++ t.Errorf("PC %v code got %#x want 0xcc", pc, code) ++ } ++ } ++ ++ // Finally ensure that Frames.Next doesn't crash when processing this ++ // PC. ++ frames := runtime.CallersFrames([]uintptr{pc}) ++ frame, _ := frames.Next() ++ if frame.Func != f { ++ t.Errorf("frames.Next() got %+v want %+v", frame.Func, f) ++ } ++} +-- +2.27.0 + diff --git a/0033-release-branch.go1.15-cmd-cgo-avoid-exporting-all-sy.patch b/0033-release-branch.go1.15-cmd-cgo-avoid-exporting-all-sy.patch new file mode 100644 index 0000000000000000000000000000000000000000..39bc904fedfa8ff11eefd382c235f5f4e87ba7fe --- /dev/null +++ b/0033-release-branch.go1.15-cmd-cgo-avoid-exporting-all-sy.patch @@ -0,0 +1,172 @@ +From 5055314a5749664ab66a24beed8158552e276959 Mon Sep 17 00:00:00 2001 +From: Quim Muntal +Date: Thu, 15 Oct 2020 23:12:49 +0200 +Subject: [PATCH 33/44] [release-branch.go1.15] cmd/cgo: avoid exporting all + symbols on windows buildmode=c-shared + +Disable default symbol auto-export behaviour by marking exported +function with the __declspec(dllexport) attribute. Old behaviour can +still be used by setting -extldflags=-Wl,--export-all-symbols. + +See https://sourceware.org/binutils/docs/ld/WIN32.html for more info. + +This change cuts 50kb of a "hello world" dll. + +Updates #6853. +Updates #30674. +Fixes #43591. + +Change-Id: I9c7fb09c677cc760f24d0f7d199740ae73981413 +Reviewed-on: https://go-review.googlesource.com/c/go/+/262797 +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-by: Ian Lance Taylor +Reviewed-by: Alex Brainman +Trust: Alex Brainman +Reviewed-on: https://go-review.googlesource.com/c/go/+/300693 +Trust: Dmitri Shuralyov +Run-TryBot: Dmitri Shuralyov +Reviewed-by: David Chase + +Conflict:NA +Reference:https://github.com/golang/go/commit/5055314a5749664ab66a24beed8158552e276959 + +--- + misc/cgo/testcshared/cshared_test.go | 96 ++++++++++++++++++++++++++++ + src/cmd/cgo/out.go | 6 +- + 2 files changed, 101 insertions(+), 1 deletion(-) + +diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go +index bd4d341820..d717b4dfb3 100644 +--- a/misc/cgo/testcshared/cshared_test.go ++++ b/misc/cgo/testcshared/cshared_test.go +@@ -7,6 +7,8 @@ package cshared_test + import ( + "bytes" + "debug/elf" ++ "debug/pe" ++ "encoding/binary" + "flag" + "fmt" + "io/ioutil" +@@ -355,6 +357,100 @@ func TestExportedSymbols(t *testing.T) { + } + } + ++func checkNumberOfExportedFunctionsWindows(t *testing.T, exportAllSymbols bool) { ++ const prog = ` ++package main ++ ++import "C" ++ ++//export GoFunc ++func GoFunc() { ++ println(42) ++} ++ ++//export GoFunc2 ++func GoFunc2() { ++ println(24) ++} ++ ++func main() { ++} ++` ++ ++ tmpdir := t.TempDir() ++ ++ srcfile := filepath.Join(tmpdir, "test.go") ++ objfile := filepath.Join(tmpdir, "test.dll") ++ if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil { ++ t.Fatal(err) ++ } ++ argv := []string{"build", "-buildmode=c-shared"} ++ if exportAllSymbols { ++ argv = append(argv, "-ldflags", "-extldflags=-Wl,--export-all-symbols") ++ } ++ argv = append(argv, "-o", objfile, srcfile) ++ out, err := exec.Command("go", argv...).CombinedOutput() ++ if err != nil { ++ t.Fatalf("build failure: %s\n%s\n", err, string(out)) ++ } ++ ++ f, err := pe.Open(objfile) ++ if err != nil { ++ t.Fatalf("pe.Open failed: %v", err) ++ } ++ defer f.Close() ++ section := f.Section(".edata") ++ if section == nil { ++ t.Error(".edata section is not present") ++ } ++ ++ // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go ++ type IMAGE_EXPORT_DIRECTORY struct { ++ _ [2]uint32 ++ _ [2]uint16 ++ _ [2]uint32 ++ NumberOfFunctions uint32 ++ NumberOfNames uint32 ++ _ [3]uint32 ++ } ++ var e IMAGE_EXPORT_DIRECTORY ++ if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil { ++ t.Fatalf("binary.Read failed: %v", err) ++ } ++ ++ expectedNumber := uint32(2) ++ ++ if exportAllSymbols { ++ if e.NumberOfFunctions <= expectedNumber { ++ t.Fatalf("missing exported functions: %v", e.NumberOfFunctions) ++ } ++ if e.NumberOfNames <= expectedNumber { ++ t.Fatalf("missing exported names: %v", e.NumberOfNames) ++ } ++ } else { ++ if e.NumberOfFunctions != expectedNumber { ++ t.Fatalf("too many exported functions: %v", e.NumberOfFunctions) ++ } ++ if e.NumberOfNames != expectedNumber { ++ t.Fatalf("too many exported names: %v", e.NumberOfNames) ++ } ++ } ++} ++ ++func TestNumberOfExportedFunctions(t *testing.T) { ++ if GOOS != "windows" { ++ t.Skip("skipping windows only test") ++ } ++ t.Parallel() ++ ++ t.Run("OnlyExported", func(t *testing.T) { ++ checkNumberOfExportedFunctionsWindows(t, false) ++ }) ++ t.Run("All", func(t *testing.T) { ++ checkNumberOfExportedFunctionsWindows(t, true) ++ }) ++} ++ + // test1: shared library can be dynamically loaded and exported symbols are accessible. + func TestExportedSymbolsWithDynamicLoad(t *testing.T) { + t.Parallel() +diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go +index b9043efbf7..ee1c563495 100644 +--- a/src/cmd/cgo/out.go ++++ b/src/cmd/cgo/out.go +@@ -961,7 +961,11 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { + } + + // Build the wrapper function compiled by gcc. +- s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) ++ gccExport := "" ++ if goos == "windows" { ++ gccExport = "__declspec(dllexport)" ++ } ++ s := fmt.Sprintf("%s %s %s(", gccExport, gccResult, exp.ExpName) + if fn.Recv != nil { + s += p.cgoType(fn.Recv.List[0].Type).C.String() + s += " recv" +-- +2.27.0 + diff --git a/0034-release-branch.go1.15-cmd-link-avoid-exporting-all-s.patch b/0034-release-branch.go1.15-cmd-link-avoid-exporting-all-s.patch new file mode 100644 index 0000000000000000000000000000000000000000..123220ef79d8250938a12add5530ab6dbca9bb8f --- /dev/null +++ b/0034-release-branch.go1.15-cmd-link-avoid-exporting-all-s.patch @@ -0,0 +1,188 @@ +From 82f9c6cac1bcc6bc80f17d1415ac3f62c0afa6c5 Mon Sep 17 00:00:00 2001 +From: Quim Muntal +Date: Thu, 22 Oct 2020 22:32:20 +0200 +Subject: [PATCH 34/44] [release-branch.go1.15] cmd/link: avoid exporting all + symbols on windows buildmode=pie + +Marking one functions with __declspec(dllexport) forces mingw to +create .reloc section without having to export all symbols. + +See https://insights.sei.cmu.edu/cert/2018/08/when-aslr-is-not-really-aslr---the-case-of-incorrect-assumptions-and-bad-defaults.html for more info. + +This change cuts 73kb of a "hello world" pie binary. + +Updates #6853. +Updates #40795. +Fixes #43592. + +Change-Id: I3cc57c3b64f61187550bc8751dfa085f106c8475 +Reviewed-on: https://go-review.googlesource.com/c/go/+/264459 +Trust: Alex Brainman +Run-TryBot: Alex Brainman +TryBot-Result: Go Bot +Reviewed-by: Alex Brainman +Reviewed-by: Austin Clements +Reviewed-on: https://go-review.googlesource.com/c/go/+/300692 +Trust: Dmitri Shuralyov +Run-TryBot: Dmitri Shuralyov +Reviewed-by: David Chase + +Conflict:NA +Reference:https://github.com/golang/go/commit/82f9c6cac1bcc6bc80f17d1415ac3f62c0afa6c5 + +--- + misc/cgo/testcshared/cshared_test.go | 9 ++++---- + src/cmd/go/go_test.go | 33 ++++++++++++++++++++++++++++ + src/cmd/link/internal/ld/lib.go | 3 --- + src/runtime/cgo/gcc_windows_386.c | 1 + + src/runtime/cgo/gcc_windows_amd64.c | 1 + + src/runtime/cgo/libcgo_windows.h | 12 ++++++++++ + 6 files changed, 52 insertions(+), 7 deletions(-) + create mode 100644 src/runtime/cgo/libcgo_windows.h + +diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go +index d717b4dfb3..dff2682e20 100644 +--- a/misc/cgo/testcshared/cshared_test.go ++++ b/misc/cgo/testcshared/cshared_test.go +@@ -401,7 +401,7 @@ func main() { + defer f.Close() + section := f.Section(".edata") + if section == nil { +- t.Error(".edata section is not present") ++ t.Fatalf(".edata section is not present") + } + + // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go +@@ -418,7 +418,8 @@ func main() { + t.Fatalf("binary.Read failed: %v", err) + } + +- expectedNumber := uint32(2) ++ // Only the two exported functions and _cgo_dummy_export should be exported ++ expectedNumber := uint32(3) + + if exportAllSymbols { + if e.NumberOfFunctions <= expectedNumber { +@@ -429,10 +430,10 @@ func main() { + } + } else { + if e.NumberOfFunctions != expectedNumber { +- t.Fatalf("too many exported functions: %v", e.NumberOfFunctions) ++ t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber) + } + if e.NumberOfNames != expectedNumber { +- t.Fatalf("too many exported names: %v", e.NumberOfNames) ++ t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber) + } + } + } +diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go +index 021930a8a8..3f790cdeab 100644 +--- a/src/cmd/go/go_test.go ++++ b/src/cmd/go/go_test.go +@@ -9,6 +9,7 @@ import ( + "debug/elf" + "debug/macho" + "debug/pe" ++ "encoding/binary" + "flag" + "fmt" + "go/format" +@@ -2166,6 +2167,38 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) { + if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 { + t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set") + } ++ if useCgo { ++ // Test that only one symbol is exported (#40795). ++ // PIE binaries don´t require .edata section but unfortunately ++ // binutils doesn´t generate a .reloc section unless there is ++ // at least one symbol exported. ++ // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 ++ section := f.Section(".edata") ++ if section == nil { ++ t.Fatalf(".edata section is not present") ++ } ++ // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go ++ type IMAGE_EXPORT_DIRECTORY struct { ++ _ [2]uint32 ++ _ [2]uint16 ++ _ [2]uint32 ++ NumberOfFunctions uint32 ++ NumberOfNames uint32 ++ _ [3]uint32 ++ } ++ var e IMAGE_EXPORT_DIRECTORY ++ if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil { ++ t.Fatalf("binary.Read failed: %v", err) ++ } ++ ++ // Only _cgo_dummy_export should be exported ++ if e.NumberOfFunctions != 1 { ++ t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions) ++ } ++ if e.NumberOfNames != 1 { ++ t.Fatalf("got %d exported names; want 1", e.NumberOfNames) ++ } ++ } + default: + panic("unreachable") + } +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index fc89759997..d03fb6cf91 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1423,9 +1423,6 @@ func (ctxt *Link) hostlink() { + if ctxt.Arch.PtrSize >= 8 { + argv = append(argv, "-Wl,--high-entropy-va") + } +- // Work around binutils limitation that strips relocation table for dynamicbase. +- // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 +- argv = append(argv, "-Wl,--export-all-symbols") + default: + // ELF. + if ctxt.UseRelro() { +diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c +index 9184b91393..60cb011bf2 100644 +--- a/src/runtime/cgo/gcc_windows_386.c ++++ b/src/runtime/cgo/gcc_windows_386.c +@@ -9,6 +9,7 @@ + #include + #include + #include "libcgo.h" ++#include "libcgo_windows.h" + + static void threadentry(void*); + +diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c +index 7192a24631..0f8c817f0e 100644 +--- a/src/runtime/cgo/gcc_windows_amd64.c ++++ b/src/runtime/cgo/gcc_windows_amd64.c +@@ -9,6 +9,7 @@ + #include + #include + #include "libcgo.h" ++#include "libcgo_windows.h" + + static void threadentry(void*); + +diff --git a/src/runtime/cgo/libcgo_windows.h b/src/runtime/cgo/libcgo_windows.h +new file mode 100644 +index 0000000000..0013f06bae +--- /dev/null ++++ b/src/runtime/cgo/libcgo_windows.h +@@ -0,0 +1,12 @@ ++// Copyright 2020 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. ++ ++// Ensure there's one symbol marked __declspec(dllexport). ++// If there are no exported symbols, the unfortunate behavior of ++// the binutils linker is to also strip the relocations table, ++// resulting in non-PIE binary. The other option is the ++// --export-all-symbols flag, but we don't need to export all symbols ++// and this may overflow the export table (#40795). ++// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 ++__declspec(dllexport) int _cgo_dummy_export; +-- +2.27.0 + diff --git a/0035-release-branch.go1.15-cmd-cgo-remove-unnecessary-spa.patch b/0035-release-branch.go1.15-cmd-cgo-remove-unnecessary-spa.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d3c8a51804ccd59f7c72a3b7bb4d15661698992 --- /dev/null +++ b/0035-release-branch.go1.15-cmd-cgo-remove-unnecessary-spa.patch @@ -0,0 +1,60 @@ +From 1373d92a75f70c62d74f9e4714cd17811f75c48b Mon Sep 17 00:00:00 2001 +From: Quim Muntal +Date: Thu, 14 Jan 2021 21:29:49 +0100 +Subject: [PATCH 35/44] [release-branch.go1.15] cmd/cgo: remove unnecessary + space in cgo export header + +The cgo header has an unnecessary space in the exported function +definition on non-windows goos. + +This was introduced in go1.16 so it would be good to fix it before +release. + +Example: + +// Current behavior, notice there is an unecessary space +// between extern and void +extern void Foo(); + +// With this CL +extern void Foo(); + +Updates #43591. + +Change-Id: Ic2c21f8d806fe35a7be7183dbfe35ac605b6e4f6 +Reviewed-on: https://go-review.googlesource.com/c/go/+/283892 +Reviewed-by: Ian Lance Taylor +Trust: Katie Hockman +Reviewed-on: https://go-review.googlesource.com/c/go/+/300694 +Trust: Dmitri Shuralyov +Trust: Emmanuel Odeke +Run-TryBot: Dmitri Shuralyov +TryBot-Result: Go Bot +Reviewed-by: David Chase + +Conflict:NA +Reference:https://github.com/golang/go/commit/1373d92a75f70c62d74f9e4714cd17811f75c48b + +--- + src/cmd/cgo/out.go | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go +index ee1c563495..be4f6ad2d5 100644 +--- a/src/cmd/cgo/out.go ++++ b/src/cmd/cgo/out.go +@@ -963,9 +963,9 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { + // Build the wrapper function compiled by gcc. + gccExport := "" + if goos == "windows" { +- gccExport = "__declspec(dllexport)" ++ gccExport = "__declspec(dllexport) " + } +- s := fmt.Sprintf("%s %s %s(", gccExport, gccResult, exp.ExpName) ++ s := fmt.Sprintf("%s%s %s(", gccExport, gccResult, exp.ExpName) + if fn.Recv != nil { + s += p.cgoType(fn.Recv.List[0].Type).C.String() + s += " recv" +-- +2.27.0 + diff --git a/0037-release-branch.go1.15-time-use-offset-and-isDST-when.patch b/0037-release-branch.go1.15-time-use-offset-and-isDST-when.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc7e32cccddee2a74d6ca4fdbfc57d5bc03e6642 --- /dev/null +++ b/0037-release-branch.go1.15-time-use-offset-and-isDST-when.patch @@ -0,0 +1,355 @@ +From 06c9756333bb506dcbf322be77af85b3162b6345 Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor +Date: Mon, 5 Apr 2021 12:12:25 -0700 +Subject: [PATCH 37/44] [release-branch.go1.15] time: use offset and isDST when + caching zone from extend string + +If the current time is computed from extend string +and the zone file contains multiple zones with the +same name, the lookup by name might find incorrect +zone. + +This happens for example with the slim Europe/Dublin +time zone file in the embedded zip. This zone file +has last transition in 1996 and rest is covered by +extend string. +tzset returns IST as the zone name to use, but there +are two records with IST name. Lookup by name finds +the wrong one. We need to check offset and isDST too. + +In case we can't find an existing zone, we allocate +a new zone so that we use correct offset and isDST. + +I have renamed zone variable to zones as it shadowed +the zone type that we need to allocate the cached zone. + +Backport note: this change also incorporates portions of +CL 264077. + +For #45370 +Fixes #45384 + +Change-Id: I43d416d009e20878261156c821a5784e2407ed1f +Reviewed-on: https://go-review.googlesource.com/c/go/+/307212 +Trust: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-by: Emmanuel Odeke + +Conflict:NA +Reference:https://github.com/golang/go/commit/06c9756333bb506dcbf322be77af85b3162b6345 + +--- + src/time/zoneinfo.go | 27 ++++++++++++++---------- + src/time/zoneinfo_read.go | 44 ++++++++++++++++++++++++--------------- + src/time/zoneinfo_test.go | 37 +++++++++++++++++++++----------- + 3 files changed, 68 insertions(+), 40 deletions(-) + +diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go +index 6db9443474..57052338d0 100644 +--- a/src/time/zoneinfo.go ++++ b/src/time/zoneinfo.go +@@ -178,7 +178,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) + // If we're at the end of the known zone transitions, + // try the extend string. + if lo == len(tx)-1 && l.extend != "" { +- if ename, eoffset, estart, eend, ok := tzset(l.extend, end, sec); ok { ++ if ename, eoffset, estart, eend, _, ok := tzset(l.extend, end, sec); ok { + return ename, eoffset, estart, eend + } + } +@@ -244,7 +244,7 @@ func (l *Location) firstZoneUsed() bool { + // We call this a tzset string since in C the function tzset reads TZ. + // The return values are as for lookup, plus ok which reports whether the + // parse succeeded. +-func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, ok bool) { ++func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, isDST, ok bool) { + var ( + stdName, dstName string + stdOffset, dstOffset int +@@ -255,7 +255,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + stdOffset, s, ok = tzsetOffset(s) + } + if !ok { +- return "", 0, 0, 0, false ++ return "", 0, 0, 0, false, false + } + + // The numbers in the tzset string are added to local time to get UTC, +@@ -265,7 +265,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + + if len(s) == 0 || s[0] == ',' { + // No daylight savings time. +- return stdName, stdOffset, initEnd, omega, true ++ return stdName, stdOffset, initEnd, omega, false, true + } + + dstName, s, ok = tzsetName(s) +@@ -278,7 +278,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + } + } + if !ok { +- return "", 0, 0, 0, false ++ return "", 0, 0, 0, false, false + } + + if len(s) == 0 { +@@ -287,19 +287,19 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + } + // The TZ definition does not mention ';' here but tzcode accepts it. + if s[0] != ',' && s[0] != ';' { +- return "", 0, 0, 0, false ++ return "", 0, 0, 0, false, false + } + s = s[1:] + + var startRule, endRule rule + startRule, s, ok = tzsetRule(s) + if !ok || len(s) == 0 || s[0] != ',' { +- return "", 0, 0, 0, false ++ return "", 0, 0, 0, false, false + } + s = s[1:] + endRule, s, ok = tzsetRule(s) + if !ok || len(s) > 0 { +- return "", 0, 0, 0, false ++ return "", 0, 0, 0, false, false + } + + year, _, _, yday := absDate(uint64(sec+unixToInternal+internalToAbsolute), false) +@@ -313,10 +313,15 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + + startSec := int64(tzruleTime(year, startRule, stdOffset)) + endSec := int64(tzruleTime(year, endRule, dstOffset)) ++ dstIsDST, stdIsDST := true, false ++ // Note: this is a flipping of "DST" and "STD" while retaining the labels ++ // This happens in southern hemispheres. The labelling here thus is a little ++ // inconsistent with the goal. + if endSec < startSec { + startSec, endSec = endSec, startSec + stdName, dstName = dstName, stdName + stdOffset, dstOffset = dstOffset, stdOffset ++ stdIsDST, dstIsDST = dstIsDST, stdIsDST + } + + // The start and end values that we return are accurate +@@ -324,11 +329,11 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in + // just the start and end of the year. That suffices for + // the only caller that cares, which is Date. + if ysec < startSec { +- return stdName, stdOffset, abs, startSec + abs, true ++ return stdName, stdOffset, abs, startSec + abs, stdIsDST, true + } else if ysec >= endSec { +- return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, true ++ return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, stdIsDST, true + } else { +- return dstName, dstOffset, startSec + abs, endSec + abs, true ++ return dstName, dstOffset, startSec + abs, endSec + abs, dstIsDST, true + } + } + +diff --git a/src/time/zoneinfo_read.go b/src/time/zoneinfo_read.go +index 22a60f3211..f7fe59c385 100644 +--- a/src/time/zoneinfo_read.go ++++ b/src/time/zoneinfo_read.go +@@ -247,8 +247,8 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + // This also avoids a panic later when we add and then use a fake transition (golang.org/issue/29437). + return nil, badData + } +- zone := make([]zone, nzone) +- for i := range zone { ++ zones := make([]zone, nzone) ++ for i := range zones { + var ok bool + var n uint32 + if n, ok = zonedata.big4(); !ok { +@@ -257,22 +257,22 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + if uint32(int(n)) != n { + return nil, badData + } +- zone[i].offset = int(int32(n)) ++ zones[i].offset = int(int32(n)) + var b byte + if b, ok = zonedata.byte(); !ok { + return nil, badData + } +- zone[i].isDST = b != 0 ++ zones[i].isDST = b != 0 + if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) { + return nil, badData + } +- zone[i].name = byteString(abbrev[b:]) ++ zones[i].name = byteString(abbrev[b:]) + if runtime.GOOS == "aix" && len(name) > 8 && (name[:8] == "Etc/GMT+" || name[:8] == "Etc/GMT-") { + // There is a bug with AIX 7.2 TL 0 with files in Etc, + // GMT+1 will return GMT-1 instead of GMT+1 or -01. + if name != "Etc/GMT+0" { + // GMT+0 is OK +- zone[i].name = name[4:] ++ zones[i].name = name[4:] + } + } + } +@@ -295,7 +295,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + } + } + tx[i].when = n +- if int(txzones[i]) >= len(zone) { ++ if int(txzones[i]) >= len(zones) { + return nil, badData + } + tx[i].index = txzones[i] +@@ -314,7 +314,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + } + + // Committed to succeed. +- l := &Location{zone: zone, tx: tx, name: name, extend: extend} ++ l := &Location{zone: zones, tx: tx, name: name, extend: extend} + + // Fill in the cache with information about right now, + // since that will be the most common lookup. +@@ -323,26 +323,27 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) { + l.cacheStart = tx[i].when + l.cacheEnd = omega +- zoneIdx := tx[i].index ++ l.cacheZone = &l.zone[tx[i].index] + if i+1 < len(tx) { + l.cacheEnd = tx[i+1].when + } else if l.extend != "" { + // If we're at the end of the known zone transitions, + // try the extend string. +- if name, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok { ++ if name, offset, estart, eend, isDST, ok := tzset(l.extend, l.cacheEnd, sec); ok { + l.cacheStart = estart + l.cacheEnd = eend +- // Find the zone that is returned by tzset, +- // the last transition is not always the correct zone. +- for i, z := range l.zone { +- if z.name == name { +- zoneIdx = uint8(i) +- break ++ // Find the zone that is returned by tzset to avoid allocation if possible. ++ if zoneIdx := findZone(l.zone, name, offset, isDST); zoneIdx != -1 { ++ l.cacheZone = &l.zone[zoneIdx] ++ } else { ++ l.cacheZone = &zone{ ++ name: name, ++ offset: offset, ++ isDST: isDST, + } + } + } + } +- l.cacheZone = &l.zone[zoneIdx] + break + } + } +@@ -350,6 +351,15 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) { + return l, nil + } + ++func findZone(zones []zone, name string, offset int, isDST bool) int { ++ for i, z := range zones { ++ if z.name == name && z.offset == offset && z.isDST == isDST { ++ return i ++ } ++ } ++ return -1 ++} ++ + // loadTzinfoFromDirOrZip returns the contents of the file with the given name + // in dir. dir can either be an uncompressed zip file, or a directory. + func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) { +diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go +index d043e1e9f1..7ba1229741 100644 +--- a/src/time/zoneinfo_test.go ++++ b/src/time/zoneinfo_test.go +@@ -186,6 +186,7 @@ func TestMalformedTZData(t *testing.T) { + var slimTests = []struct { + zoneName string + tzData string ++ date func(*time.Location) time.Time + wantName string + wantOffset int + }{ +@@ -193,6 +194,7 @@ var slimTests = []struct { + // 2020b slim tzdata for Europe/Berlin. + zoneName: "Europe/Berlin", + tzData: "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3<-02>,M3.5.0/-2,M10.5.0/-1\n", ++ date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) }, + wantName: "-03", + wantOffset: -10800, + }, +@@ -207,9 +210,18 @@ var slimTests = []struct { + // 2021a slim tzdata for Asia/Gaza. + zoneName: "Asia/Gaza", + tzData: "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\n", ++ date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) }, + wantName: "EET", + wantOffset: 7200, + }, ++ { ++ // 2021a slim tzdata for Europe/Dublin. ++ zoneName: "Europe/Dublin", ++ tzData: "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x08\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6\x0b\x11\xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4\xc3\xa0\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba\x20\xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c\x20\xff\xff\xff\xff\xa3{\xc8\xa0\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb\x20\xff\xff\xff\xff\xa6%`\x20\xff\xff\xff\xff\xa7'\xc6\x20\xff\xff\xff\xff\xa8*,\x20\xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00\xd3\xa0\xff\xff\xff\xff\xaa\xd5\x15\x20\xff\xff\xff\xff\xab\xe9\xf0\x20\xff\xff\xff\xff\xac\xc7l\x20\xff\xff\xff\xff\xad\xc9\xd2\x20\xff\xff\xff\xff\xae\xa7N\x20\xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870\x20\xff\xff\xff\xff\xb1\x92\xd0\xa0\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ\x20\xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xef\xd4\xa0\xff\xff\xff\xff\xba\xe9\x00\x20\xff\xff\xff\xff\xbb\xd8\xf1\x20\xff\xff\xff\xff\xbc\xdbW\x20\xff\xff\xff\xff\xbd\xb8\xd3\x20\xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5\x20\xff\xff\xff\xff\xc0\x9b\x1b\x20\xff\xff\xff\xff\xc1x\x97\x20\xff\xff\xff\xff\xc2z\xfd\x20\xff\xff\xff\xff\xc3Xy\x20\xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[\x20\xff\xff\xff\xff\xc6:\xc1\x20\xff\xff\xff\xff\xc7X\xd6\xa0\xff\xff\xff\xff\xc7\xda\x09\xa0\xff\xff\xff\xff\xd4I\xe0\x20\xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac\x20\xff\xff\xff\xff\xd7,(\x20\xff\xff\xff\xff\xd8.\x8e\x20\xff\xff\xff\xff\xd8\xf9\x95\x20\xff\xff\xff\xff\xda\x0ep\x20\xff\xff\xff\xff\xda\xeb\xec\x20\xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce\x20\xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\xde\xb4\xea\xa0\xff\xff\xff\xff\xdf\xae\x16\x20\xff\xff\xff\xff\xe0\x94\xcc\xa0\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt\x20\xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\x0c\xa0\xff\xff\xff\xff\xe6=\xad\x20\xff\xff\xff\xff\xe7\x1b)\x20\xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\x0b\x20\xff\xff\xff\xff\xe9\xfdq\x20\xff\xff\xff\xff\xea\xda\xed\x20\xff\xff\xff\xff\xeb\xddS\x20\xff\xff\xff\xff\xec\xba\xcf\x20\xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\xee\x9a\xb1\x20\xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f}\x20\xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\x7f_\x20\xff\xff\xff\xff\xf3Jf\x20\xff\xff\xff\xff\xf4_A\x20\xff\xff\xff\xff\xf5!\x0d\xa0\xff\xff\xff\xff\xf6?#\x20\xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05\x20\xff\xff\xff\xff\xf8\xe0\xd1\xa0\xff\xff\xff\xff\xf9\xfe\xe7\x20\xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfd\xc7\xbbp\x00\x00\x00\x00\x03p\xc6\x20\x00\x00\x00\x00\x04)X\x20\x00\x00\x00\x00\x05P\xa8\x20\x00\x00\x00\x00\x06\x09:\x20\x00\x00\x00\x00\x070\x8a\x20\x00\x00\x00\x00\x07\xe9\x1c\x20\x00\x00\x00\x00\x09\x10l\x20\x00\x00\x00\x00\x09\xc8\xfe\x20\x00\x00\x00\x00\n\xf0N\x20\x00\x00\x00\x00\x0b\xb2\x1a\xa0\x00\x00\x00\x00\x0c\xd00\x20\x00\x00\x00\x00\x0d\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12\x20\x00\x00\x00\x00\x0fq\xde\xa0\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168\xc6\x90\x00\x00\x00\x00\x17\x03\xcd\x90\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18\xe3\xaf\x90\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1a\xc3\x91\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00\x20lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\x22LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\x0c\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9\xd3\x90\x00\x00\x00\x00-\x94\xda\x90\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\x08\x1f\x01\x08\x00\x00\x0e\x10\x01\x0c\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\x08\x00\x00\x00\x00\x01\x10\x00\x00\x0e\x10\x00\x08LMT\x00DMT\x00IST\x00BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\n", ++ date: func(loc *time.Location) time.Time { return time.Date(2021, time.April, 2, 11, 12, 13, 0, loc) }, ++ wantName: "IST", ++ wantOffset: 3600, ++ }, + } + + func TestLoadLocationFromTZDataSlim(t *testing.T) { +@@ -219,7 +231,7 @@ func TestLoadLocationFromTZDataSlim(t *testing.T) { + t.Fatal(err) + } + +- d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference) ++ d := test.date(reference) + tzName, tzOffset := d.Zone() + if tzName != test.wantName { + t.Errorf("Zone name == %s, want %s", tzName, test.wantName) +@@ -239,20 +251,21 @@ func TestTzset(t *testing.T) { + off int + start int64 + end int64 ++ isDST bool + ok bool + }{ +- {"", 0, 0, "", 0, 0, 0, false}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2159200800, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173599, "PST", -8 * 60 * 60, 2145916800, 2152173600, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173600, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173601, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733199, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733200, "PST", -8 * 60 * 60, 2172733200, 2177452800, true}, +- {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733201, "PST", -8 * 60 * 60, 2172733200, 2177452800, true}, ++ {"", 0, 0, "", 0, 0, 0, false, false}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2159200800, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173599, "PST", -8 * 60 * 60, 2145916800, 2152173600, false, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173600, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2152173601, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733199, "PDT", -7 * 60 * 60, 2152173600, 2172733200, true, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733200, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true}, ++ {"PST8PDT,M3.2.0,M11.1.0", 0, 2172733201, "PST", -8 * 60 * 60, 2172733200, 2177452800, false, true}, + } { +- name, off, start, end, ok := time.Tzset(test.inStr, test.inEnd, test.inSec) +- if name != test.name || off != test.off || start != test.start || end != test.end || ok != test.ok { +- t.Errorf("tzset(%q, %d, %d) = %q, %d, %d, %d, %t, want %q, %d, %d, %d, %t", test.inStr, test.inEnd, test.inSec, name, off, start, end, ok, test.name, test.off, test.start, test.end, test.ok) ++ name, off, start, end, isDST, ok := time.Tzset(test.inStr, test.inEnd, test.inSec) ++ if name != test.name || off != test.off || start != test.start || end != test.end || isDST != test.isDST || ok != test.ok { ++ t.Errorf("tzset(%q, %d, %d) = %q, %d, %d, %d, %t, %t, want %q, %d, %d, %d, %t, %t", test.inStr, test.inEnd, test.inSec, name, off, start, end, isDST, ok, test.name, test.off, test.start, test.end, test.isDST, test.ok) + } + } + } +-- +2.27.0 + diff --git a/0038-release-branch.go1.15-std-update-golang.org-x-net-to.patch b/0038-release-branch.go1.15-std-update-golang.org-x-net-to.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe2ee89f3a6ca1062d6dd9a165a381084f1de269 --- /dev/null +++ b/0038-release-branch.go1.15-std-update-golang.org-x-net-to.patch @@ -0,0 +1,97 @@ +From 5aed4ce3c854bdbbb6dd5c1ccfa15c23d4b6c989 Mon Sep 17 00:00:00 2001 +From: Katie Hockman +Date: Wed, 28 Apr 2021 14:47:48 -0400 +Subject: [PATCH 38/44] [release-branch.go1.15] std: update golang.org/x/net to + 20210428183841-261fb518b1ed + +Steps: + go get -d golang.org/x/net@release-branch.go1.15 + go mod tidy + go mod vendor + +This http2 bundle does not need to be updated. + +Fixes #45711 + +Change-Id: I085ca592dfc8d5d9c328a7979142e88e7130a813 +Reviewed-on: https://go-review.googlesource.com/c/go/+/314790 +Trust: Katie Hockman +Run-TryBot: Katie Hockman +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/5aed4ce3c854bdbbb6dd5c1ccfa15c23d4b6c989 + +--- + src/go.mod | 2 +- + src/go.sum | 4 ++-- + src/vendor/golang.org/x/net/http/httpguts/httplex.go | 10 ++++++---- + src/vendor/modules.txt | 2 +- + 4 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/src/go.mod b/src/go.mod +index 6b97366bbe..dfcba7a1c8 100644 +--- a/src/go.mod ++++ b/src/go.mod +@@ -4,7 +4,7 @@ go 1.15 + + require ( + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 +- golang.org/x/net v0.0.0-20201008223702-a5fa9d4b7c91 ++ golang.org/x/net v0.0.0-20210428183841-261fb518b1ed + golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect + golang.org/x/text v0.3.3-0.20200430171850-afb9336c4530 // indirect + ) +diff --git a/src/go.sum b/src/go.sum +index fbd3279aad..47e918848c 100644 +--- a/src/go.sum ++++ b/src/go.sum +@@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +-golang.org/x/net v0.0.0-20201008223702-a5fa9d4b7c91 h1:zd7kl5i5PDM0OnFbRWVM6B8mXojzv8LOkHN9LsOrRf4= +-golang.org/x/net v0.0.0-20201008223702-a5fa9d4b7c91/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= ++golang.org/x/net v0.0.0-20210428183841-261fb518b1ed h1:aunM0N/jnRHvQgZo3kYkfaAGet2kIMFOPIbopG5BhYw= ++golang.org/x/net v0.0.0-20210428183841-261fb518b1ed/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= + golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= + golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +diff --git a/src/vendor/golang.org/x/net/http/httpguts/httplex.go b/src/vendor/golang.org/x/net/http/httpguts/httplex.go +index e7de24ee64..c79aa73f28 100644 +--- a/src/vendor/golang.org/x/net/http/httpguts/httplex.go ++++ b/src/vendor/golang.org/x/net/http/httpguts/httplex.go +@@ -137,11 +137,13 @@ func trimOWS(x string) string { + // contains token amongst its comma-separated tokens, ASCII + // case-insensitively. + func headerValueContainsToken(v string, token string) bool { +- v = trimOWS(v) +- if comma := strings.IndexByte(v, ','); comma != -1 { +- return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token) ++ for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') { ++ if tokenEqual(trimOWS(v[:comma]), token) { ++ return true ++ } ++ v = v[comma+1:] + } +- return tokenEqual(v, token) ++ return tokenEqual(trimOWS(v), token) + } + + // lowerASCII returns the ASCII lowercase version of b. +diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt +index 03ca3c3ae4..dd2296b694 100644 +--- a/src/vendor/modules.txt ++++ b/src/vendor/modules.txt +@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 + golang.org/x/crypto/hkdf + golang.org/x/crypto/internal/subtle + golang.org/x/crypto/poly1305 +-# golang.org/x/net v0.0.0-20201008223702-a5fa9d4b7c91 ++# golang.org/x/net v0.0.0-20210428183841-261fb518b1ed + ## explicit + golang.org/x/net/dns/dnsmessage + golang.org/x/net/http/httpguts +-- +2.27.0 + diff --git a/0039-release-branch.go1.15-runtime-time-disable-preemptio.patch b/0039-release-branch.go1.15-runtime-time-disable-preemptio.patch new file mode 100644 index 0000000000000000000000000000000000000000..bde920dd557b423f4b43c278b5a0de121703a47c --- /dev/null +++ b/0039-release-branch.go1.15-runtime-time-disable-preemptio.patch @@ -0,0 +1,95 @@ +From 72ccabc99449b2cb5bb1438eb90244d55f7b02f5 Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Wed, 10 Mar 2021 16:06:47 -0500 +Subject: [PATCH 39/44] [release-branch.go1.15] runtime, time: disable + preemption in addtimer + +The timerpMask optimization updates a mask of Ps (potentially) +containing timers in pidleget / pidleput. For correctness, it depends on +the assumption that new timers can only be added to a P's own heap. + +addtimer violates this assumption if it is preempted after computing pp. +That G may then run on a different P, but adding a timer to the original +P's heap. + +Avoid this by disabling preemption while pp is in use. + +Other uses of doaddtimer should be OK: + +* moveTimers: always moves to the current P's heap +* modtimer, cleantimers, addAdjustedTimers, runtimer: does not add net + new timers to the heap while locked + +For #44868 +Fixes #45731 + +Change-Id: I4a5d080865e854931d0a3a09a51ca36879101d72 +Reviewed-on: https://go-review.googlesource.com/c/go/+/300610 +Trust: Michael Pratt +Run-TryBot: Michael Pratt +Reviewed-by: Michael Knyszek +Reviewed-by: Ian Lance Taylor +TryBot-Result: Go Bot +Reviewed-on: https://go-review.googlesource.com/c/go/+/313129 +Trust: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +Reviewed-by: Michael Pratt + +Conflict:NA +Reference:https://github.com/golang/go/commit/72ccabc99449b2cb5bb1438eb90244d55f7b02f5 + +--- + src/runtime/time.go | 5 +++++ + src/time/sleep_test.go | 16 ++++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/src/runtime/time.go b/src/runtime/time.go +index ec3eae9cca..de7468d129 100644 +--- a/src/runtime/time.go ++++ b/src/runtime/time.go +@@ -254,6 +254,9 @@ func addtimer(t *timer) { + + when := t.when + ++ // Disable preemption while using pp to avoid changing another P's heap. ++ mp := acquirem() ++ + pp := getg().m.p.ptr() + lock(&pp.timersLock) + cleantimers(pp) +@@ -261,6 +264,8 @@ func addtimer(t *timer) { + unlock(&pp.timersLock) + + wakeNetPoller(when) ++ ++ releasem(mp) + } + + // doaddtimer adds t to the current P's heap. +diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go +index f5678020b9..ea253f8709 100644 +--- a/src/time/sleep_test.go ++++ b/src/time/sleep_test.go +@@ -501,3 +501,19 @@ func TestZeroTimerStopPanics(t *testing.T) { + var tr Timer + tr.Stop() + } ++ ++// Test that zero duration timers aren't missed by the scheduler. Regression test for issue 44868. ++func TestZeroTimer(t *testing.T) { ++ if testing.Short() { ++ t.Skip("-short") ++ } ++ ++ for i := 0; i < 1000000; i++ { ++ s := Now() ++ ti := NewTimer(0) ++ <-ti.C ++ if diff := Since(s); diff > 2*Second { ++ t.Errorf("Expected time to get value from Timer channel in less than 2 sec, took %v", diff) ++ } ++ } ++} +-- +2.27.0 + diff --git a/0040-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch b/0040-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch new file mode 100644 index 0000000000000000000000000000000000000000..e13ccf7ff64825089e7764a93a305b17d5f223e6 --- /dev/null +++ b/0040-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch @@ -0,0 +1,54 @@ +From c0a7ecfae775a9d50d338e8123fac32a5d04308c Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Fri, 9 Apr 2021 17:01:45 -0400 +Subject: [PATCH 40/44] [release-branch.go1.15] runtime: non-strict + InlTreeIndex lookup in expandFinalInlineFrame + +This is a follow-up to golang.org/cl/301369, which made the same change +in Frames.Next. The same logic applies here: a profile stack may have +been truncated at an invalid PC provided by cgoTraceback. +expandFinalInlineFrame will then try to lookup the inline tree and +crash. + +The same fix applies as well: upon encountering a bad PC, simply leave +it as-is and move on. + +For #44971 +For #45480 +Fixes #45481 + +Change-Id: I2823c67a1f3425466b05384cc6d30f5fc8ee6ddc +Reviewed-on: https://go-review.googlesource.com/c/go/+/309109 +Reviewed-by: Michael Knyszek +Trust: Michael Pratt +(cherry picked from commit aad13cbb749d1e6c085ff0556d306de1a2d5d063) +Reviewed-on: https://go-review.googlesource.com/c/go/+/309550 +Run-TryBot: Michael Pratt +Reviewed-by: Cherry Zhang +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/c0a7ecfae775a9d50d338e8123fac32a5d04308c + +--- + src/runtime/symtab.go | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go +index c77d513e74..75772f4fd8 100644 +--- a/src/runtime/symtab.go ++++ b/src/runtime/symtab.go +@@ -185,7 +185,9 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr { + var cache pcvalueCache + inltree := (*[1 << 20]inlinedCall)(inldata) + for { +- ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache) ++ // Non-strict as cgoTraceback may have added bogus PCs ++ // with a valid funcInfo but invalid PCDATA. ++ ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, tracepc, &cache, false) + if ix < 0 { + break + } +-- +2.27.0 + diff --git a/0041-release-branch.go1.15-runtime-pprof-skip-tests-for-A.patch b/0041-release-branch.go1.15-runtime-pprof-skip-tests-for-A.patch new file mode 100644 index 0000000000000000000000000000000000000000..dd2edf4e19747bcf3780e97fd239dd1c501ec4d7 --- /dev/null +++ b/0041-release-branch.go1.15-runtime-pprof-skip-tests-for-A.patch @@ -0,0 +1,48 @@ +From ba7cac469b399b36e8d3e40ac57eb11688c53e00 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= +Date: Thu, 1 Apr 2021 10:06:05 +0200 +Subject: [PATCH 41/44] [release-branch.go1.15] runtime/pprof: skip tests for + AIX + +Most of the time, the pprof tests are passing, except +for the builder. The reason is still unknown but I'd rather release +the builder to avoid missing other more important bugs. + +Updates #45170 + +Change-Id: I667543ee1ae309b7319c5b3676a0901b4d0ecf2e +Reviewed-on: https://go-review.googlesource.com/c/go/+/306489 +Run-TryBot: Tobias Klauser +TryBot-Result: Go Bot +Reviewed-by: Cherry Zhang +Trust: Lynn Boger +(cherry picked from commit 7bfd681c2f11918c6245ad2906b2efc12eda2914) +Reviewed-on: https://go-review.googlesource.com/c/go/+/317369 +Reviewed-by: Heschi Kreinick +Trust: Dmitri Shuralyov +Run-TryBot: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/ba7cac469b399b36e8d3e40ac57eb11688c53e00 + +--- + src/runtime/pprof/pprof_test.go | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go +index 7149bfb31f..9c1c097206 100644 +--- a/src/runtime/pprof/pprof_test.go ++++ b/src/runtime/pprof/pprof_test.go +@@ -280,7 +280,8 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri + + broken := false + switch runtime.GOOS { +- case "darwin", "dragonfly", "netbsd", "illumos", "solaris": ++ // See https://golang.org/issue/45170 for AIX. ++ case "darwin", "dragonfly", "netbsd", "illumos", "solaris", "aix": + broken = true + case "openbsd": + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { +-- +2.27.0 + diff --git a/0043-release-branch.go1.15-math-big-fix-TestShiftOverlap-.patch b/0043-release-branch.go1.15-math-big-fix-TestShiftOverlap-.patch new file mode 100644 index 0000000000000000000000000000000000000000..61e4a7658747c36b5c3c47407f90550dd93333dc --- /dev/null +++ b/0043-release-branch.go1.15-math-big-fix-TestShiftOverlap-.patch @@ -0,0 +1,65 @@ +From 44a6805ca92b00f30d5ed3f9e8d0b464d3f402bf Mon Sep 17 00:00:00 2001 +From: SparrowLii +Date: Mon, 24 Aug 2020 14:43:32 +0800 +Subject: [PATCH 43/44] [release-branch.go1.15] math/big: fix TestShiftOverlap + for test -count arguments > 1 + +Don't overwrite incoming test data. + +The change uses copy instead of assigning statement to avoid this. + +For #45335 + +Change-Id: Ib907101822d811de5c45145cb9d7961907e212c3 +Reviewed-on: https://go-review.googlesource.com/c/go/+/250137 +Run-TryBot: Emmanuel Odeke +TryBot-Result: Gobot Gobot +Reviewed-by: Robert Griesemer +(cherry picked from commit 41bc0a1713b9436e96c2d64211ad94e42cafd591) +Reviewed-on: https://go-review.googlesource.com/c/go/+/319831 +Run-TryBot: Carlos Amedee +TryBot-Result: Go Bot +Trust: Carlos Amedee +Reviewed-by: Jonathan Albrecht +Reviewed-by: Emmanuel Odeke + +Conflict:NA +Reference:https://github.com/golang/go/commit/44a6805ca92b00f30d5ed3f9e8d0b464d3f402bf + +--- + src/math/big/arith_test.go | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go +index 05136f1895..e2b982c89c 100644 +--- a/src/math/big/arith_test.go ++++ b/src/math/big/arith_test.go +@@ -241,20 +241,20 @@ var argshrVU = []argVU{ + } + + func testShiftFunc(t *testing.T, f func(z, x []Word, s uint) Word, a argVU) { +- // save a.d for error message, or it will be overwritten. ++ // work on copy of a.d to preserve the original data. + b := make([]Word, len(a.d)) + copy(b, a.d) +- z := a.d[a.zp : a.zp+a.l] +- x := a.d[a.xp : a.xp+a.l] ++ z := b[a.zp : a.zp+a.l] ++ x := b[a.xp : a.xp+a.l] + c := f(z, x, a.s) + for i, zi := range z { + if zi != a.r[i] { +- t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot z[%d] = %#x; want %#x", b, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, i, zi, a.r[i]) ++ t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot z[%d] = %#x; want %#x", a.d, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, i, zi, a.r[i]) + break + } + } + if c != a.c { +- t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot c = %#x; want %#x", b, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, c, a.c) ++ t.Errorf("d := %v, %s(d[%d:%d], d[%d:%d], %d)\n\tgot c = %#x; want %#x", a.d, a.m, a.zp, a.zp+a.l, a.xp, a.xp+a.l, a.s, c, a.c) + } + } + +-- +2.27.0 + diff --git a/0044-release-branch.go1.15-math-big-remove-the-s390x-asse.patch b/0044-release-branch.go1.15-math-big-remove-the-s390x-asse.patch new file mode 100644 index 0000000000000000000000000000000000000000..799505e68cfc601c9532cedc83ed7d393528e4b8 --- /dev/null +++ b/0044-release-branch.go1.15-math-big-remove-the-s390x-asse.patch @@ -0,0 +1,337 @@ +From 963687891319d118c20a2a71f0234ceb3a8dade4 Mon Sep 17 00:00:00 2001 +From: Jonathan Albrecht +Date: Wed, 2 Dec 2020 10:44:10 -0500 +Subject: [PATCH 44/44] [release-branch.go1.15] math/big: remove the s390x + assembly for shlVU and shrVU + +The s390x assembly for shlVU does a forward copy when the shift amount s +is 0. This causes corruption of the result z when z is aliased to the +input x. + +This fix removes the s390x assembly for both shlVU and shrVU so the pure +go implementations will be used. + +Test cases have been added to the existing TestShiftOverlap test to +cover shift values of 0, 1 and (_W - 1). + +Fixes #45335 + +Change-Id: I75ca0e98f3acfaa6366a26355dcd9dd82499a48b +Reviewed-on: https://go-review.googlesource.com/c/go/+/274442 +Run-TryBot: Robert Griesemer +TryBot-Result: Go Bot +Reviewed-by: Robert Griesemer +Reviewed-by: Matthew Dempsky +Trust: Robert Griesemer +(cherry picked from commit b1369d5862bc78eaa902ae637c874e6a6133f1f9) +Reviewed-on: https://go-review.googlesource.com/c/go/+/320169 +Trust: Carlos Amedee +Run-TryBot: Carlos Amedee +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/963687891319d118c20a2a71f0234ceb3a8dade4 + +--- + src/math/big/arith_s390x.s | 192 +------------------------------------ + src/math/big/arith_test.go | 55 ++++++++++- + 2 files changed, 54 insertions(+), 193 deletions(-) + +diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s +index 4891768111..153c42679c 100644 +--- a/src/math/big/arith_s390x.s ++++ b/src/math/big/arith_s390x.s +@@ -702,199 +702,11 @@ returnC: + + // func shlVU(z, x []Word, s uint) (c Word) + TEXT ·shlVU(SB), NOSPLIT, $0 +- MOVD z_len+8(FP), R5 +- MOVD $0, R0 +- SUB $1, R5 // n-- +- BLT X8b // n < 0 (n <= 0) +- +- // n > 0 +- MOVD s+48(FP), R4 +- CMPBEQ R0, R4, Z80 // handle 0 case beq +- MOVD $64, R6 +- CMPBEQ R6, R4, Z864 // handle 64 case beq +- MOVD z+0(FP), R2 +- MOVD x+24(FP), R8 +- SLD $3, R5 // n = n*8 +- SUB R4, R6, R7 +- MOVD (R8)(R5*1), R10 // w1 = x[i-1] +- SRD R7, R10, R3 +- MOVD R3, c+56(FP) +- +- MOVD $0, R1 // i = 0 +- BR E8 +- +- // i < n-1 +-L8: +- MOVD R10, R3 // w = w1 +- MOVD -8(R8)(R5*1), R10 // w1 = x[i+1] +- +- SLD R4, R3 // w<>ŝ +- SRD R7, R10, R6 +- OR R6, R3 +- MOVD R3, (R2)(R5*1) // z[i] = w<>ŝ +- SUB $8, R5 // i-- +- +-E8: +- CMPBGT R5, R0, L8 // i < n-1 +- +- // i >= n-1 +-X8a: +- SLD R4, R10 // w1<= n-1 +- MOVD R10, (R2)(R5*1) +- RET +- +-Z864: +- MOVD z+0(FP), R2 +- MOVD x+24(FP), R8 +- SLD $3, R5 // n = n*8 +- MOVD (R8)(R5*1), R3 // w1 = x[n-1] +- MOVD R3, c+56(FP) // z[i] = x[n-1] +- +- BR E864 +- +- // i < n-1 +-L864: +- MOVD -8(R8)(R5*1), R3 +- +- MOVD R3, (R2)(R5*1) // z[i] = x[n-1] +- SUB $8, R5 // i-- +- +-E864: +- CMPBGT R5, R0, L864 // i < n-1 +- +- MOVD R0, (R2) // z[n-1] = 0 +- RET ++ BR ·shlVU_g(SB) + +-// CX = R4, r8 = r8, r10 = r2 , r11 = r5, DX = r3, AX = r10 , BX = R1 , 64-count = r7 (R0 set to 0) temp = R6 + // func shrVU(z, x []Word, s uint) (c Word) + TEXT ·shrVU(SB), NOSPLIT, $0 +- MOVD z_len+8(FP), R5 +- MOVD $0, R0 +- SUB $1, R5 // n-- +- BLT X9b // n < 0 (n <= 0) +- +- // n > 0 +- MOVD s+48(FP), R4 +- CMPBEQ R0, R4, ZB0 // handle 0 case beq +- MOVD $64, R6 +- CMPBEQ R6, R4, ZB64 // handle 64 case beq +- MOVD z+0(FP), R2 +- MOVD x+24(FP), R8 +- SLD $3, R5 // n = n*8 +- SUB R4, R6, R7 +- MOVD (R8), R10 // w1 = x[0] +- SLD R7, R10, R3 +- MOVD R3, c+56(FP) +- +- MOVD $0, R1 // i = 0 +- BR E9 +- +- // i < n-1 +-L9: +- MOVD R10, R3 // w = w1 +- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1] +- +- SRD R4, R3 // w>>s | w1<>s | w1<= n-1 +-X9a: +- SRD R4, R10 // w1>>s +- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s +- RET +- +-X9b: +- MOVD R0, c+56(FP) +- RET +- +-ZB0: +- MOVD z+0(FP), R2 +- MOVD x+24(FP), R8 +- SLD $3, R5 // n = n*8 +- +- MOVD (R8), R10 // w1 = x[0] +- MOVD $0, R3 // R10 << 64 +- MOVD R3, c+56(FP) +- +- MOVD $0, R1 // i = 0 +- BR E9Z +- +- // i < n-1 +-L9Z: +- MOVD R10, R3 // w = w1 +- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1] +- +- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1 +- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s +- RET +- +-ZB64: +- MOVD z+0(FP), R2 +- MOVD x+24(FP), R8 +- SLD $3, R5 // n = n*8 +- MOVD (R8), R3 // w1 = x[0] +- MOVD R3, c+56(FP) +- +- MOVD $0, R1 // i = 0 +- BR E964 +- +- // i < n-1 +-L964: +- MOVD 8(R8)(R1*1), R3 // w1 = x[i+1] +- +- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1 +- MOVD $0, R10 // w1>>s +- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s +- RET ++ BR ·shrVU_g(SB) + + // CX = R4, r8 = r8, r9=r9, r10 = r2 , r11 = r5, DX = r3, AX = r6 , BX = R1 , (R0 set to 0) + use R11 + use R7 for i + // func mulAddVWW(z, x []Word, y, r Word) (c Word) +diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go +index e2b982c89c..fbbaa0e122 100644 +--- a/src/math/big/arith_test.go ++++ b/src/math/big/arith_test.go +@@ -224,13 +224,36 @@ type argVU struct { + m string // message. + } + ++var argshlVUIn = []Word{1, 2, 4, 8, 16, 32, 64, 0, 0, 0} ++var argshlVUr0 = []Word{1, 2, 4, 8, 16, 32, 64} ++var argshlVUr1 = []Word{2, 4, 8, 16, 32, 64, 128} ++var argshlVUrWm1 = []Word{1 << (_W - 1), 0, 1, 2, 4, 8, 16} ++ + var argshlVU = []argVU{ + // test cases for shlVU + {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0}, 7, 0, 0, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "complete overlap of shlVU"}, + {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0}, 7, 0, 3, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by half of shlVU"}, + {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0}, 7, 0, 6, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by 1 Word of shlVU"}, + {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0, 0}, 7, 0, 7, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "no overlap of shlVU"}, +-} ++ // additional test cases with shift values of 0, 1 and (_W-1) ++ {argshlVUIn, 7, 0, 0, 0, argshlVUr0, 0, "complete overlap of shlVU and shift of 0"}, ++ {argshlVUIn, 7, 0, 0, 1, argshlVUr1, 0, "complete overlap of shlVU and shift of 1"}, ++ {argshlVUIn, 7, 0, 0, _W - 1, argshlVUrWm1, 32, "complete overlap of shlVU and shift of _W - 1"}, ++ {argshlVUIn, 7, 0, 1, 0, argshlVUr0, 0, "partial overlap by 6 Words of shlVU and shift of 0"}, ++ {argshlVUIn, 7, 0, 1, 1, argshlVUr1, 0, "partial overlap by 6 Words of shlVU and shift of 1"}, ++ {argshlVUIn, 7, 0, 1, _W - 1, argshlVUrWm1, 32, "partial overlap by 6 Words of shlVU and shift of _W - 1"}, ++ {argshlVUIn, 7, 0, 2, 0, argshlVUr0, 0, "partial overlap by 5 Words of shlVU and shift of 0"}, ++ {argshlVUIn, 7, 0, 2, 1, argshlVUr1, 0, "partial overlap by 5 Words of shlVU and shift of 1"}, ++ {argshlVUIn, 7, 0, 2, _W - 1, argshlVUrWm1, 32, "partial overlap by 5 Words of shlVU abd shift of _W - 1"}, ++ {argshlVUIn, 7, 0, 3, 0, argshlVUr0, 0, "partial overlap by 4 Words of shlVU and shift of 0"}, ++ {argshlVUIn, 7, 0, 3, 1, argshlVUr1, 0, "partial overlap by 4 Words of shlVU and shift of 1"}, ++ {argshlVUIn, 7, 0, 3, _W - 1, argshlVUrWm1, 32, "partial overlap by 4 Words of shlVU and shift of _W - 1"}, ++} ++ ++var argshrVUIn = []Word{0, 0, 0, 1, 2, 4, 8, 16, 32, 64} ++var argshrVUr0 = []Word{1, 2, 4, 8, 16, 32, 64} ++var argshrVUr1 = []Word{0, 1, 2, 4, 8, 16, 32} ++var argshrVUrWm1 = []Word{4, 8, 16, 32, 64, 128, 0} + + var argshrVU = []argVU{ + // test cases for shrVU +@@ -238,6 +261,19 @@ var argshrVU = []argVU{ + {[]Word{0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 4, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by half of shrVU"}, + {[]Word{0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 7, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by 1 Word of shrVU"}, + {[]Word{0, 0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 8, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "no overlap of shrVU"}, ++ // additional test cases with shift values of 0, 1 and (_W-1) ++ {argshrVUIn, 7, 3, 3, 0, argshrVUr0, 0, "complete overlap of shrVU and shift of 0"}, ++ {argshrVUIn, 7, 3, 3, 1, argshrVUr1, 1 << (_W - 1), "complete overlap of shrVU and shift of 1"}, ++ {argshrVUIn, 7, 3, 3, _W - 1, argshrVUrWm1, 2, "complete overlap of shrVU and shift of _W - 1"}, ++ {argshrVUIn, 7, 3, 2, 0, argshrVUr0, 0, "partial overlap by 6 Words of shrVU and shift of 0"}, ++ {argshrVUIn, 7, 3, 2, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 6 Words of shrVU and shift of 1"}, ++ {argshrVUIn, 7, 3, 2, _W - 1, argshrVUrWm1, 2, "partial overlap by 6 Words of shrVU and shift of _W - 1"}, ++ {argshrVUIn, 7, 3, 1, 0, argshrVUr0, 0, "partial overlap by 5 Words of shrVU and shift of 0"}, ++ {argshrVUIn, 7, 3, 1, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 5 Words of shrVU and shift of 1"}, ++ {argshrVUIn, 7, 3, 1, _W - 1, argshrVUrWm1, 2, "partial overlap by 5 Words of shrVU and shift of _W - 1"}, ++ {argshrVUIn, 7, 3, 0, 0, argshrVUr0, 0, "partial overlap by 4 Words of shrVU and shift of 0"}, ++ {argshrVUIn, 7, 3, 0, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 4 Words of shrVU and shift of 1"}, ++ {argshrVUIn, 7, 3, 0, _W - 1, argshrVUrWm1, 2, "partial overlap by 4 Words of shrVU and shift of _W - 1"}, + } + + func testShiftFunc(t *testing.T, f func(z, x []Word, s uint) Word, a argVU) { +@@ -274,11 +310,24 @@ func TestIssue31084(t *testing.T) { + // compute 10^n via 5^n << n. + const n = 165 + p := nat(nil).expNN(nat{5}, nat{n}, nil) +- p = p.shl(p, uint(n)) ++ p = p.shl(p, n) + got := string(p.utoa(10)) + want := "1" + strings.Repeat("0", n) + if got != want { +- t.Errorf("shl(%v, %v)\n\tgot %s; want %s\n", p, uint(n), got, want) ++ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", p, n, got, want) ++ } ++} ++ ++const issue42838Value = "159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625" ++ ++func TestIssue42838(t *testing.T) { ++ const s = 192 ++ z, _, _, _ := nat(nil).scan(strings.NewReader(issue42838Value), 0, false) ++ z = z.shl(z, s) ++ got := string(z.utoa(10)) ++ want := "1" + strings.Repeat("0", s) ++ if got != want { ++ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", z, s, got, want) + } + } + +-- +2.27.0 + diff --git a/0045-net-http-fix-hijack-hang-at-abortPendingRead.patch b/0045-net-http-fix-hijack-hang-at-abortPendingRead.patch new file mode 100644 index 0000000000000000000000000000000000000000..a80c86513946fde1390b2de1a8a40ec7d266a16f --- /dev/null +++ b/0045-net-http-fix-hijack-hang-at-abortPendingRead.patch @@ -0,0 +1,59 @@ +From 78770c121e8c2315d7bdf9e66870abffdaedbe9b Mon Sep 17 00:00:00 2001 +From: jingrui +Date: Thu, 20 May 2021 09:18:27 +0800 +Subject: [PATCH] net/http: fix hijack hang at abortPendingRead + +When concurrent many http requests which need hijack the connenction, +hijack may hang at abortPendingRead() on cr.cond.Wait(). + +The read can be from readRequest() from conn.serve() or +w.conn.r.startBackgroundRead(). especially in startBackgroundRead() +which always set the deadline time.Time{}. + +This problem seems easy reproduce on arm. + +Signed-off-by: jingrui + +Conflict:NA +Reference:https://github.com/golang/go/pull/46278/commits/78770c121e8c2315d7bdf9e66870abffdaedbe9b + +--- + src/net/http/server.go | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/src/net/http/server.go b/src/net/http/server.go +index 4e73508973..01e7e10011 100644 +--- a/src/net/http/server.go ++++ b/src/net/http/server.go +@@ -736,9 +736,25 @@ func (cr *connReader) abortPendingRead() { + } + cr.aborted = true + cr.conn.rwc.SetReadDeadline(aLongTimeAgo) +- for cr.inRead { +- cr.cond.Wait() +- } ++ done := make(chan struct{}) ++ go func() { ++ for cr.inRead { ++ cr.cond.Wait() ++ } ++ close(done) ++ }() ++ ++ func() { ++ for { ++ select { ++ case <-done: ++ return ++ case <-time.After(100*time.Millisecond): ++ cr.conn.rwc.SetReadDeadline(aLongTimeAgo) ++ } ++ } ++ }() ++ + cr.conn.rwc.SetReadDeadline(time.Time{}) + } + +-- +2.27.0 + diff --git a/0046-release-branch.go1.15-net-verify-results-from-Lookup.patch b/0046-release-branch.go1.15-net-verify-results-from-Lookup.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea2d49a5a00c984bcce7cb4080ba525b38b961eb --- /dev/null +++ b/0046-release-branch.go1.15-net-verify-results-from-Lookup.patch @@ -0,0 +1,375 @@ +From 31d60cda1f58b7558fc5725d2b9e4531655d980e Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Thu, 27 May 2021 10:40:06 -0700 +Subject: [PATCH] [release-branch.go1.15] net: verify results from Lookup* are + valid domain names + +For the methods LookupCNAME, LookupSRV, LookupMX, LookupNS, and +LookupAddr check that the returned domain names are in fact valid DNS +names using the existing isDomainName function. + +Thanks to Philipp Jeitner and Haya Shulman from Fraunhofer SIT for +reporting this issue. + +Updates #46241 +Fixes #46356 +Fixes CVE-2021-33195 + +Conflict:NA +Reference:https://github.com/golang/go/commit/31d60cda1f58b7558fc5725d2b9e4531655d980e + +Change-Id: I47a4f58c031cb752f732e88bbdae7f819f0af4f3 +Reviewed-on: https://go-review.googlesource.com/c/go/+/323131 +Trust: Roland Shoemaker +Run-TryBot: Roland Shoemaker +TryBot-Result: Go Bot +Reviewed-by: Filippo Valsorda +Reviewed-by: Katie Hockman +(cherry picked from commit cdcd02842da7c004efd023881e3719105209c908) +Reviewed-on: https://go-review.googlesource.com/c/go/+/323269 +--- + src/net/dnsclient_unix_test.go | 157 +++++++++++++++++++++++++++++++++ + src/net/lookup.go | 111 ++++++++++++++++++++--- + 2 files changed, 255 insertions(+), 13 deletions(-) + +diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go +index 06553636ee..819f20b887 100644 +--- a/src/net/dnsclient_unix_test.go ++++ b/src/net/dnsclient_unix_test.go +@@ -1799,3 +1799,160 @@ func TestPTRandNonPTR(t *testing.T) { + t.Errorf("names = %q; want %q", names, want) + } + } ++ ++func TestCVE202133195(t *testing.T) { ++ fake := fakeDNSServer{ ++ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { ++ r := dnsmessage.Message{ ++ Header: dnsmessage.Header{ ++ ID: q.Header.ID, ++ Response: true, ++ RCode: dnsmessage.RCodeSuccess, ++ RecursionAvailable: true, ++ }, ++ Questions: q.Questions, ++ } ++ switch q.Questions[0].Type { ++ case dnsmessage.TypeCNAME: ++ r.Answers = []dnsmessage.Resource{} ++ case dnsmessage.TypeA: // CNAME lookup uses a A/AAAA as a proxy ++ r.Answers = append(r.Answers, ++ dnsmessage.Resource{ ++ Header: dnsmessage.ResourceHeader{ ++ Name: dnsmessage.MustNewName(".golang.org."), ++ Type: dnsmessage.TypeA, ++ Class: dnsmessage.ClassINET, ++ Length: 4, ++ }, ++ Body: &dnsmessage.AResource{ ++ A: TestAddr, ++ }, ++ }, ++ ) ++ case dnsmessage.TypeSRV: ++ n := q.Questions[0].Name ++ if n.String() == "_hdr._tcp.golang.org." { ++ n = dnsmessage.MustNewName(".golang.org.") ++ } ++ r.Answers = append(r.Answers, ++ dnsmessage.Resource{ ++ Header: dnsmessage.ResourceHeader{ ++ Name: n, ++ Type: dnsmessage.TypeSRV, ++ Class: dnsmessage.ClassINET, ++ Length: 4, ++ }, ++ Body: &dnsmessage.SRVResource{ ++ Target: dnsmessage.MustNewName(".golang.org."), ++ }, ++ }, ++ ) ++ case dnsmessage.TypeMX: ++ r.Answers = append(r.Answers, ++ dnsmessage.Resource{ ++ Header: dnsmessage.ResourceHeader{ ++ Name: dnsmessage.MustNewName(".golang.org."), ++ Type: dnsmessage.TypeMX, ++ Class: dnsmessage.ClassINET, ++ Length: 4, ++ }, ++ Body: &dnsmessage.MXResource{ ++ MX: dnsmessage.MustNewName(".golang.org."), ++ }, ++ }, ++ ) ++ case dnsmessage.TypeNS: ++ r.Answers = append(r.Answers, ++ dnsmessage.Resource{ ++ Header: dnsmessage.ResourceHeader{ ++ Name: dnsmessage.MustNewName(".golang.org."), ++ Type: dnsmessage.TypeNS, ++ Class: dnsmessage.ClassINET, ++ Length: 4, ++ }, ++ Body: &dnsmessage.NSResource{ ++ NS: dnsmessage.MustNewName(".golang.org."), ++ }, ++ }, ++ ) ++ case dnsmessage.TypePTR: ++ r.Answers = append(r.Answers, ++ dnsmessage.Resource{ ++ Header: dnsmessage.ResourceHeader{ ++ Name: dnsmessage.MustNewName(".golang.org."), ++ Type: dnsmessage.TypePTR, ++ Class: dnsmessage.ClassINET, ++ Length: 4, ++ }, ++ Body: &dnsmessage.PTRResource{ ++ PTR: dnsmessage.MustNewName(".golang.org."), ++ }, ++ }, ++ ) ++ } ++ return r, nil ++ }, ++ } ++ ++ r := Resolver{PreferGo: true, Dial: fake.DialContext} ++ // Change the default resolver to match our manipulated resolver ++ originalDefault := DefaultResolver ++ DefaultResolver = &r ++ defer func() { ++ DefaultResolver = originalDefault ++ }() ++ ++ _, err := r.LookupCNAME(context.Background(), "golang.org") ++ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, err = LookupCNAME("golang.org") ++ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ ++ _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org") ++ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, _, err = LookupSRV("target", "tcp", "golang.org") ++ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ ++ _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org") ++ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, _, err = LookupSRV("hdr", "tcp", "golang.org") ++ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ ++ _, err = r.LookupMX(context.Background(), "golang.org") ++ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, err = LookupMX("golang.org") ++ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupMX returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ ++ _, err = r.LookupNS(context.Background(), "golang.org") ++ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, err = LookupNS("golang.org") ++ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupNS returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ ++ _, err = r.LookupAddr(context.Background(), "1.2.3.4") ++ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++ _, err = LookupAddr("1.2.3.4") ++ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected { ++ t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected) ++ } ++} +diff --git a/src/net/lookup.go b/src/net/lookup.go +index 5f7119872a..0660268249 100644 +--- a/src/net/lookup.go ++++ b/src/net/lookup.go +@@ -389,8 +389,11 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por + // LookupCNAME does not return an error if host does not + // contain DNS "CNAME" records, as long as host resolves to + // address records. ++// ++// The returned canonical name is validated to be a properly ++// formatted presentation-format domain name. + func LookupCNAME(host string) (cname string, err error) { +- return DefaultResolver.lookupCNAME(context.Background(), host) ++ return DefaultResolver.LookupCNAME(context.Background(), host) + } + + // LookupCNAME returns the canonical name for the given host. +@@ -403,8 +406,18 @@ func LookupCNAME(host string) (cname string, err error) { + // LookupCNAME does not return an error if host does not + // contain DNS "CNAME" records, as long as host resolves to + // address records. +-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) { +- return r.lookupCNAME(ctx, host) ++// ++// The returned canonical name is validated to be a properly ++// formatted presentation-format domain name. ++func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) { ++ cname, err := r.lookupCNAME(ctx, host) ++ if err != nil { ++ return "", err ++ } ++ if !isDomainName(cname) { ++ return "", &DNSError{Err: "CNAME target is invalid", Name: host} ++ } ++ return cname, nil + } + + // LookupSRV tries to resolve an SRV query of the given service, +@@ -416,8 +429,11 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, + // That is, it looks up _service._proto.name. To accommodate services + // publishing SRV records under non-standard names, if both service + // and proto are empty strings, LookupSRV looks up name directly. ++// ++// The returned service names are validated to be properly ++// formatted presentation-format domain names. + func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) { +- return DefaultResolver.lookupSRV(context.Background(), service, proto, name) ++ return DefaultResolver.LookupSRV(context.Background(), service, proto, name) + } + + // LookupSRV tries to resolve an SRV query of the given service, +@@ -429,28 +445,82 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err + // That is, it looks up _service._proto.name. To accommodate services + // publishing SRV records under non-standard names, if both service + // and proto are empty strings, LookupSRV looks up name directly. +-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) { +- return r.lookupSRV(ctx, service, proto, name) ++// ++// The returned service names are validated to be properly ++// formatted presentation-format domain names. ++func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { ++ cname, addrs, err := r.lookupSRV(ctx, service, proto, name) ++ if err != nil { ++ return "", nil, err ++ } ++ if cname != "" && !isDomainName(cname) { ++ return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name} ++ } ++ for _, addr := range addrs { ++ if addr == nil { ++ continue ++ } ++ if !isDomainName(addr.Target) { ++ return "", nil, &DNSError{Err: "SRV target is invalid", Name: name} ++ } ++ } ++ return cname, addrs, nil + } + + // LookupMX returns the DNS MX records for the given domain name sorted by preference. ++// ++// The returned mail server names are validated to be properly ++// formatted presentation-format domain names. + func LookupMX(name string) ([]*MX, error) { +- return DefaultResolver.lookupMX(context.Background(), name) ++ return DefaultResolver.LookupMX(context.Background(), name) + } + + // LookupMX returns the DNS MX records for the given domain name sorted by preference. ++// ++// The returned mail server names are validated to be properly ++// formatted presentation-format domain names. + func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { +- return r.lookupMX(ctx, name) ++ records, err := r.lookupMX(ctx, name) ++ if err != nil { ++ return nil, err ++ } ++ for _, mx := range records { ++ if mx == nil { ++ continue ++ } ++ if !isDomainName(mx.Host) { ++ return nil, &DNSError{Err: "MX target is invalid", Name: name} ++ } ++ } ++ return records, nil + } + + // LookupNS returns the DNS NS records for the given domain name. ++// ++// The returned name server names are validated to be properly ++// formatted presentation-format domain names. + func LookupNS(name string) ([]*NS, error) { +- return DefaultResolver.lookupNS(context.Background(), name) ++ return DefaultResolver.LookupNS(context.Background(), name) + } + + // LookupNS returns the DNS NS records for the given domain name. ++// ++// The returned name server names are validated to be properly ++// formatted presentation-format domain names. + func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { +- return r.lookupNS(ctx, name) ++ records, err := r.lookupNS(ctx, name) ++ if err != nil { ++ return nil, err ++ } ++ for _, ns := range records { ++ if ns == nil { ++ continue ++ } ++ if !isDomainName(ns.Host) { ++ return nil, &DNSError{Err: "NS target is invalid", Name: name} ++ } ++ } ++ return records, nil + } + + // LookupTXT returns the DNS TXT records for the given domain name. +@@ -466,14 +536,29 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) + // LookupAddr performs a reverse lookup for the given address, returning a list + // of names mapping to that address. + // ++// The returned names are validated to be properly formatted presentation-format ++// domain names. ++// + // When using the host C library resolver, at most one result will be + // returned. To bypass the host resolver, use a custom Resolver. + func LookupAddr(addr string) (names []string, err error) { +- return DefaultResolver.lookupAddr(context.Background(), addr) ++ return DefaultResolver.LookupAddr(context.Background(), addr) + } + + // LookupAddr performs a reverse lookup for the given address, returning a list + // of names mapping to that address. +-func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) { +- return r.lookupAddr(ctx, addr) ++// ++// The returned names are validated to be properly formatted presentation-format ++// domain names. ++func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) { ++ names, err := r.lookupAddr(ctx, addr) ++ if err != nil { ++ return nil, err ++ } ++ for _, name := range names { ++ if !isDomainName(name) { ++ return nil, &DNSError{Err: "PTR target is invalid", Name: addr} ++ } ++ } ++ return names, nil + } +-- +2.27.0 + diff --git a/0047-release-branch.go1.15-archive-zip-only-preallocate-F.patch b/0047-release-branch.go1.15-archive-zip-only-preallocate-F.patch new file mode 100644 index 0000000000000000000000000000000000000000..4be111d1da11b2b4ec2b0df989003944e307ee00 --- /dev/null +++ b/0047-release-branch.go1.15-archive-zip-only-preallocate-F.patch @@ -0,0 +1,130 @@ +From c92adf420a3d9a5510f9aea382d826f0c9216a10 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Tue, 11 May 2021 11:31:31 -0700 +Subject: [PATCH] [release-branch.go1.15] archive/zip: only preallocate File + slice if reasonably sized + +Since the number of files in the EOCD record isn't validated, it isn't +safe to preallocate Reader.Files using that field. A malformed archive +can indicate it contains up to 1 << 128 - 1 files. We can still safely +preallocate the slice by checking if the specified number of files in +the archive is reasonable, given the size of the archive. + +Thanks to the OSS-Fuzz project for discovering this issue and to +Emmanuel Odeke for reporting it. + +Updates #46242 +Fixes #46396 +Fixes CVE-2021-33196 + +Conflict:NA +Reference:https://github.com/golang/go/commit/c92adf420a3d9a5510f9aea382d826f0c9216a10 + +Change-Id: I3c76d8eec178468b380d87fdb4a3f2cb06f0ee76 +Reviewed-on: https://go-review.googlesource.com/c/go/+/318909 +Trust: Roland Shoemaker +Trust: Katie Hockman +Trust: Joe Tsai +Run-TryBot: Roland Shoemaker +TryBot-Result: Go Bot +Reviewed-by: Katie Hockman +Reviewed-by: Joe Tsai +(cherry picked from commit 74242baa4136c7a9132a8ccd9881354442788c8c) +Reviewed-on: https://go-review.googlesource.com/c/go/+/322949 +Reviewed-by: Filippo Valsorda +--- + src/archive/zip/reader.go | 10 +++++- + src/archive/zip/reader_test.go | 59 ++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 1 deletion(-) + +diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go +index 13ff9ddcf4..2d5151af3d 100644 +--- a/src/archive/zip/reader.go ++++ b/src/archive/zip/reader.go +@@ -84,7 +84,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { + return err + } + z.r = r +- z.File = make([]*File, 0, end.directoryRecords) ++ // Since the number of directory records is not validated, it is not ++ // safe to preallocate z.File without first checking that the specified ++ // number of files is reasonable, since a malformed archive may ++ // indicate it contains up to 1 << 128 - 1 files. Since each file has a ++ // header which will be _at least_ 30 bytes we can safely preallocate ++ // if (data size / 30) >= end.directoryRecords. ++ if (uint64(size)-end.directorySize)/30 >= end.directoryRecords { ++ z.File = make([]*File, 0, end.directoryRecords) ++ } + z.Comment = end.comment + rs := io.NewSectionReader(r, 0, size) + if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil { +diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go +index adca87a8b3..6f67d2e4a9 100644 +--- a/src/archive/zip/reader_test.go ++++ b/src/archive/zip/reader_test.go +@@ -1070,3 +1070,62 @@ func TestIssue12449(t *testing.T) { + t.Errorf("Error reading the archive: %v", err) + } + } ++ ++func TestCVE202133196(t *testing.T) { ++ // Archive that indicates it has 1 << 128 -1 files, ++ // this would previously cause a panic due to attempting ++ // to allocate a slice with 1 << 128 -1 elements. ++ data := []byte{ ++ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08, ++ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02, ++ 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00, ++ 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20, ++ 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, ++ 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, ++ 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00, ++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, ++ 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00, ++ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, ++ 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0x00, 0x00, ++ } ++ _, err := NewReader(bytes.NewReader(data), int64(len(data))) ++ if err != ErrFormat { ++ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat) ++ } ++ ++ // Also check that an archive containing a handful of empty ++ // files doesn't cause an issue ++ b := bytes.NewBuffer(nil) ++ w := NewWriter(b) ++ for i := 0; i < 5; i++ { ++ _, err := w.Create("") ++ if err != nil { ++ t.Fatalf("Writer.Create failed: %s", err) ++ } ++ } ++ if err := w.Close(); err != nil { ++ t.Fatalf("Writer.Close failed: %s", err) ++ } ++ r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len())) ++ if err != nil { ++ t.Fatalf("NewReader failed: %s", err) ++ } ++ if len(r.File) != 5 { ++ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File)) ++ } ++} +-- +2.27.0 + diff --git a/0048-release-branch.go1.15-net-http-httputil-always-remov.patch b/0048-release-branch.go1.15-net-http-httputil-always-remov.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a404bee420c8d8781de3362a98b5fde690ba5fc --- /dev/null +++ b/0048-release-branch.go1.15-net-http-httputil-always-remov.patch @@ -0,0 +1,154 @@ +From cbd1ca84453fecf3825a6bb9f985823e8bc32b76 Mon Sep 17 00:00:00 2001 +From: Filippo Valsorda +Date: Fri, 21 May 2021 14:02:30 -0400 +Subject: [PATCH] [release-branch.go1.15] net/http/httputil: always remove + hop-by-hop headers + +Previously, we'd fail to remove the Connection header from a request +like this: + + Connection: + Connection: x-header + +Updates #46313 +Fixes #46314 +Fixes CVE-2021-33197 + +Change-Id: Ie3009e926ceecfa86dfa6bcc6fe14ff01086be7d +Reviewed-on: https://go-review.googlesource.com/c/go/+/321929 +Run-TryBot: Filippo Valsorda +Reviewed-by: Katie Hockman +Trust: Katie Hockman +Trust: Filippo Valsorda +TryBot-Result: Go Bot +Reviewed-on: https://go-review.googlesource.com/c/go/+/323091 +Run-TryBot: Katie Hockman + +Conflict:NA +Reference:https://github.com/golang/go/commit/cbd1ca84453fecf3825a6bb9f985823e8bc32b76 + +--- + src/net/http/httputil/reverseproxy.go | 22 ++++---- + src/net/http/httputil/reverseproxy_test.go | 63 +++++++++++++++++++++- + 2 files changed, 70 insertions(+), 15 deletions(-) + +diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go +index 3f48fab544..f49cefbb4f 100644 +--- a/src/net/http/httputil/reverseproxy.go ++++ b/src/net/http/httputil/reverseproxy.go +@@ -248,22 +248,18 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + // important is "Connection" because we want a persistent + // connection, regardless of what the client sent to us. + for _, h := range hopHeaders { +- hv := outreq.Header.Get(h) +- if hv == "" { +- continue +- } +- if h == "Te" && hv == "trailers" { +- // Issue 21096: tell backend applications that +- // care about trailer support that we support +- // trailers. (We do, but we don't go out of +- // our way to advertise that unless the +- // incoming client request thought it was +- // worth mentioning) +- continue +- } + outreq.Header.Del(h) + } + ++ // Issue 21096: tell backend applications that care about trailer support ++ // that we support trailers. (We do, but we don't go out of our way to ++ // advertise that unless the incoming client request thought it was worth ++ // mentioning.) Note that we look at req.Header, not outreq.Header, since ++ // the latter has passed through removeConnectionHeaders. ++ if httpguts.HeaderValuesContainsToken(req.Header["Te"], "trailers") { ++ outreq.Header.Set("Te", "trailers") ++ } ++ + // After stripping all the hop-by-hop connection headers above, add back any + // necessary for protocol upgrades, such as for websockets. + if reqUpType != "" { +diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go +index 764939fb0f..1f2dfb9867 100644 +--- a/src/net/http/httputil/reverseproxy_test.go ++++ b/src/net/http/httputil/reverseproxy_test.go +@@ -91,8 +91,9 @@ func TestReverseProxy(t *testing.T) { + + getReq, _ := http.NewRequest("GET", frontend.URL, nil) + getReq.Host = "some-name" +- getReq.Header.Set("Connection", "close") +- getReq.Header.Set("Te", "trailers") ++ getReq.Header.Set("Connection", "close, TE") ++ getReq.Header.Add("Te", "foo") ++ getReq.Header.Add("Te", "bar, trailers") + getReq.Header.Set("Proxy-Connection", "should be deleted") + getReq.Header.Set("Upgrade", "foo") + getReq.Close = true +@@ -236,6 +237,64 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) { + } + } + ++func TestReverseProxyStripEmptyConnection(t *testing.T) { ++ // See Issue 46313. ++ const backendResponse = "I am the backend" ++ ++ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header ++ // in the Request's Connection header. ++ const someConnHeader = "X-Some-Conn-Header" ++ ++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if c := r.Header.Values("Connection"); len(c) != 0 { ++ t.Errorf("handler got header %q = %v; want empty", "Connection", c) ++ } ++ if c := r.Header.Get(someConnHeader); c != "" { ++ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c) ++ } ++ w.Header().Add("Connection", "") ++ w.Header().Add("Connection", someConnHeader) ++ w.Header().Set(someConnHeader, "should be deleted") ++ io.WriteString(w, backendResponse) ++ })) ++ defer backend.Close() ++ backendURL, err := url.Parse(backend.URL) ++ if err != nil { ++ t.Fatal(err) ++ } ++ proxyHandler := NewSingleHostReverseProxy(backendURL) ++ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ proxyHandler.ServeHTTP(w, r) ++ if c := r.Header.Get(someConnHeader); c != "should be deleted" { ++ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "should be deleted") ++ } ++ })) ++ defer frontend.Close() ++ ++ getReq, _ := http.NewRequest("GET", frontend.URL, nil) ++ getReq.Header.Add("Connection", "") ++ getReq.Header.Add("Connection", someConnHeader) ++ getReq.Header.Set(someConnHeader, "should be deleted") ++ res, err := frontend.Client().Do(getReq) ++ if err != nil { ++ t.Fatalf("Get: %v", err) ++ } ++ defer res.Body.Close() ++ bodyBytes, err := ioutil.ReadAll(res.Body) ++ if err != nil { ++ t.Fatalf("reading body: %v", err) ++ } ++ if got, want := string(bodyBytes), backendResponse; got != want { ++ t.Errorf("got body %q; want %q", got, want) ++ } ++ if c := res.Header.Get("Connection"); c != "" { ++ t.Errorf("handler got header %q = %q; want empty", "Connection", c) ++ } ++ if c := res.Header.Get(someConnHeader); c != "" { ++ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c) ++ } ++} ++ + func TestXForwardedFor(t *testing.T) { + const prevForwardedFor = "client ip" + const backendResponse = "I am the backend" +-- +2.27.0 + diff --git a/0049-release-branch.go1.15-math-big-check-for-excessive-e.patch b/0049-release-branch.go1.15-math-big-check-for-excessive-e.patch new file mode 100644 index 0000000000000000000000000000000000000000..745e88c108dea4440ca1aaf5798c81e37d7ab99e --- /dev/null +++ b/0049-release-branch.go1.15-math-big-check-for-excessive-e.patch @@ -0,0 +1,114 @@ +From df9ce19db6df32d94eae8760927bdfbc595433c3 Mon Sep 17 00:00:00 2001 +From: Robert Griesemer +Date: Sun, 2 May 2021 11:27:03 -0700 +Subject: [PATCH] [release-branch.go1.15] math/big: check for excessive + exponents in Rat.SetString + +Found by OSS-Fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33284 + +Thanks to Emmanuel Odeke for reporting this issue. + +Updates #45910 +Fixes #46305 +Fixes CVE-2021-33198 + +Change-Id: I61e7b04dbd80343420b57eede439e361c0f7b79c +Reviewed-on: https://go-review.googlesource.com/c/go/+/316149 +Trust: Robert Griesemer +Trust: Katie Hockman +Run-TryBot: Robert Griesemer +TryBot-Result: Go Bot +Reviewed-by: Katie Hockman +Reviewed-by: Emmanuel Odeke +(cherry picked from commit 6c591f79b0b5327549bd4e94970f7a279efb4ab0) +Reviewed-on: https://go-review.googlesource.com/c/go/+/321831 +Run-TryBot: Katie Hockman +Reviewed-by: Roland Shoemaker + +Conflict:NA +Reference:https://github.com/golang/go/commit/df9ce19db6df32d94eae8760927bdfbc595433c3 + +--- + src/math/big/ratconv.go | 15 ++++++++------- + src/math/big/ratconv_test.go | 25 +++++++++++++++++++++++++ + 2 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go +index 941139e72d..ac3c8bd11f 100644 +--- a/src/math/big/ratconv.go ++++ b/src/math/big/ratconv.go +@@ -51,7 +51,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error { + // An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants) + // exponent may be provided as well, except for hexadecimal floats which + // only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot +-// be distinguished from a mantissa digit). ++// be distinguished from a mantissa digit). If the exponent's absolute value ++// is too large, the operation may fail. + // The entire string, not just a prefix, must be valid for success. If the + // operation failed, the value of z is undefined but the returned value is nil. + func (z *Rat) SetString(s string) (*Rat, bool) { +@@ -169,6 +170,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) { + if n < 0 { + n = -n + } ++ if n > 1e6 { ++ return nil, false // avoid excessively large exponents ++ } + pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs + if exp5 > 0 { + z.a.abs = z.a.abs.mul(z.a.abs, pow5) +@@ -181,15 +185,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) { + } + + // apply exp2 contributions ++ if exp2 < -1e7 || exp2 > 1e7 { ++ return nil, false // avoid excessively large exponents ++ } + if exp2 > 0 { +- if int64(uint(exp2)) != exp2 { +- panic("exponent too large") +- } + z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2)) + } else if exp2 < 0 { +- if int64(uint(-exp2)) != -exp2 { +- panic("exponent too large") +- } + z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2)) + } + +diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go +index ba0d1ba9e1..15d206cb38 100644 +--- a/src/math/big/ratconv_test.go ++++ b/src/math/big/ratconv_test.go +@@ -589,3 +589,28 @@ func TestIssue31184(t *testing.T) { + } + } + } ++ ++func TestIssue45910(t *testing.T) { ++ var x Rat ++ for _, test := range []struct { ++ input string ++ want bool ++ }{ ++ {"1e-1000001", false}, ++ {"1e-1000000", true}, ++ {"1e+1000000", true}, ++ {"1e+1000001", false}, ++ ++ {"0p1000000000000", true}, ++ {"1p-10000001", false}, ++ {"1p-10000000", true}, ++ {"1p+10000000", true}, ++ {"1p+10000001", false}, ++ {"1.770p02041010010011001001", false}, // test case from issue ++ } { ++ _, got := x.SetString(test.input) ++ if got != test.want { ++ t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want) ++ } ++ } ++} +-- +2.27.0 + diff --git a/0050-release-branch.go1.15-crypto-tls-test-key-type-when-.patch b/0050-release-branch.go1.15-crypto-tls-test-key-type-when-.patch new file mode 100644 index 0000000000000000000000000000000000000000..e946b5d0067d3e30d5be1c2f6fab9b2fe06d8e76 --- /dev/null +++ b/0050-release-branch.go1.15-crypto-tls-test-key-type-when-.patch @@ -0,0 +1,53 @@ +From c77980bc077f3774276ab2deba78d8e6bfe4b3bd Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Wed, 9 Jun 2021 11:31:27 -0700 +Subject: [PATCH] [release-branch.go1.15] crypto/tls: test key type when + casting + +When casting the certificate public key in generateClientKeyExchange, +check the type is appropriate. This prevents a panic when a server +agrees to a RSA based key exchange, but then sends an ECDSA (or +other) certificate. + +Updates #47143 +Fixes #47144 +Fixes CVE-2021-34558 + +Thanks to Imre Rad for reporting this issue. + +Change-Id: Iabccacca6052769a605cccefa1216a9f7b7f6aea +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1116723 +Reviewed-by: Filippo Valsorda +Reviewed-by: Katie Hockman +Reviewed-on: https://go-review.googlesource.com/c/go/+/334030 +Trust: Filippo Valsorda +Run-TryBot: Filippo Valsorda +Reviewed-by: Dmitri Shuralyov + +Conflict:NA +Reference:https://github.com/golang/go/commit/c77980bc077f3774276ab2deba78d8e6bfe4b3bd + +--- + src/crypto/tls/key_agreement.go | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go +index 7e6534bd46..22f1b2e1f2 100644 +--- a/src/crypto/tls/key_agreement.go ++++ b/src/crypto/tls/key_agreement.go +@@ -67,7 +67,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello + return nil, nil, err + } + +- encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) ++ rsaKey, ok := cert.PublicKey.(*rsa.PublicKey) ++ if !ok { ++ return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite") ++ } ++ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret) + if err != nil { + return nil, nil, err + } +-- +2.27.0 + diff --git a/0051-net-reject-leading-zeros-in-IP-address-parsers.patch b/0051-net-reject-leading-zeros-in-IP-address-parsers.patch new file mode 100644 index 0000000000000000000000000000000000000000..57c4d064e222bbdd3699c7cc51af59ecedbd6506 --- /dev/null +++ b/0051-net-reject-leading-zeros-in-IP-address-parsers.patch @@ -0,0 +1,124 @@ +From d3e3d03666bbd8784007bbb78a75864aac786967 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Mon, 7 Jun 2021 10:21:29 -0700 +Subject: [PATCH] net: reject leading zeros in IP address parsers + +In both net.ParseIP and net.ParseCIDR reject leading zeros in the +dot-decimal notation of IPv4 addresses. + +Fixes #30999 +Fixes #43389 + +Change-Id: I2b6a31fe84db89ac828cf5ed03eaa586ee96ab68 +Reviewed-on: https://go-review.googlesource.com/c/go/+/325829 +Trust: Roland Shoemaker +Trust: Katie Hockman +Run-TryBot: Roland Shoemaker +Reviewed-by: Filippo Valsorda +Reviewed-by: Katie Hockman +TryBot-Result: Go Bot + +Conflict:NA +Reference:https://github.com/golang/go/commit/d3e3d03666bbd8784007bbb78a75864aac786967 + +--- + src/net/hosts_test.go | 4 ++-- + src/net/ip.go | 4 ++++ + src/net/ip_test.go | 8 ++++++-- + src/net/testdata/ipv4-hosts | 8 ++------ + 5 files changed, 24 insertions(+), 10 deletions(-) + + +diff --git a/src/net/hosts_test.go b/src/net/hosts_test.go +index f850e2fccf..19c43999f9 100644 +--- a/src/net/hosts_test.go ++++ b/src/net/hosts_test.go +@@ -36,7 +36,7 @@ var lookupStaticHostTests = []struct { + }, + }, + { +- "testdata/ipv4-hosts", // see golang.org/issue/8996 ++ "testdata/ipv4-hosts", + []staticHostEntry{ + {"localhost", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}}, + {"localhost.localdomain", []string{"127.0.0.3"}}, +@@ -102,7 +102,7 @@ var lookupStaticAddrTests = []struct { + }, + }, + { +- "testdata/ipv4-hosts", // see golang.org/issue/8996 ++ "testdata/ipv4-hosts", + []staticHostEntry{ + {"127.0.0.1", []string{"localhost"}}, + {"127.0.0.2", []string{"localhost"}}, +diff --git a/src/net/ip.go b/src/net/ip.go +index 0477269761..38e1aa2247 100644 +--- a/src/net/ip.go ++++ b/src/net/ip.go +@@ -574,6 +574,10 @@ func parseIPv4(s string) IP { + if !ok || n > 0xFF { + return nil + } ++ if c > 1 && s[0] == '0' { ++ // Reject non-zero components with leading zeroes. ++ return nil ++ } + s = s[c:] + p[i] = byte(n) + } +diff --git a/src/net/ip_test.go b/src/net/ip_test.go +index 3af5e41ceb..5bbda6024d 100644 +--- a/src/net/ip_test.go ++++ b/src/net/ip_test.go +@@ -21,9 +21,7 @@ var parseIPTests = []struct { + }{ + {"127.0.1.2", IPv4(127, 0, 1, 2)}, + {"127.0.0.1", IPv4(127, 0, 0, 1)}, +- {"127.001.002.003", IPv4(127, 1, 2, 3)}, + {"::ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, +- {"::ffff:127.001.002.003", IPv4(127, 1, 2, 3)}, + {"::ffff:7f01:0203", IPv4(127, 1, 2, 3)}, + {"0:0:0:0:0000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, + {"0:0:0:0:000000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, +@@ -43,6 +41,11 @@ var parseIPTests = []struct { + {"fe80::1%911", nil}, + {"", nil}, + {"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628 ++ {"127.001.002.003", nil}, ++ {"::ffff:127.001.002.003", nil}, ++ {"123.000.000.000", nil}, ++ {"1.2..4", nil}, ++ {"0123.0.0.1", nil}, + } + + func TestParseIP(t *testing.T) { +@@ -358,6 +361,7 @@ var parseCIDRTests = []struct { + {"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}}, + {"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}}, + {"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}}, ++ {"127.000.000.001/32", nil, nil, &ParseError{Type: "CIDR address", Text: "127.000.000.001/32"}}, + {"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}}, + } + +diff --git a/src/net/testdata/ipv4-hosts b/src/net/testdata/ipv4-hosts +index 5208bb44ac..6b99675dfc 100644 +--- a/src/net/testdata/ipv4-hosts ++++ b/src/net/testdata/ipv4-hosts +@@ -1,12 +1,8 @@ + # See https://tools.ietf.org/html/rfc1123. +-# +-# The literal IPv4 address parser in the net package is a relaxed +-# one. It may accept a literal IPv4 address in dotted-decimal notation +-# with leading zeros such as "001.2.003.4". + + # internet address and host name + 127.0.0.1 localhost # inline comment separated by tab +-127.000.000.002 localhost # inline comment separated by space ++127.0.0.2 localhost # inline comment separated by space + + # internet address, host name and aliases +-127.000.000.003 localhost localhost.localdomain ++127.0.0.3 localhost localhost.localdomain +-- +2.27.0 + diff --git a/0052-release-branch.go1.16-misc-wasm-cmd-link-do-not-let-.patch b/0052-release-branch.go1.16-misc-wasm-cmd-link-do-not-let-.patch new file mode 100644 index 0000000000000000000000000000000000000000..cf2d264d5b2bff034474365e4626a7a46dad66c8 --- /dev/null +++ b/0052-release-branch.go1.16-misc-wasm-cmd-link-do-not-let-.patch @@ -0,0 +1,89 @@ +From 4548fcc8dfd933c237f29bba6f90040a85922564 Mon Sep 17 00:00:00 2001 +From: Michael Knyszek +Date: Thu, 2 Sep 2021 16:51:59 -0400 +Subject: [PATCH] [release-branch.go1.16] misc/wasm, cmd/link: do not let + command line args overwrite global data + +On Wasm, wasm_exec.js puts command line arguments at the beginning +of the linear memory (following the "zero page"). Currently there +is no limit for this, and a very long command line can overwrite +the program's data section. Prevent this by limiting the command +line to 4096 bytes, and in the linker ensuring the data section +starts at a high enough address (8192). + +(Arguably our address assignment on Wasm is a bit confusing. This +is the minimum fix I can come up with.) + +Thanks to Ben Lubar for reporting this issue. + +Change by Cherry Mui . + +For #48797 +Fixes #48799 +Fixes CVE-2021-38297 + +Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933 +Reviewed-by: Roland Shoemaker +Reviewed-by: Than McIntosh +Reviewed-on: https://go-review.googlesource.com/c/go/+/354591 +Trust: Michael Knyszek +Reviewed-by: Heschi Kreinick +--- + misc/wasm/wasm_exec.js | 7 +++++++ + src/cmd/link/internal/ld/data.go | 11 ++++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js +index 82041e6bb9..a0a264278b 100644 +--- a/misc/wasm/wasm_exec.js ++++ b/misc/wasm/wasm_exec.js +@@ -564,6 +564,13 @@ + offset += 8; + }); + ++ // The linker guarantees global data starts from at least wasmMinDataAddr. ++ // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. ++ const wasmMinDataAddr = 4096 + 4096; ++ if (offset >= wasmMinDataAddr) { ++ throw new Error("command line too long"); ++ } ++ + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); +diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go +index 52035e9630..54a1d188cd 100644 +--- a/src/cmd/link/internal/ld/data.go ++++ b/src/cmd/link/internal/ld/data.go +@@ -2330,6 +2330,11 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64 + return sect, n, va + } + ++// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js ++// to store command line args. Data sections starts from at least address 8192. ++// Keep in sync with wasm_exec.js. ++const wasmMinDataAddr = 4096 + 4096 ++ + // address assigns virtual addresses to all segments and sections and + // returns all segments in file order. + func (ctxt *Link) address() []*sym.Segment { +@@ -2339,10 +2344,14 @@ func (ctxt *Link) address() []*sym.Segment { + order = append(order, &Segtext) + Segtext.Rwx = 05 + Segtext.Vaddr = va +- for _, s := range Segtext.Sections { ++ for i, s := range Segtext.Sections { + va = uint64(Rnd(int64(va), int64(s.Align))) + s.Vaddr = va + va += s.Length ++ ++ if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr { ++ va = wasmMinDataAddr ++ } + } + + Segtext.Length = va - uint64(*FlagTextAddr) +-- +2.27.0 + diff --git a/0053-net-http-httputil-close-incoming-ReverseProxy-reques.patch b/0053-net-http-httputil-close-incoming-ReverseProxy-reques.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6f58e4b484789c839cf1def9af53a3622051685 --- /dev/null +++ b/0053-net-http-httputil-close-incoming-ReverseProxy-reques.patch @@ -0,0 +1,49 @@ +From b7a85e0003cedb1b48a1fd3ae5b746ec6330102e Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Wed, 7 Jul 2021 16:34:34 -0700 +Subject: [PATCH] net/http/httputil: close incoming ReverseProxy request body + +Reading from an incoming request body after the request handler aborts +with a panic can cause a panic, becuse http.Server does not (contrary +to its documentation) close the request body in this case. + +Always close the incoming request body in ReverseProxy.ServeHTTP to +ensure that any in-flight outgoing requests using the body do not +read from it. + +Updates #46866 +Fixes CVE-2021-36221 + +Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df +Reviewed-on: https://go-review.googlesource.com/c/go/+/333191 +Trust: Damien Neil +Reviewed-by: Brad Fitzpatrick +Reviewed-by: Filippo Valsorda +--- + src/net/http/httputil/reverseproxy.go | 9 +++++ + src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go +index 5d39955d62..8b63368386 100644 +--- a/src/net/http/httputil/reverseproxy.go ++++ b/src/net/http/httputil/reverseproxy.go +@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if req.ContentLength == 0 { + outreq.Body = nil // Issue 16036: nil Body for http.Transport retries + } ++ if outreq.Body != nil { ++ // Reading from the request body after returning from a handler is not ++ // allowed, and the RoundTrip goroutine that reads the Body can outlive ++ // this handler. This can lead to a crash if the handler panics (see ++ // Issue 46866). Although calling Close doesn't guarantee there isn't ++ // any Read in flight after the handle returns, in practice it's safe to ++ // read after closing it. ++ defer outreq.Body.Close() ++ } + if outreq.Header == nil { + outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate + } +-- +2.27.0 + diff --git a/go1.13.15.src.tar.gz b/go1.15.7.src.tar.gz similarity index 67% rename from go1.13.15.src.tar.gz rename to go1.15.7.src.tar.gz index 2b551e218945996fbd6a6ca5354030983e2d87f2..aff1b44d465236814ec342f27071a13e894398a8 100644 Binary files a/go1.13.15.src.tar.gz and b/go1.15.7.src.tar.gz differ diff --git a/golang.spec b/golang.spec index cb0fefbb85cbde4feb4b4ebcd52593eb257e121d..6ec784df4e80863e4a0c3c999f9d9a1bd5b80bfe 100644 --- a/golang.spec +++ b/golang.spec @@ -2,8 +2,8 @@ %global _binaries_in_noarch_packages_terminate_build 0 %global golibdir %{_libdir}/golang %global goroot /usr/lib/%{name} -%global go_api 1.13 -%global go_version 1.13 +%global go_api 1.15 +%global go_version 1.15 %global __spec_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot /usr/lib/rpm/brp-compress %global __requires_exclude_from ^(%{_datadir}|/usr/lib)/%{name}/(doc|src)/.*$ %global __strip /bin/true @@ -61,8 +61,8 @@ %endif Name: golang -Version: 1.13.15 -Release: 2 +Version: 1.15.7 +Release: 5 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -149,22 +149,59 @@ Obsoletes: %{name}-vim < 1.4 Obsoletes: emacs-%{name} < 1.4 Requires: openEuler-rpm-config -Patch6002: 0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch -Patch6003: 0003-golang-delete-pem-files.patch -Patch6004: 0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch -Patch6005: 0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch -Patch6006: 0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch -Patch6007: 0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch -Patch6008: 0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch -Patch6013: 0013-drop-hard-code-cert.patch -Patch6019: 0019-net-http-cgi-net-http-fcgi-add-Content-Type-detectio.patch -Patch6020: 0020-golang-fix-CVE-2020-28366.patch -Patch6021: 0021-golang-fix-CVE-2020-28367.patch -Patch6022: 0022-fix-CVE-2020-29509-CVE-2020-29511.patch -Patch6023: 0023-fix-CVE-2020-29510.patch - ExclusiveArch: %{golang_arches} +Patch6001: 0001-release-branch.go1.15-doc-go1.15-mention-1.15.3-cgo-.patch +Patch6002: 0002-release-branch.go1.15-cmd-go-fix-mod_get_fallback-te.patch +Patch6003: 0003-release-branch.go1.15-internal-execabs-only-run-test.patch +Patch6004: 0004-release-branch.go1.15-cmd-compile-don-t-short-circui.patch +Patch6005: 0005-release-branch.go1.15-cmd-go-fix-get_update_unknown_.patch +Patch6006: 0006-release-branch.go1.15-net-http-update-bundled-x-net-.patch +Patch6007: 0007-release-branch.go1.15-cmd-go-don-t-lookup-the-path-f.patch +Patch6008: 0008-release-branch.go1.15-cmd-link-internal-ld-pe-fix-se.patch +Patch6009: 0009-release-branch.go1.15-cmd-internal-goobj2-fix-buglet.patch +Patch6010: 0010-release-branch.go1.15-runtime-don-t-adjust-timer-pp-.patch +Patch6011: 0011-release-branch.go1.15-runtime-cgo-fix-Android-build-.patch +Patch6013: 0013-release-branch.go1.15-internal-poll-if-copy_file_ran.patch +Patch6014: 0014-release-branch.go1.15-internal-poll-netpollcheckerr-.patch +Patch6015: 0015-release-branch.go1.15-cmd-compile-do-not-assume-TST-.patch +Patch6016: 0016-release-branch.go1.15-syscall-do-not-overflow-key-me.patch +Patch6017: 0017-release-branch.go1.15-time-correct-unusual-extension.patch +Patch6018: 0018-release-branch.go1.15-cmd-compile-fix-escape-analysi.patch +Patch6019: 0019-release-branch.go1.15-net-http-ignore-connection-clo.patch +Patch6020: 0020-release-branch.go1.15-net-http-add-connections-back-.patch +Patch6021: 0021-release-branch.go1.15-security-encoding-xml-prevent-.patch +Patch6023: 0023-release-branch.go1.15-cmd-go-don-t-report-missing-st.patch +Patch6025: 0025-release-branch.go1.15-cmd-go-internal-modfetch-detec.patch +Patch6026: 0026-release-branch.go1.15-cmd-link-generate-trampoline-f.patch +Patch6027: 0027-release-branch.go1.15-net-http-update-bundled-x-net-.patch +Patch6028: 0028-release-branch.go1.15-net-http-fix-detection-of-Roun.patch +Patch6029: 0029-release-branch.go1.15-build-set-GOPATH-consistently-.patch +Patch6030: 0030-release-branch.go1.15-database-sql-fix-tx-stmt-deadl.patch +Patch6031: 0031-release-branch.go1.15-cmd-compile-disable-shortcircu.patch +Patch6032: 0032-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch +Patch6033: 0033-release-branch.go1.15-cmd-cgo-avoid-exporting-all-sy.patch +Patch6034: 0034-release-branch.go1.15-cmd-link-avoid-exporting-all-s.patch +Patch6035: 0035-release-branch.go1.15-cmd-cgo-remove-unnecessary-spa.patch +Patch6037: 0037-release-branch.go1.15-time-use-offset-and-isDST-when.patch +Patch6038: 0038-release-branch.go1.15-std-update-golang.org-x-net-to.patch +Patch6039: 0039-release-branch.go1.15-runtime-time-disable-preemptio.patch +Patch6040: 0040-release-branch.go1.15-runtime-non-strict-InlTreeInde.patch +Patch6041: 0041-release-branch.go1.15-runtime-pprof-skip-tests-for-A.patch +Patch6043: 0043-release-branch.go1.15-math-big-fix-TestShiftOverlap-.patch +Patch6044: 0044-release-branch.go1.15-math-big-remove-the-s390x-asse.patch +Patch6045: 0045-net-http-fix-hijack-hang-at-abortPendingRead.patch +Patch6046: 0046-release-branch.go1.15-net-verify-results-from-Lookup.patch +Patch6047: 0047-release-branch.go1.15-archive-zip-only-preallocate-F.patch +Patch6048: 0048-release-branch.go1.15-net-http-httputil-always-remov.patch +Patch6049: 0049-release-branch.go1.15-math-big-check-for-excessive-e.patch +Patch6050: 0050-release-branch.go1.15-crypto-tls-test-key-type-when-.patch +Patch6051: 0051-net-reject-leading-zeros-in-IP-address-parsers.patch +Patch6052: 0052-release-branch.go1.16-misc-wasm-cmd-link-do-not-let-.patch +Patch6053: 0053-net-http-httputil-close-incoming-ReverseProxy-reques.patch + +Patch9001: 0001-drop-hard-code-cert.patch + %description %{summary}. @@ -356,7 +393,7 @@ export GO_TEST_TIMEOUT_SCALE=2 %if %{fail_on_tests} echo tests ignored %else -./run.bash --no-rebuild -v -v -v -k || : +./run.bash --no-rebuild -v -v -v -k go_test:testing || : %endif cd .. @@ -395,6 +432,21 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Wed Oct 27 2021 chenjiankun - 1.15.7-5 +- fix CVE-2021-33195,CVE-2021-33196,CVE-2021-33197,CVE-2021-33198,CVE-2021-34558,CVE-2021-29923,CVE-2021-38297,CVE-2021-36221 + +* Fri Jun 18 2021 chenjiankun - 1.15.7-4 +- batch synchronization + +* Fri Apr 23 2021 chenjiankun - 1.15.7-3 +- fix CVE-2021-27918 + +* Thu Apr 15 2021 lixiang - 1.15.7-2 +- speed up build progress + +* Thu Jan 28 2021 xingweizheng - 1.15.7-1 +- upgrade to 1.15.7 + * Mon Jan 18 2021 jingrui - 1.13.15-2 - sync cve fix