From 8144f1dc261315004f12bd7cf1e8c043d74965a6 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 8 Jun 2021 15:33:54 +0200 Subject: [release-branch.go1.16] testing: drop unusual characters from TempDir directory name Only use safe characters of the test name for the os.MkdirTemp pattern. This currently includes the alphanumeric characters and ASCII punctuation characters known not to interact with globs. For #46624 Fixes #50645 Change-Id: I402c34775b943fed9b97963c52f79245cc16dc1d Reviewed-on: https://go-review.googlesource.com/c/go/+/326010 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Ian Lance Taylor (cherry picked from commit 97cee43c93cfccded197cd281f0a5885cdb605b4) Reviewed-on: https://go-review.googlesource.com/c/go/+/378914 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Tobias Klauser --- src/testing/testing.go | 34 ++++++++++++++++++++++------------ src/testing/testing_test.go | 10 +++++++++- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index dec39d24da..a53d5745cb 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -251,6 +251,8 @@ import ( "sync" "sync/atomic" "time" + "unicode" + "unicode/utf8" ) var initRan bool @@ -906,11 +908,6 @@ func (c *common) Cleanup(f func()) { c.cleanups = append(c.cleanups, fn) } -var tempDirReplacer struct { - sync.Once - r *strings.Replacer -} - // TempDir returns a temporary directory for the test to use. // The directory is automatically removed by Cleanup when the test and // all its subtests complete. @@ -934,13 +931,26 @@ func (c *common) TempDir() string { if nonExistent { c.Helper() - // os.MkdirTemp doesn't like path separators in its pattern, - // so mangle the name to accommodate subtests. - tempDirReplacer.Do(func() { - tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_") - }) - pattern := tempDirReplacer.r.Replace(c.Name()) - + // Drop unusual characters (such as path separators or + // characters interacting with globs) from the directory name to + // avoid surprising os.MkdirTemp behavior. + mapper := func(r rune) rune { + if r < utf8.RuneSelf { + const allowed = "!#$%&()+,-.=@^_{}~ " + if '0' <= r && r <= '9' || + 'a' <= r && r <= 'z' || + 'A' <= r && r <= 'Z' { + return r + } + if strings.ContainsRune(allowed, r) { + return r + } + } else if unicode.IsLetter(r) || unicode.IsNumber(r) { + return r + } + return -1 + } + pattern := strings.Map(mapper, c.Name()) c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern) if c.tempDirErr == nil { c.Cleanup(func() { diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go index 0f096980ca..42058ae449 100644 --- a/src/testing/testing_test.go +++ b/src/testing/testing_test.go @@ -58,6 +58,9 @@ func TestTempDir(t *testing.T) { t.Run("test:subtest", testTempDir) t.Run("test/..", testTempDir) t.Run("../test", testTempDir) + t.Run("test[]", testTempDir) + t.Run("test*", testTempDir) + t.Run("äöüéè", testTempDir) } func testTempDir(t *testing.T) { @@ -74,7 +77,7 @@ func testTempDir(t *testing.T) { if err != nil { t.Fatal(err) } - t.Errorf("directory %q stil exists: %v, isDir=%v", dir, fi, fi.IsDir()) + t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir()) default: if !t.Failed() { t.Fatal("never received dir channel") @@ -108,4 +111,9 @@ func testTempDir(t *testing.T) { if len(files) > 0 { t.Errorf("unexpected %d files in TempDir: %v", len(files), files) } + + glob := filepath.Join(dir, "*.txt") + if _, err := filepath.Glob(glob); err != nil { + t.Error(err) + } } -- cgit v1.2.3-54-g00ecf From 57d5d8f98748d0c3f47d44898acaa019c548ffc1 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 4 Oct 2021 10:20:22 -0700 Subject: [release-branch.go1.16] net/http/internal: use FIPS-compliant certificate Upgrade the test certificate from RSA 1024 (not FIPS-approved) to RSA 2048 (FIPS-approved), allowing tests to pass when the dev.boringcrypto branch FIPS-only mode is enabled. For #48674. Fixes #50585. Change-Id: I613d2f8d0207bf3683fd0df256bf0167604996c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353869 Trust: Damien Neil Run-TryBot: Damien Neil Reviewed-by: Filippo Valsorda (cherry picked from commit 90860e0c3110ac5898dfe8e0e0fafd0aea8d979a) Reviewed-on: https://go-review.googlesource.com/c/go/+/380997 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Gopher Robot --- src/net/http/internal/testcert.go | 69 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/net/http/internal/testcert.go b/src/net/http/internal/testcert.go index 2284a836fb..e1bdbe16e1 100644 --- a/src/net/http/internal/testcert.go +++ b/src/net/http/internal/testcert.go @@ -9,37 +9,56 @@ import "strings" // LocalhostCert is a PEM-encoded TLS cert with SAN IPs // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. // generated from src/crypto/tls: -// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h +// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- -MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS +MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 -iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul -rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO -BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw -AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA -AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 -tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs -h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM -fblo6RBxUQ== +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r +bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U +aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P +YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk +POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu +h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE +AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv +bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI +5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv +cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 ++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B +grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK +5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ +WkBKOclmOV2xlTVuPw== -----END CERTIFICATE-----`) // LocalhostKey is the private key for localhostCert. var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- -MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9 -SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB -l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB -AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet -3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb -uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H -qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp -jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY -fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U -fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU -y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX -qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo -f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA== +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi +4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS +gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW +URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX +AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy +VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK +x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk +lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL +dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89 +EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq +XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki +6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O +3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s +uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ +Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ +w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo ++bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP +OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA +brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv +m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y +LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN +/3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN +s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ +Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0 +xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/ +ZboOWVe3icTy64BT3OQhmg== -----END RSA TESTING KEY-----`)) func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } -- cgit v1.2.3-54-g00ecf From 6cbcf581aff555d09d91ae1b3b360511ebb7e35f Mon Sep 17 00:00:00 2001 From: "Daniel S. Fava" Date: Fri, 12 Feb 2021 09:54:50 +0100 Subject: [release-branch.go1.16] testing/race: fixing intermittent test failure Test NoRaceMutexPureHappensBefore in runtime/race/testdata/mutex_test.go expects the second spawned goroutine to run after the first. The test attempts to force this scheduling with a 10 millisecond wait. Following a suggestion by Bryan Mills, we force this scheduling using a shared variable whose access take place within the existing mutex. Fixes #50832. Updates #35745. Change-Id: Ib23ec51492ecfeed4752e020401dd25755a669ed Reviewed-on: https://go-review.googlesource.com/c/go/+/291292 Reviewed-by: Bryan C. Mills Reviewed-by: Dmitry Vyukov Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot (cherry picked from commit aaed6cbced238030053df4e54f676a1d59df89d7) Reviewed-on: https://go-review.googlesource.com/c/go/+/381034 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov --- src/runtime/race/testdata/mutex_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/runtime/race/testdata/mutex_test.go b/src/runtime/race/testdata/mutex_test.go index cbed2d370c..9dbed9a2c9 100644 --- a/src/runtime/race/testdata/mutex_test.go +++ b/src/runtime/race/testdata/mutex_test.go @@ -78,16 +78,23 @@ func TestNoRaceMutexPureHappensBefore(t *testing.T) { var mu sync.Mutex var x int16 = 0 _ = x + written := false ch := make(chan bool, 2) go func() { x = 1 mu.Lock() + written = true mu.Unlock() ch <- true }() go func() { - <-time.After(1e5) + time.Sleep(100 * time.Microsecond) mu.Lock() + for !written { + mu.Unlock() + time.Sleep(100 * time.Microsecond) + mu.Lock() + } mu.Unlock() x = 1 ch <- true -- cgit v1.2.3-54-g00ecf From 07ee9e6445057e181fb3895df978748ffef30327 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 19 Jan 2022 16:54:41 -0500 Subject: [release-branch.go1.16] math/big: prevent overflow in (*Rat).SetString Credit to rsc@ for the original patch. Thanks to the OSS-Fuzz project for discovering this issue and to Emmanuel Odeke (@odeke_et) for reporting it. Updates #50699 Fixes #50700 Fixes CVE-2022-23772 Change-Id: I590395a3d55689625390cf1e58f5f40623b26ee5 Reviewed-on: https://go-review.googlesource.com/c/go/+/379537 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Gopher Robot Reviewed-by: Emmanuel Odeke Reviewed-by: Roland Shoemaker Reviewed-by: Julie Qiu (cherry picked from commit ad345c265916bbf6c646865e4642eafce6d39e78) Reviewed-on: https://go-review.googlesource.com/c/go/+/381337 --- src/math/big/ratconv.go | 5 +++++ src/math/big/ratconv_test.go | 1 + 2 files changed, 6 insertions(+) diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go index ac3c8bd11f..90053a9c81 100644 --- a/src/math/big/ratconv.go +++ b/src/math/big/ratconv.go @@ -169,6 +169,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) { n := exp5 if n < 0 { n = -n + if n < 0 { + // This can occur if -n overflows. -(-1 << 63) would become + // -1 << 63, which is still negative. + return nil, false + } } if n > 1e6 { return nil, false // avoid excessively large exponents diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go index 15d206cb38..e55e655718 100644 --- a/src/math/big/ratconv_test.go +++ b/src/math/big/ratconv_test.go @@ -104,6 +104,7 @@ var setStringTests = []StringTest{ {in: "4/3/"}, {in: "4/3."}, {in: "4/"}, + {in: "13e-9223372036854775808"}, // CVE-2022-23772 // valid {"0", "0", true}, -- cgit v1.2.3-54-g00ecf From 355915ba9105cad1b0300de1ff1ef30ee643379c Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 15 Nov 2021 10:14:04 +0100 Subject: [release-branch.go1.16] debug/pe,debug/macho: add support for DWARF5 sections Adds the same logic used in debug/elf to load DWARF5 sections. For #49590 Fixes #50721 Change-Id: Iee05b9927a6f521842b330eab8942ade3fc2bd86 Reviewed-on: https://go-review.googlesource.com/c/go/+/363895 Reviewed-by: Ian Lance Taylor Trust: Than McIntosh (cherry picked from commit 6c36c332fefdd433cfe6e6468a2542fc310e9f8a) Reviewed-on: https://go-review.googlesource.com/c/go/+/379915 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Alessandro Arzilli Reviewed-by: Emmanuel Odeke --- src/debug/macho/file.go | 14 +++++++++++--- src/debug/pe/file.go | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index 73cfce3c76..cdc500e476 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -650,10 +650,14 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - // Look for DWARF4 .debug_types sections. + // Look for DWARF4 .debug_types sections and DWARF5 sections. for i, s := range f.Sections { suffix := dwarfSuffix(s) - if suffix != "types" { + if suffix == "" { + continue + } + if _, ok := dat[suffix]; ok { + // Already handled. continue } @@ -662,7 +666,11 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if suffix == "types" { + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + } else { + err = d.AddSection(".debug_"+suffix, b) + } if err != nil { return nil, err } diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go index 7d763fff19..7987730858 100644 --- a/src/debug/pe/file.go +++ b/src/debug/pe/file.go @@ -267,10 +267,14 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - // Look for DWARF4 .debug_types sections. + // Look for DWARF4 .debug_types sections and DWARF5 sections. for i, s := range f.Sections { suffix := dwarfSuffix(s) - if suffix != "types" { + if suffix == "" { + continue + } + if _, ok := dat[suffix]; ok { + // Already handled. continue } @@ -279,7 +283,11 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if suffix == "types" { + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + } else { + err = d.AddSection(".debug_"+suffix, b) + } if err != nil { return nil, err } -- cgit v1.2.3-54-g00ecf From 0a15110f0851542732e2e0fa10fcc2114c306c7a Mon Sep 17 00:00:00 2001 From: Ethan Anderson Date: Tue, 14 Dec 2021 10:59:06 -0600 Subject: [release-branch.go1.16] cmd/go: remove mercurial from bitbucket vcs options Mercurial was deprecated as of July 1, 2020 as per https://bitbucket.org/blog/sunsetting-mercurial-support-in-bitbucket Fixes #50811. Updates #50810. Change-Id: I0d40f84aaa393905cae7c4bed8919b15de9a5f6d Reviewed-on: https://go-review.googlesource.com/c/go/+/371720 Trust: Russ Cox Reviewed-by: Bryan Mills Trust: Bryan Mills (cherry picked from commit 5b1b80beb1a2a9a353738e80777d1e25cfdfa095) Reviewed-on: https://go-review.googlesource.com/c/go/+/380998 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- src/cmd/go/internal/vcs/vcs.go | 54 ++----------------------------------- src/cmd/go/internal/vcs/vcs_test.go | 7 +++++ 2 files changed, 9 insertions(+), 52 deletions(-) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 9feffe0765..ecc42262de 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -5,7 +5,6 @@ package vcs import ( - "encoding/json" "errors" "fmt" exec "internal/execabs" @@ -1189,8 +1188,9 @@ var vcsPaths = []*vcsPath{ { pathPrefix: "bitbucket.org", regexp: lazyregexp.New(`^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`), + vcs: "git", repo: "https://{root}", - check: bitbucketVCS, + check: noVCSSuffix, }, // IBM DevOps Services (JazzHub) @@ -1262,56 +1262,6 @@ func noVCSSuffix(match map[string]string) error { return nil } -// bitbucketVCS determines the version control system for a -// Bitbucket repository, by using the Bitbucket API. -func bitbucketVCS(match map[string]string) error { - if err := noVCSSuffix(match); err != nil { - return err - } - - var resp struct { - SCM string `json:"scm"` - } - url := &urlpkg.URL{ - Scheme: "https", - Host: "api.bitbucket.org", - Path: expand(match, "/2.0/repositories/{bitname}"), - RawQuery: "fields=scm", - } - data, err := web.GetBytes(url) - if err != nil { - if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 { - // this may be a private repository. If so, attempt to determine which - // VCS it uses. See issue 5375. - root := match["root"] - for _, vcs := range []string{"git", "hg"} { - if vcsByCmd(vcs).Ping("https", root) == nil { - resp.SCM = vcs - break - } - } - } - - if resp.SCM == "" { - return err - } - } else { - if err := json.Unmarshal(data, &resp); err != nil { - return fmt.Errorf("decoding %s: %v", url, err) - } - } - - if vcsByCmd(resp.SCM) != nil { - match["vcs"] = resp.SCM - if resp.SCM == "git" { - match["repo"] += ".git" - } - return nil - } - - return fmt.Errorf("unable to detect version control system for bitbucket.org/ path") -} - // launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case, // "foo" could be a series name registered in Launchpad with its own branch, // and it could also be the name of a directory within the main project diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index c5c7a3283b..a4fec3f8f8 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -183,6 +183,13 @@ func TestRepoRootForImportPath(t *testing.T) { "chiselapp.com/user/kyle/fossilgg", nil, }, + { + "bitbucket.org/workspace/pkgname", + &RepoRoot{ + VCS: vcsGit, + Repo: "https://bitbucket.org/workspace/pkgname", + }, + }, } for _, test := range tests { -- cgit v1.2.3-54-g00ecf From fcd482a2d014137d8c20bf02bcc8fe37b107eb8c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 18 Jan 2022 18:36:00 -0500 Subject: [release-branch.go1.16] cmd/compile: don't elide extension for LoadReg to FP register on MIPS64 For an extension operation like MOVWreg, if the operand is already extended, we optimize the second extension out. Usually a LoadReg of a proper type would come already extended, as a MOVW/MOVWU etc. instruction does. But for a LoadReg to a floating point register, the instruction does not do the extension. So we cannot elide the extension. Updates #50671. Fixes #50682. Change-Id: Id8991df78d5acdecd3fd6138c558428cbd5f6ba3 Reviewed-on: https://go-review.googlesource.com/c/go/+/379236 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: David Chase (cherry picked from commit d93ff73ae207763871bee38590242be968b2e743) Reviewed-on: https://go-review.googlesource.com/c/go/+/379515 --- src/cmd/compile/internal/mips64/ssa.go | 5 ++++- test/fixedbugs/issue50671.go | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue50671.go diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index 2727c4d8a8..b0e0165ad8 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -321,7 +321,10 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPS64MOVVreg { a = a.Args[0] } - if a.Op == ssa.OpLoadReg { + if a.Op == ssa.OpLoadReg && mips.REG_R0 <= a.Reg() && a.Reg() <= mips.REG_R31 { + // LoadReg from a narrower type does an extension, except loading + // to a floating point register. So only eliminate the extension + // if it is loaded to an integer register. t := a.Type switch { case v.Op == ssa.OpMIPS64MOVBreg && t.Size() == 1 && t.IsSigned(), diff --git a/test/fixedbugs/issue50671.go b/test/fixedbugs/issue50671.go new file mode 100644 index 0000000000..9f4742bfcd --- /dev/null +++ b/test/fixedbugs/issue50671.go @@ -0,0 +1,35 @@ +// run + +// Copyright 2022 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. + +// Issue 50671: sign extension eliminated incorrectly on MIPS64. + +package main + +//go:noinline +func F(x int32) (float64, int64) { + a := float64(x) + b := int64(x) + return a, b +} + +var a, b, c float64 + +// Poison some floating point registers with non-zero high bits. +// +//go:noinline +func poison(x float64) { + a = x - 123.45 + b = a * 1.2 + c = b + 3.4 +} + +func main() { + poison(333.3) + _, b := F(123) + if b != 123 { + panic("FAIL") + } +} -- cgit v1.2.3-54-g00ecf From 4d284ea05230c37a653053c163f0eb8b1f9b6138 Mon Sep 17 00:00:00 2001 From: David Chase Date: Thu, 27 Jan 2022 11:26:59 -0500 Subject: [release-branch.go1.16] cmd/compile: remove incorrect arm,arm64 CMP->CMN transformations These can go wrong when one of the operands is the minimum integer value. Fixes #50866. Change-Id: I238fe284f60c7ee5aeb9dc9a18e8b1578cdb77d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/381318 Reviewed-by: Keith Randall Reviewed-by: Cherry Mui Trust: David Chase Run-TryBot: David Chase TryBot-Result: Gopher Robot (cherry picked from commit b7b44b3173f151a2313da7072afd25de80511605) Reviewed-on: https://go-review.googlesource.com/c/go/+/381475 Trust: Michael Knyszek Run-TryBot: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM.rules | 4 +- src/cmd/compile/internal/ssa/gen/ARM64.rules | 10 +- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 4 +- src/cmd/compile/internal/ssa/gen/ARMOps.go | 2 +- src/cmd/compile/internal/ssa/rewriteARM.go | 144 ------------------------ src/cmd/compile/internal/ssa/rewriteARM64.go | 160 --------------------------- test/fixedbugs/issue50854.go | 38 +++++++ 7 files changed, 45 insertions(+), 317 deletions(-) create mode 100644 test/fixedbugs/issue50854.go diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index 69989b0c45..2a30f9c342 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -1263,8 +1263,8 @@ (SRLconst (SLLconst x [c]) [d]) && objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x) // comparison simplification -((LT|LE|EQ|NE|GE|GT) (CMP x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMN x y)) // sense of carry bit not preserved -((LT|LE|EQ|NE|GE|GT) (CMN x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMP x y)) // sense of carry bit not preserved +((EQ|NE) (CMP x (RSBconst [0] y))) => ((EQ|NE) (CMN x y)) // sense of carry bit not preserved; see also #50854 +((EQ|NE) (CMN x (RSBconst [0] y))) => ((EQ|NE) (CMP x y)) // sense of carry bit not preserved; see also #50864 (EQ (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (EQ (CMP x y) yes no) (EQ (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (EQ (CMP a (MUL x y)) yes no) (EQ (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (EQ (CMPconst [c] x) yes no) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 80b4005df1..3c66494ab5 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -643,19 +643,13 @@ (GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GTnoov (CMNW x y) yes no) (GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GEnoov (CMNW x y) yes no) +// CMP(x,-y) -> CMN(x,y) is only valid for unordered comparison, if y can be -1<<63 (EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no) (NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no) -(LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMN x y) yes no) -(LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMN x y) yes no) -(GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMN x y) yes no) -(GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMN x y) yes no) +// CMPW(x,-y) -> CMNW(x,y) is only valid for unordered comparison, if y can be -1<<31 (EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no) (NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no) -(LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMNW x y) yes no) -(LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMNW x y) yes no) -(GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMNW x y) yes no) -(GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMNW x y) yes no) (EQ (CMPconst [0] x) yes no) => (Z x yes no) (NE (CMPconst [0] x) yes no) => (NZ x yes no) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 4d1d14e18b..fc3dcce629 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -281,9 +281,9 @@ func init() { {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to auxInt {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1, 32 bit {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt, 32 bit - {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1 + {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63 {name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // arg0 compare to -auxInt - {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit + {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit, provided arg1 is not 1<<31 {name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt, 32 bit {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0 {name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"}, // arg0 & auxInt compare to 0 diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index 1a7eefa50a..7516c4ffe9 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -329,7 +329,7 @@ func init() { // comparisons {name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1 {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt - {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1 + {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63 {name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0 {name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0 diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 1f25005eb7..8da5b40cf5 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -17123,42 +17123,6 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMLE, cmp) return true } - // match: (GE (CMP x (RSBconst [0] y))) - // result: (GE (CMN x y)) - for b.Controls[0].Op == OpARMCMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - v_0_1 := v_0.Args[1] - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - break - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) - return true - } - // match: (GE (CMN x (RSBconst [0] y))) - // result: (GE (CMP x y)) - for b.Controls[0].Op == OpARMCMN { - v_0 := b.Controls[0] - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - x := v_0_0 - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - continue - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) - return true - } - break - } // match: (GE (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 // result: (GEnoov (CMP x y) yes no) @@ -18039,42 +18003,6 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMLT, cmp) return true } - // match: (GT (CMP x (RSBconst [0] y))) - // result: (GT (CMN x y)) - for b.Controls[0].Op == OpARMCMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - v_0_1 := v_0.Args[1] - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - break - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) - return true - } - // match: (GT (CMN x (RSBconst [0] y))) - // result: (GT (CMP x y)) - for b.Controls[0].Op == OpARMCMN { - v_0 := b.Controls[0] - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - x := v_0_0 - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - continue - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) - return true - } - break - } // match: (GT (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 // result: (GTnoov (CMP x y) yes no) @@ -19046,42 +18974,6 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGE, cmp) return true } - // match: (LE (CMP x (RSBconst [0] y))) - // result: (LE (CMN x y)) - for b.Controls[0].Op == OpARMCMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - v_0_1 := v_0.Args[1] - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - break - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) - return true - } - // match: (LE (CMN x (RSBconst [0] y))) - // result: (LE (CMP x y)) - for b.Controls[0].Op == OpARMCMN { - v_0 := b.Controls[0] - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - x := v_0_0 - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - continue - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) - return true - } - break - } // match: (LE (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 // result: (LEnoov (CMP x y) yes no) @@ -19962,42 +19854,6 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGT, cmp) return true } - // match: (LT (CMP x (RSBconst [0] y))) - // result: (LT (CMN x y)) - for b.Controls[0].Op == OpARMCMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - v_0_1 := v_0.Args[1] - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - break - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) - return true - } - // match: (LT (CMN x (RSBconst [0] y))) - // result: (LT (CMP x y)) - for b.Controls[0].Op == OpARMCMN { - v_0 := b.Controls[0] - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - x := v_0_0 - if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 { - continue - } - y := v_0_1.Args[0] - v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) - return true - } - break - } // match: (LT (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 // result: (LTnoov (CMP x y) yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index e61d89992d..5afccf163d 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -26214,46 +26214,6 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (GE (CMP x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (GE (CMN x y) yes no) - for b.Controls[0].Op == OpARM64CMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64GE, v0) - return true - } - // match: (GE (CMPW x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (GE (CMNW x y) yes no) - for b.Controls[0].Op == OpARM64CMPW { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64GE, v0) - return true - } // match: (GE (CMPconst [0] z:(MADD a x y)) yes no) // cond: z.Uses==1 // result: (GEnoov (CMN a (MUL x y)) yes no) @@ -26650,46 +26610,6 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (GT (CMP x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (GT (CMN x y) yes no) - for b.Controls[0].Op == OpARM64CMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64GT, v0) - return true - } - // match: (GT (CMPW x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (GT (CMNW x y) yes no) - for b.Controls[0].Op == OpARM64CMPW { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64GT, v0) - return true - } // match: (GT (CMPconst [0] z:(MADD a x y)) yes no) // cond: z.Uses==1 // result: (GTnoov (CMN a (MUL x y)) yes no) @@ -27182,46 +27102,6 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (LE (CMP x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (LE (CMN x y) yes no) - for b.Controls[0].Op == OpARM64CMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64LE, v0) - return true - } - // match: (LE (CMPW x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (LE (CMNW x y) yes no) - for b.Controls[0].Op == OpARM64CMPW { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64LE, v0) - return true - } // match: (LE (CMPconst [0] z:(MADD a x y)) yes no) // cond: z.Uses==1 // result: (LEnoov (CMN a (MUL x y)) yes no) @@ -27594,46 +27474,6 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (LT (CMP x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (LT (CMN x y) yes no) - for b.Controls[0].Op == OpARM64CMP { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64LT, v0) - return true - } - // match: (LT (CMPW x z:(NEG y)) yes no) - // cond: z.Uses == 1 - // result: (LT (CMNW x y) yes no) - for b.Controls[0].Op == OpARM64CMPW { - v_0 := b.Controls[0] - _ = v_0.Args[1] - x := v_0.Args[0] - z := v_0.Args[1] - if z.Op != OpARM64NEG { - break - } - y := z.Args[0] - if !(z.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARM64LT, v0) - return true - } // match: (LT (CMPconst [0] z:(MADD a x y)) yes no) // cond: z.Uses==1 // result: (LTnoov (CMN a (MUL x y)) yes no) diff --git a/test/fixedbugs/issue50854.go b/test/fixedbugs/issue50854.go new file mode 100644 index 0000000000..a5be9195f1 --- /dev/null +++ b/test/fixedbugs/issue50854.go @@ -0,0 +1,38 @@ +// run + +// Copyright 2022 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 + +// This checks for incorrect application of CMP(-x,y) -> CMN(x,y) in arm and arm64 + +//go:noinline +func f(p int64, x, y int64) bool { return -x <= p && p <= y } + +//go:noinline +func g(p int32, x, y int32) bool { return -x <= p && p <= y } + +// There are some more complicated patterns involving compares and shifts, try to trigger those. + +//go:noinline +func h(p int64, x, y int64) bool { return -(x<<1) <= p && p <= y } + +//go:noinline +func k(p int32, x, y int32) bool { return -(1< Date: Thu, 13 Jan 2022 15:38:14 -0500 Subject: [release-branch.go1.16] cmd/go/internal/modfetch: do not short-circuit canonical versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since at least CL 121857, the conversion logic in (*modfetch).codeRepo.Stat has had a short-circuit to use the version requested by the caller if it successfully resolves and is already canonical. However, we should not use that version if it refers to a branch instead of a tag, because branches (unlike tags) usually do not refer to a single, stable release: a branch named "v1.0.0" may be for the development of the v1.0.0 release, or for the development of patches based on v1.0.0, but only one commit (perhaps at the end of that branch — but possibly not even written yet!) can be that specific version. We already have some logic to prefer tags that are semver-equivalent to the version requested by the caller. That more general case suffices for exact equality too — so we can eliminate the special-case, fixing the bug and (happily!) also somewhat simplifying the code. Updates #35671 Fixes #50686 Fixes CVE-2022-23773 Change-Id: I2fd290190b8a99a580deec7e26d15659b58a50b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/378400 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Russ Cox TryBot-Result: Gopher Robot (cherry picked from commit fa4d9b8e2bc2612960c80474fca83a4c85a974eb) Reviewed-on: https://go-review.googlesource.com/c/go/+/382839 --- src/cmd/go/internal/modfetch/coderepo.go | 216 +++++++-------- src/cmd/go/internal/modfetch/coderepo_test.go | 301 ++++++++++++--------- src/cmd/go/testdata/script/mod_invalid_version.txt | 10 +- 3 files changed, 277 insertions(+), 250 deletions(-) diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index 2dcbb99b18..db7496faf6 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -298,16 +298,13 @@ func (r *codeRepo) Latest() (*RevInfo, error) { // If statVers is a valid module version, it is used for the Version field. // Otherwise, the Version is derived from the passed-in info and recent tags. func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) { - info2 := &RevInfo{ - Name: info.Name, - Short: info.Short, - Time: info.Time, - } - // If this is a plain tag (no dir/ prefix) // and the module path is unversioned, // and if the underlying file tree has no go.mod, // then allow using the tag with a +incompatible suffix. + // + // (If the version is +incompatible, then the go.mod file must not exist: + // +incompatible is not an ongoing opt-out from semantic import versioning.) var canUseIncompatible func() bool canUseIncompatible = func() bool { var ok bool @@ -321,19 +318,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e return ok } - invalidf := func(format string, args ...interface{}) error { - return &module.ModuleError{ - Path: r.modPath, - Err: &module.InvalidVersionError{ - Version: info2.Version, - Err: fmt.Errorf(format, args...), - }, - } - } - - // checkGoMod verifies that the go.mod file for the module exists or does not - // exist as required by info2.Version and the module path represented by r. - checkGoMod := func() (*RevInfo, error) { + // checkCanonical verifies that the canonical version v is compatible with the + // module path represented by r, adding a "+incompatible" suffix if needed. + // + // If statVers is also canonical, checkCanonical also verifies that v is + // either statVers or statVers with the added "+incompatible" suffix. + checkCanonical := func(v string) (*RevInfo, error) { // If r.codeDir is non-empty, then the go.mod file must exist: the module // author — not the module consumer, — gets to decide how to carve up the repo // into modules. @@ -344,73 +334,91 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e // r.findDir verifies both of these conditions. Execute it now so that // r.Stat will correctly return a notExistError if the go.mod location or // declared module path doesn't match. - _, _, _, err := r.findDir(info2.Version) + _, _, _, err := r.findDir(v) if err != nil { // TODO: It would be nice to return an error like "not a module". // Right now we return "missing go.mod", which is a little confusing. return nil, &module.ModuleError{ Path: r.modPath, Err: &module.InvalidVersionError{ - Version: info2.Version, + Version: v, Err: notExistError{err: err}, }, } } - // If the version is +incompatible, then the go.mod file must not exist: - // +incompatible is not an ongoing opt-out from semantic import versioning. - if strings.HasSuffix(info2.Version, "+incompatible") { - if !canUseIncompatible() { + invalidf := func(format string, args ...interface{}) error { + return &module.ModuleError{ + Path: r.modPath, + Err: &module.InvalidVersionError{ + Version: v, + Err: fmt.Errorf(format, args...), + }, + } + } + + // Add the +incompatible suffix if needed or requested explicitly, and + // verify that its presence or absence is appropriate for this version + // (which depends on whether it has an explicit go.mod file). + + if v == strings.TrimSuffix(statVers, "+incompatible") { + v = statVers + } + base := strings.TrimSuffix(v, "+incompatible") + var errIncompatible error + if !module.MatchPathMajor(base, r.pathMajor) { + if canUseIncompatible() { + v = base + "+incompatible" + } else { if r.pathMajor != "" { - return nil, invalidf("+incompatible suffix not allowed: module path includes a major version suffix, so major version must match") + errIncompatible = invalidf("module path includes a major version suffix, so major version must match") } else { - return nil, invalidf("+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required") + errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v))) } } + } else if strings.HasSuffix(v, "+incompatible") { + errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v)) + } - if err := module.CheckPathMajor(strings.TrimSuffix(info2.Version, "+incompatible"), r.pathMajor); err == nil { - return nil, invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(info2.Version)) + if statVers != "" && statVers == module.CanonicalVersion(statVers) { + // Since the caller-requested version is canonical, it would be very + // confusing to resolve it to anything but itself, possibly with a + // "+incompatible" suffix. Error out explicitly. + if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base { + return nil, &module.ModuleError{ + Path: r.modPath, + Err: &module.InvalidVersionError{ + Version: statVers, + Err: fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase), + }, + } } } - return info2, nil + if errIncompatible != nil { + return nil, errIncompatible + } + + return &RevInfo{ + Name: info.Name, + Short: info.Short, + Time: info.Time, + Version: v, + }, nil } // Determine version. - // - // If statVers is canonical, then the original call was repo.Stat(statVers). - // Since the version is canonical, we must not resolve it to anything but - // itself, possibly with a '+incompatible' annotation: we do not need to do - // the work required to look for an arbitrary pseudo-version. - if statVers != "" && statVers == module.CanonicalVersion(statVers) { - info2.Version = statVers - - if IsPseudoVersion(info2.Version) { - if err := r.validatePseudoVersion(info, info2.Version); err != nil { - return nil, err - } - return checkGoMod() - } - if err := module.CheckPathMajor(info2.Version, r.pathMajor); err != nil { - if canUseIncompatible() { - info2.Version += "+incompatible" - return checkGoMod() - } else { - if vErr, ok := err.(*module.InvalidVersionError); ok { - // We're going to describe why the version is invalid in more detail, - // so strip out the existing “invalid version” wrapper. - err = vErr.Err - } - return nil, invalidf("module contains a go.mod file, so major version must be compatible: %v", err) - } + if IsPseudoVersion(statVers) { + if err := r.validatePseudoVersion(info, statVers); err != nil { + return nil, err } - - return checkGoMod() + return checkCanonical(statVers) } - // statVers is empty or non-canonical, so we need to resolve it to a canonical - // version or pseudo-version. + // statVers is not a pseudo-version, so we need to either resolve it to a + // canonical version or verify that it is already a canonical tag + // (not a branch). // Derive or verify a version from a code repo tag. // Tag must have a prefix matching codeDir. @@ -441,71 +449,62 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e if v == "" || !strings.HasPrefix(trimmed, v) { return "", false // Invalid or incomplete version (just vX or vX.Y). } - if isRetracted(v) { - return "", false - } if v == trimmed { tagIsCanonical = true } - - if err := module.CheckPathMajor(v, r.pathMajor); err != nil { - if canUseIncompatible() { - return v + "+incompatible", tagIsCanonical - } - return "", false - } - return v, tagIsCanonical } // If the VCS gave us a valid version, use that. if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical { - info2.Version = v - return checkGoMod() + if info, err := checkCanonical(v); err == nil { + return info, err + } } // Look through the tags on the revision for either a usable canonical version // or an appropriate base for a pseudo-version. - var pseudoBase string + var ( + highestCanonical string + pseudoBase string + ) for _, pathTag := range info.Tags { v, tagIsCanonical := tagToVersion(pathTag) - if tagIsCanonical { - if statVers != "" && semver.Compare(v, statVers) == 0 { - // The user requested a non-canonical version, but the tag for the - // canonical equivalent refers to the same revision. Use it. - info2.Version = v - return checkGoMod() + if statVers != "" && semver.Compare(v, statVers) == 0 { + // The tag is equivalent to the version requested by the user. + if tagIsCanonical { + // This tag is the canonical form of the requested version, + // not some other form with extra build metadata. + // Use this tag so that the resolved version will match exactly. + // (If it isn't actually allowed, we'll error out in checkCanonical.) + return checkCanonical(v) } else { - // Save the highest canonical tag for the revision. If we don't find a - // better match, we'll use it as the canonical version. + // The user explicitly requested something equivalent to this tag. We + // can't use the version from the tag directly: since the tag is not + // canonical, it could be ambiguous. For example, tags v0.0.1+a and + // v0.0.1+b might both exist and refer to different revisions. // - // NOTE: Do not replace this with semver.Max. Despite the name, - // semver.Max *also* canonicalizes its arguments, which uses - // semver.Canonical instead of module.CanonicalVersion and thereby - // strips our "+incompatible" suffix. - if semver.Compare(info2.Version, v) < 0 { - info2.Version = v - } + // The tag is otherwise valid for the module, so we can at least use it as + // the base of an unambiguous pseudo-version. + // + // If multiple tags match, tagToVersion will canonicalize them to the same + // base version. + pseudoBase = v + } + } + // Save the highest non-retracted canonical tag for the revision. + // If we don't find a better match, we'll use it as the canonical version. + if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) { + if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() { + highestCanonical = v } - } else if v != "" && semver.Compare(v, statVers) == 0 { - // The user explicitly requested something equivalent to this tag. We - // can't use the version from the tag directly: since the tag is not - // canonical, it could be ambiguous. For example, tags v0.0.1+a and - // v0.0.1+b might both exist and refer to different revisions. - // - // The tag is otherwise valid for the module, so we can at least use it as - // the base of an unambiguous pseudo-version. - // - // If multiple tags match, tagToVersion will canonicalize them to the same - // base version. - pseudoBase = v } } - // If we found any canonical tag for the revision, return it. + // If we found a valid canonical tag for the revision, return it. // Even if we found a good pseudo-version base, a canonical version is better. - if info2.Version != "" { - return checkGoMod() + if highestCanonical != "" { + return checkCanonical(highestCanonical) } // Find the highest tagged version in the revision's history, subject to @@ -528,11 +527,10 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v0")) } } - pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid + pseudoBase, _ = tagToVersion(tag) } - info2.Version = PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short) - return checkGoMod() + return checkCanonical(PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)) } // validatePseudoVersion checks that version has a major version compatible with @@ -556,10 +554,6 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) } }() - if err := module.CheckPathMajor(version, r.pathMajor); err != nil { - return err - } - rev, err := PseudoVersionRev(version) if err != nil { return err diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go index 02e399f352..d98ea87da2 100644 --- a/src/cmd/go/internal/modfetch/coderepo_test.go +++ b/src/cmd/go/internal/modfetch/coderepo_test.go @@ -418,171 +418,204 @@ var codeRepoTests = []codeRepoTest{ zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=", zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5", }, + { + // Git branch with a semver name, +incompatible version, and no go.mod file. + vcs: "git", + path: "vcs-test.golang.org/go/mod/gitrepo1", + rev: "v2.3.4+incompatible", + err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`, + }, + { + // Git branch with a semver name, matching go.mod file, and compatible version. + vcs: "git", + path: "vcs-test.golang.org/git/semver-branch.git", + rev: "v1.0.0", + err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`, + }, + { + // Git branch with a semver name, matching go.mod file, and disallowed +incompatible version. + // The version/tag mismatch takes precedence over the +incompatible mismatched. + vcs: "git", + path: "vcs-test.golang.org/git/semver-branch.git", + rev: "v2.0.0+incompatible", + err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`, + }, + { + // Git branch with a semver name, matching go.mod file, and mismatched version. + // The version/tag mismatch takes precedence over the +incompatible mismatched. + vcs: "git", + path: "vcs-test.golang.org/git/semver-branch.git", + rev: "v2.0.0", + err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`, + }, + { + // v3.0.0-devel is the same as tag v4.0.0-beta.1, but v4.0.0-beta.1 would + // not be allowed because it is incompatible and a go.mod file exists. + // The error message should refer to a valid pseudo-version, not the + // unusable semver tag. + vcs: "git", + path: "vcs-test.golang.org/git/semver-branch.git", + rev: "v3.0.0-devel", + err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`, + }, } func TestCodeRepo(t *testing.T) { testenv.MustHaveExternalNetwork(t) + tmpdir := t.TempDir() - tmpdir, err := os.MkdirTemp("", "modfetch-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + for _, tt := range codeRepoTests { + f := func(tt codeRepoTest) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + if tt.vcs != "mod" { + testenv.MustHaveExecPath(t, tt.vcs) + } - t.Run("parallel", func(t *testing.T) { - for _, tt := range codeRepoTests { - f := func(tt codeRepoTest) func(t *testing.T) { - return func(t *testing.T) { - t.Parallel() - if tt.vcs != "mod" { - testenv.MustHaveExecPath(t, tt.vcs) - } + repo := Lookup("direct", tt.path) - repo := Lookup("direct", tt.path) + if tt.mpath == "" { + tt.mpath = tt.path + } + if mpath := repo.ModulePath(); mpath != tt.mpath { + t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) + } - if tt.mpath == "" { - tt.mpath = tt.path - } - if mpath := repo.ModulePath(); mpath != tt.mpath { - t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) + info, err := repo.Stat(tt.rev) + if err != nil { + if tt.err != "" { + if !strings.Contains(err.Error(), tt.err) { + t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) + } + return } + t.Fatalf("repo.Stat(%q): %v", tt.rev, err) + } + if tt.err != "" { + t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) + } + if info.Version != tt.version { + t.Errorf("info.Version = %q, want %q", info.Version, tt.version) + } + if info.Name != tt.name { + t.Errorf("info.Name = %q, want %q", info.Name, tt.name) + } + if info.Short != tt.short { + t.Errorf("info.Short = %q, want %q", info.Short, tt.short) + } + if !info.Time.Equal(tt.time) { + t.Errorf("info.Time = %v, want %v", info.Time, tt.time) + } - info, err := repo.Stat(tt.rev) - if err != nil { - if tt.err != "" { - if !strings.Contains(err.Error(), tt.err) { - t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) - } - return + if tt.gomod != "" || tt.gomodErr != "" { + data, err := repo.GoMod(tt.version) + if err != nil && tt.gomodErr == "" { + t.Errorf("repo.GoMod(%q): %v", tt.version, err) + } else if err != nil && tt.gomodErr != "" { + if err.Error() != tt.gomodErr { + t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr) } - t.Fatalf("repo.Stat(%q): %v", tt.rev, err) - } - if tt.err != "" { - t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) - } - if info.Version != tt.version { - t.Errorf("info.Version = %q, want %q", info.Version, tt.version) + } else if tt.gomodErr != "" { + t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr) + } else if string(data) != tt.gomod { + t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) } - if info.Name != tt.name { - t.Errorf("info.Name = %q, want %q", info.Name, tt.name) - } - if info.Short != tt.short { - t.Errorf("info.Short = %q, want %q", info.Short, tt.short) + } + + needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") + if tt.zip != nil || tt.zipErr != "" || needHash { + f, err := os.CreateTemp(tmpdir, tt.version+".zip.") + if err != nil { + t.Fatalf("os.CreateTemp: %v", err) } - if !info.Time.Equal(tt.time) { - t.Errorf("info.Time = %v, want %v", info.Time, tt.time) + zipfile := f.Name() + defer func() { + f.Close() + os.Remove(zipfile) + }() + + var w io.Writer + var h hash.Hash + if needHash { + h = sha256.New() + w = io.MultiWriter(f, h) + } else { + w = f } - - if tt.gomod != "" || tt.gomodErr != "" { - data, err := repo.GoMod(tt.version) - if err != nil && tt.gomodErr == "" { - t.Errorf("repo.GoMod(%q): %v", tt.version, err) - } else if err != nil && tt.gomodErr != "" { - if err.Error() != tt.gomodErr { - t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr) + err = repo.Zip(w, tt.version) + f.Close() + if err != nil { + if tt.zipErr != "" { + if err.Error() == tt.zipErr { + return } - } else if tt.gomodErr != "" { - t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr) - } else if string(data) != tt.gomod { - t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) + t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr) } + t.Fatalf("repo.Zip(%q): %v", tt.version, err) + } + if tt.zipErr != "" { + t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr) } - needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") - if tt.zip != nil || tt.zipErr != "" || needHash { - f, err := os.CreateTemp(tmpdir, tt.version+".zip.") + if tt.zip != nil { + prefix := tt.path + "@" + tt.version + "/" + z, err := zip.OpenReader(zipfile) if err != nil { - t.Fatalf("os.CreateTemp: %v", err) + t.Fatalf("open zip %s: %v", zipfile, err) } - zipfile := f.Name() - defer func() { - f.Close() - os.Remove(zipfile) - }() - - var w io.Writer - var h hash.Hash - if needHash { - h = sha256.New() - w = io.MultiWriter(f, h) - } else { - w = f - } - err = repo.Zip(w, tt.version) - f.Close() - if err != nil { - if tt.zipErr != "" { - if err.Error() == tt.zipErr { - return - } - t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr) + var names []string + for _, file := range z.File { + if !strings.HasPrefix(file.Name, prefix) { + t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) + continue } - t.Fatalf("repo.Zip(%q): %v", tt.version, err) - } - if tt.zipErr != "" { - t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr) + names = append(names, file.Name[len(prefix):]) } - - if tt.zip != nil { - prefix := tt.path + "@" + tt.version + "/" - z, err := zip.OpenReader(zipfile) - if err != nil { - t.Fatalf("open zip %s: %v", zipfile, err) - } - var names []string - for _, file := range z.File { - if !strings.HasPrefix(file.Name, prefix) { - t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) - continue - } - names = append(names, file.Name[len(prefix):]) - } - z.Close() - if !reflect.DeepEqual(names, tt.zip) { - t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) - } + z.Close() + if !reflect.DeepEqual(names, tt.zip) { + t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) } + } - if needHash { - sum, err := dirhash.HashZip(zipfile, dirhash.Hash1) - if err != nil { - t.Errorf("repo.Zip(%q): %v", tt.version, err) - } else if sum != tt.zipSum { - t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum) - } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash { - t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash) - } + if needHash { + sum, err := dirhash.HashZip(zipfile, dirhash.Hash1) + if err != nil { + t.Errorf("repo.Zip(%q): %v", tt.version, err) + } else if sum != tt.zipSum { + t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum) + } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash { + t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash) } } } } - t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) - if strings.HasPrefix(tt.path, vgotest1git) { - for vcs, alt := range altVgotests { - altTest := tt - altTest.vcs = vcs - altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git) - if strings.HasPrefix(altTest.mpath, vgotest1git) { - altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git) - } - var m map[string]string - if alt == vgotest1hg { - m = hgmap - } - altTest.version = remap(altTest.version, m) - altTest.name = remap(altTest.name, m) - altTest.short = remap(altTest.short, m) - altTest.rev = remap(altTest.rev, m) - altTest.err = remap(altTest.err, m) - altTest.gomodErr = remap(altTest.gomodErr, m) - altTest.zipErr = remap(altTest.zipErr, m) - altTest.zipSum = "" - altTest.zipFileHash = "" - t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest)) + } + t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) + if strings.HasPrefix(tt.path, vgotest1git) { + for vcs, alt := range altVgotests { + altTest := tt + altTest.vcs = vcs + altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git) + if strings.HasPrefix(altTest.mpath, vgotest1git) { + altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git) + } + var m map[string]string + if alt == vgotest1hg { + m = hgmap } + altTest.version = remap(altTest.version, m) + altTest.name = remap(altTest.name, m) + altTest.short = remap(altTest.short, m) + altTest.rev = remap(altTest.rev, m) + altTest.err = remap(altTest.err, m) + altTest.gomodErr = remap(altTest.gomodErr, m) + altTest.zipErr = remap(altTest.zipErr, m) + altTest.zipSum = "" + altTest.zipFileHash = "" + t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest)) } } - }) + } } var hgmap = map[string]string{ diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index 43b9564356..361d99373f 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -194,10 +194,10 @@ cp go.mod.orig go.mod go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible cd outside ! go list -m github.com/pierrec/lz4 -stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr '^go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' cd .. ! go list -m github.com/pierrec/lz4 -stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr '^go: github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' # A +incompatible pseudo-version is valid for a revision of the module # that lacks a go.mod file. @@ -222,7 +222,7 @@ stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible' # not resolve to a pseudo-version with a different major version. cp go.mod.orig go.mod ! go get -d github.com/pierrec/lz4@v2.0.8 -stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' +stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' # An invalid +incompatible suffix for a canonical version should error out, # not resolve to a pseudo-version. @@ -233,10 +233,10 @@ cp go.mod.orig go.mod go mod edit -require github.com/pierrec/lz4@v2.0.8+incompatible cd outside ! go list -m github.com/pierrec/lz4 -stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' cd .. ! go list -m github.com/pierrec/lz4 -stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' -- go.mod.orig -- module example.com -- cgit v1.2.3-54-g00ecf From 6b3e741a834c34b8a844a33b3aa060dd4ed37231 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Wed, 2 Feb 2022 09:15:44 -0800 Subject: [release-branch.go1.16] crypto/elliptic: make IsOnCurve return false for invalid field elements Updates #50974 Fixes #50977 Fixes CVE-2022-23806 Change-Id: I0201c2c88f13dd82910985a495973f1683af9259 Reviewed-on: https://go-review.googlesource.com/c/go/+/382855 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda Reviewed-by: Katie Hockman Trust: Katie Hockman TryBot-Result: Gopher Robot --- src/crypto/elliptic/elliptic.go | 5 +++ src/crypto/elliptic/elliptic_test.go | 81 ++++++++++++++++++++++++++++++++++++ src/crypto/elliptic/p224.go | 5 +++ 3 files changed, 91 insertions(+) diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go index f93dc16419..afedf18df1 100644 --- a/src/crypto/elliptic/elliptic.go +++ b/src/crypto/elliptic/elliptic.go @@ -71,6 +71,11 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int { } func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { + if x.Sign() < 0 || x.Cmp(curve.P) >= 0 || + y.Sign() < 0 || y.Cmp(curve.P) >= 0 { + return false + } + // y² = x³ - 3x + b y2 := new(big.Int).Mul(y, y) y2.Mod(y2, curve.P) diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go index e80e7731aa..bb16b0d163 100644 --- a/src/crypto/elliptic/elliptic_test.go +++ b/src/crypto/elliptic/elliptic_test.go @@ -721,3 +721,84 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte t.Errorf("point did not round-trip correctly: got (%v, %v), want (%v, %v)", X, Y, x, y) } } + +func testAllCurves(t *testing.T, f func(*testing.T, Curve)) { + tests := []struct { + name string + curve Curve + }{ + {"P256", P256()}, + {"P256/Params", P256().Params()}, + {"P224", P224()}, + {"P224/Params", P224().Params()}, + {"P384", P384()}, + {"P384/Params", P384().Params()}, + {"P521", P521()}, + {"P521/Params", P521().Params()}, + } + if testing.Short() { + tests = tests[:1] + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) + } +} + +// TestInvalidCoordinates tests big.Int values that are not valid field elements +// (negative or bigger than P). They are expected to return false from +// IsOnCurve, all other behavior is undefined. +func TestInvalidCoordinates(t *testing.T) { + testAllCurves(t, testInvalidCoordinates) +} + +func testInvalidCoordinates(t *testing.T, curve Curve) { + checkIsOnCurveFalse := func(name string, x, y *big.Int) { + if curve.IsOnCurve(x, y) { + t.Errorf("IsOnCurve(%s) unexpectedly returned true", name) + } + } + + p := curve.Params().P + _, x, y, _ := GenerateKey(curve, rand.Reader) + xx, yy := new(big.Int), new(big.Int) + + // Check if the sign is getting dropped. + xx.Neg(x) + checkIsOnCurveFalse("-x, y", xx, y) + yy.Neg(y) + checkIsOnCurveFalse("x, -y", x, yy) + + // Check if negative values are reduced modulo P. + xx.Sub(x, p) + checkIsOnCurveFalse("x-P, y", xx, y) + yy.Sub(y, p) + checkIsOnCurveFalse("x, y-P", x, yy) + + // Check if positive values are reduced modulo P. + xx.Add(x, p) + checkIsOnCurveFalse("x+P, y", xx, y) + yy.Add(y, p) + checkIsOnCurveFalse("x, y+P", x, yy) + + // Check if the overflow is dropped. + xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535)) + checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y) + yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535)) + checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy) + + // Check if P is treated like zero (if possible). + // y^2 = x^3 - 3x + B + // y = mod_sqrt(x^3 - 3x + B) + // y = mod_sqrt(B) if x = 0 + // If there is no modsqrt, there is no point with x = 0, can't test x = P. + if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil { + if !curve.IsOnCurve(big.NewInt(0), yy) { + t.Fatal("(0, mod_sqrt(B)) is not on the curve?") + } + checkIsOnCurveFalse("P, y", p, yy) + } +} diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go index 8c76021464..ff5c834452 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -48,6 +48,11 @@ func (curve p224Curve) Params() *CurveParams { } func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { + if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 || + bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 { + return false + } + var x, y p224FieldElement p224FromBig(&x, bigX) p224FromBig(&y, bigY) -- cgit v1.2.3-54-g00ecf From 5ef95666946dd744c0392166981783f72687993f Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 16 Dec 2021 14:33:13 -0500 Subject: [release-branch.go1.16] cmd/link: force eager binding when using plugins on darwin When building/using plugins on darwin, we need to use flat namespace so the same symbol from the main executable and the plugin can be resolved to the same address. Apparently, when using flat namespace the dynamic linker can hang at forkExec when resolving a lazy binding. Work around it by forcing early bindings. Updates #38824. Fixes #50245. Change-Id: I983aa0a0960b15bf3f7871382e8231ee244655f4 Reviewed-on: https://go-review.googlesource.com/c/go/+/372798 Trust: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: Ian Lance Taylor Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot (cherry picked from commit c5fee935bbb8f02406eb653cfed550593755a1a4) Reviewed-on: https://go-review.googlesource.com/c/go/+/373095 --- misc/cgo/testplugin/plugin_test.go | 28 +++++++++++++++++++++++++ misc/cgo/testplugin/testdata/forkexec/main.go | 30 +++++++++++++++++++++++++++ src/cmd/link/internal/ld/lib.go | 5 ++++- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 misc/cgo/testplugin/testdata/forkexec/main.go diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go index 8869528015..7b4df3f8ed 100644 --- a/misc/cgo/testplugin/plugin_test.go +++ b/misc/cgo/testplugin/plugin_test.go @@ -216,3 +216,31 @@ func TestIssue44956(t *testing.T) { goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go") run(t, "./issue44956.exe") } + +func TestForkExec(t *testing.T) { + // Issue 38824: importing the plugin package causes it hang in forkExec on darwin. + + t.Parallel() + goCmd(t, "build", "-o", "forkexec.exe", "./forkexec/main.go") + + var cmd *exec.Cmd + done := make(chan int, 1) + + go func() { + for i := 0; i < 100; i++ { + cmd = exec.Command("./forkexec.exe", "1") + err := cmd.Run() + if err != nil { + t.Errorf("running command failed: %v", err) + break + } + } + done <- 1 + }() + select { + case <-done: + case <-time.After(5 * time.Minute): + cmd.Process.Kill() + t.Fatalf("subprocess hang") + } +} diff --git a/misc/cgo/testplugin/testdata/forkexec/main.go b/misc/cgo/testplugin/testdata/forkexec/main.go new file mode 100644 index 0000000000..3169ff5f04 --- /dev/null +++ b/misc/cgo/testplugin/testdata/forkexec/main.go @@ -0,0 +1,30 @@ +// 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 ( + "os" + "os/exec" + _ "plugin" + "sync" +) + +func main() { + if os.Args[1] != "1" { + return + } + + var wg sync.WaitGroup + for i := 0; i < 8; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // does not matter what we exec, just exec itself + cmd := exec.Command("./forkexec.exe", "0") + cmd.Run() + }() + } + wg.Wait() +} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 18db567041..d56a51e375 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1269,7 +1269,10 @@ func (ctxt *Link) hostlink() { if ctxt.DynlinkingGo() && objabi.GOOS != "ios" { // -flat_namespace is deprecated on iOS. // It is useful for supporting plugins. We don't support plugins on iOS. - argv = append(argv, "-Wl,-flat_namespace") + // -flat_namespace may cause the dynamic linker to hang at forkExec when + // resolving a lazy binding. See issue 38824. + // Force eager resolution to work around. + argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load") } if !combineDwarf { argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols -- cgit v1.2.3-54-g00ecf From e2277c8dd4fb349a3d6b10ae8d1735c8e86956b7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 18:32:45 -0400 Subject: [release-branch.go1.16] runtime: set vdsoSP to caller's SP consistently m.vdsoSP should be set to the SP of the caller of nanotime1, instead of the SP of nanotime1 itself, which matches m.vdsoPC. Otherwise the unmatched vdsoPC and vdsoSP would make the stack trace look like recursive. We already do it correctly on AMD64, 386, and RISCV64. This CL fixes the rest. Also incorporate CL 352509, skipping a flaky test. Updates #47324, #50772. Fixes #50780. Change-Id: I98b6fcfbe9fc6bdd28b8fe2a1299b7c505371dd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/337590 Trust: Cherry Mui Trust: Josh Bleecher Snyder Reviewed-by: Josh Bleecher Snyder (cherry picked from commit 217507eb035933bac6c990844f0d71d6000fd339) Reviewed-on: https://go-review.googlesource.com/c/go/+/380716 Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- src/runtime/pprof/pprof_test.go | 35 +++++++++++++++++++++++++++++++++++ src/runtime/sys_linux_arm.s | 6 ++++-- src/runtime/sys_linux_arm64.s | 6 ++++-- src/runtime/sys_linux_mips64x.s | 6 ++++-- src/runtime/sys_linux_ppc64x.s | 8 +++++--- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 0e0cccbc6a..7bd28fc8bb 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1458,3 +1458,38 @@ func TestTryAdd(t *testing.T) { }) } } + +func TestTimeVDSO(t *testing.T) { + // Test that time functions have the right stack trace. In particular, + // it shouldn't be recursive. + + if runtime.GOOS == "android" { + // Flaky on Android, issue 48655. VDSO may not be enabled. + testenv.SkipFlaky(t, 48655) + } + + p := testCPUProfile(t, stackContains, []string{"time.now"}, avoidFunctions(), func(dur time.Duration) { + t0 := time.Now() + for { + t := time.Now() + if t.Sub(t0) >= dur { + return + } + } + }) + + // Check for recursive time.now sample. + for _, sample := range p.Sample { + var seenNow bool + for _, loc := range sample.Location { + for _, line := range loc.Line { + if line.Function.Name == "time.now" { + if seenNow { + t.Fatalf("unexpected recursive time.now") + } + seenNow = true + } + } + } + } +} diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 475f52344c..5ebff90e76 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -259,8 +259,9 @@ TEXT runtime·walltime1(SB),NOSPLIT,$8-12 MOVW R1, 4(R13) MOVW R2, 8(R13) + MOVW $ret-4(FP), R2 // caller's SP MOVW LR, m_vdsoPC(R5) - MOVW R13, m_vdsoSP(R5) + MOVW R2, m_vdsoSP(R5) MOVW m_curg(R5), R0 @@ -351,8 +352,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$8-8 MOVW R1, 4(R13) MOVW R2, 8(R13) + MOVW $ret-4(FP), R2 // caller's SP MOVW LR, m_vdsoPC(R5) - MOVW R13, m_vdsoSP(R5) + MOVW R2, m_vdsoSP(R5) MOVW m_curg(R5), R0 diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index 198a5bacef..27a285090e 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -221,8 +221,9 @@ TEXT runtime·walltime1(SB),NOSPLIT,$24-12 MOVD R2, 8(RSP) MOVD R3, 16(RSP) + MOVD $ret-8(FP), R2 // caller's SP MOVD LR, m_vdsoPC(R21) - MOVD R20, m_vdsoSP(R21) + MOVD R2, m_vdsoSP(R21) MOVD m_curg(R21), R0 CMP g, R0 @@ -304,8 +305,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$24-8 MOVD R2, 8(RSP) MOVD R3, 16(RSP) + MOVD $ret-8(FP), R2 // caller's SP MOVD LR, m_vdsoPC(R21) - MOVD R20, m_vdsoSP(R21) + MOVD R2, m_vdsoSP(R21) MOVD m_curg(R21), R0 CMP g, R0 diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index c3e9f37694..6450b2896a 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -228,8 +228,9 @@ TEXT runtime·walltime1(SB),NOSPLIT,$16-12 MOVV R2, 8(R29) MOVV R3, 16(R29) + MOVV $ret-8(FP), R2 // caller's SP MOVV R31, m_vdsoPC(R17) - MOVV R29, m_vdsoSP(R17) + MOVV R2, m_vdsoSP(R17) MOVV m_curg(R17), R4 MOVV g, R5 @@ -297,8 +298,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVV R2, 8(R29) MOVV R3, 16(R29) + MOVV $ret-8(FP), R2 // caller's SP MOVV R31, m_vdsoPC(R17) - MOVV R29, m_vdsoSP(R17) + MOVV R2, m_vdsoSP(R17) MOVV m_curg(R17), R4 MOVV g, R5 diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index 7be8c4c724..601ce20b78 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -204,8 +204,9 @@ TEXT runtime·walltime1(SB),NOSPLIT,$16-12 MOVD R5, 40(R1) MOVD LR, R14 + MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP MOVD R14, m_vdsoPC(R21) - MOVD R15, m_vdsoSP(R21) + MOVD R5, m_vdsoSP(R21) MOVD m_curg(R21), R6 CMP g, R6 @@ -296,9 +297,10 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVD R4, 32(R1) MOVD R5, 40(R1) - MOVD LR, R14 // R14 is unchanged by C code + MOVD LR, R14 // R14 is unchanged by C code + MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP MOVD R14, m_vdsoPC(R21) - MOVD R15, m_vdsoSP(R21) + MOVD R5, m_vdsoSP(R21) MOVD m_curg(R21), R6 CMP g, R6 -- cgit v1.2.3-54-g00ecf From 0a6cf8706fdd0fe1bd26e4d1ecbcd41650bf5e6c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 9 Feb 2022 15:36:17 +0000 Subject: [release-branch.go1.16] go1.16.14 Change-Id: Ibab854254bba48eab2396bc35a29ec18993f8720 Reviewed-on: https://go-review.googlesource.com/c/go/+/384495 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 86ad8f862a..aa9987f20c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.16.13 \ No newline at end of file +go1.16.14 \ No newline at end of file -- cgit v1.2.3-54-g00ecf