diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index db652810c2..7682d7f301 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,9 @@ # time to hit the patch failure N times. However, the actual tests run in AzDO, so we can't # reasonably cancel them from here (GitHub Actions). -name: "Test" +# The "0:" prefix makes this workflow's checks sort above the alphabetical AzDO stage names on the +# PR checks list, so patch failures are immediately visible without scrolling. +name: "0: Test" on: pull_request: diff --git a/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch b/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch deleted file mode 100644 index e737c46b5c..0000000000 --- a/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch +++ /dev/null @@ -1,415 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: bot-for-go[bot] <199222863+bot-for-go[bot]@users.noreply.github.com> -Date: Wed, 31 May 2023 16:54:31 -0500 -Subject: [PATCH] Add crypto backend GOEXPERIMENTs - -Adds crypto backend GOEXPERIMENTs and modifies tag handling to make -goexperiment.systemcrypto behave as an alias that enables the recommended -backend for the target GOOS. See src/internal/goexperiment/flags.go for more -information about the behavior. - -Includes new tests in "build_test.go" and "buildbackend_test.go" to help -maintain this feature. For more information, see the test files. ---- - src/cmd/go/internal/modindex/build_test.go | 73 +++++++++++++++++++ - src/go/build/buildbackend_test.go | 50 +++++++++++++ - .../build/testdata/backendtags_system/main.go | 3 + - .../backendtags_system/systemcrypto.go | 3 + - src/internal/buildcfg/exp.go | 34 +++++++++ - .../goexperiment/exp_cngcrypto_off.go | 8 ++ - src/internal/goexperiment/exp_cngcrypto_on.go | 8 ++ - .../goexperiment/exp_darwincrypto_off.go | 8 ++ - .../goexperiment/exp_darwincrypto_on.go | 8 ++ - .../goexperiment/exp_opensslcrypto_off.go | 8 ++ - .../goexperiment/exp_opensslcrypto_on.go | 8 ++ - .../goexperiment/exp_systemcrypto_off.go | 8 ++ - .../goexperiment/exp_systemcrypto_on.go | 8 ++ - src/internal/goexperiment/flags.go | 18 +++++ - 14 files changed, 245 insertions(+) - create mode 100644 src/cmd/go/internal/modindex/build_test.go - create mode 100644 src/go/build/buildbackend_test.go - create mode 100644 src/go/build/testdata/backendtags_system/main.go - create mode 100644 src/go/build/testdata/backendtags_system/systemcrypto.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_on.go - create mode 100644 src/internal/goexperiment/exp_darwincrypto_off.go - create mode 100644 src/internal/goexperiment/exp_darwincrypto_on.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_on.go - create mode 100644 src/internal/goexperiment/exp_systemcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_systemcrypto_on.go - -diff --git a/src/cmd/go/internal/modindex/build_test.go b/src/cmd/go/internal/modindex/build_test.go -new file mode 100644 -index 00000000000000..1756c5d027fee0 ---- /dev/null -+++ b/src/cmd/go/internal/modindex/build_test.go -@@ -0,0 +1,73 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This file is not a copy. It tests that the copied code in this directory is -+// maintained. Specifically, it tests areas that are modified by microsoft/go. -+// The files also contain intentional modifications, so it isn't reasonable (as -+// of writing) to test that the entire file is identical. -+ -+package modindex -+ -+import ( -+ "flag" -+ "os" -+ "strings" -+ "testing" -+) -+ -+var fixCopy = flag.Bool("fixcopy", false, "if true, update some copied code in build.go") -+ -+func TestCopyIdentical(t *testing.T) { -+ originalBytes, err := os.ReadFile("../../../../go/build/build.go") -+ if err != nil { -+ t.Fatal(err) -+ } -+ wantCode := string(originalBytes) -+ -+ gotBytes, err := os.ReadFile("build.go") -+ if err != nil { -+ t.Fatal(err) -+ } -+ gotCode := string(gotBytes) -+ -+ tests := []struct { -+ name string -+ prefix string -+ suffix string -+ }{ -+ {"matchTag", "func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {", "\n}"}, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ var want, got string -+ if _, after, ok := strings.Cut(wantCode, tt.prefix); ok { -+ if before, _, ok := strings.Cut(after, tt.suffix); ok { -+ want = before -+ } else { -+ t.Fatal("suffix not found in original file") -+ } -+ } else { -+ t.Fatal("prefix not found in original file") -+ } -+ if _, after, ok := strings.Cut(gotCode, tt.prefix); ok { -+ if before, _, ok := strings.Cut(after, tt.suffix); ok { -+ got = before -+ } else { -+ t.Fatal("suffix not found in copied file") -+ } -+ } else { -+ t.Fatal("prefix not found in copied file") -+ } -+ if got != want { -+ if *fixCopy { -+ if err := os.WriteFile("build.go", []byte(strings.Replace(gotCode, got, want, 1)), 0o666); err != nil { -+ t.Fatal(err) -+ } -+ } else { -+ t.Error("copy is not the same as original; use '-fixcopy' to replace copied code with the code from the original file") -+ } -+ } -+ }) -+ } -+} -diff --git a/src/go/build/buildbackend_test.go b/src/go/build/buildbackend_test.go -new file mode 100644 -index 00000000000000..ffb835ce34a2f7 ---- /dev/null -+++ b/src/go/build/buildbackend_test.go -@@ -0,0 +1,50 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package build -+ -+import ( -+ "reflect" -+ "testing" -+) -+ -+// Check that the systemcrypto tag works and collects AllTags correctly. -+// This is based on the TestAllTags test. -+func TestCryptoBackendAllTags(t *testing.T) { -+ ctxt := Default -+ // Remove tool tags so these tests behave the same regardless of the -+ // goexperiments that happen to be set during the run. -+ ctxt.ToolTags = []string{} -+ ctxt.GOARCH = "amd64" -+ ctxt.GOOS = "linux" -+ ctxt.BuildTags = []string{"goexperiment.systemcrypto"} -+ -+ p, err := ctxt.ImportDir("testdata/backendtags_system", 0) -+ if err != nil { -+ t.Fatal(err) -+ } -+ want := []string{"goexperiment.systemcrypto"} -+ if !reflect.DeepEqual(p.AllTags, want) { -+ t.Errorf("AllTags = %v, want %v", p.AllTags, want) -+ } -+ wantFiles := []string{"main.go", "systemcrypto.go"} -+ if !reflect.DeepEqual(p.GoFiles, wantFiles) { -+ t.Errorf("GoFiles = %v, want %v", p.GoFiles, wantFiles) -+ } -+ -+ // Test without systemcrypto - only main.go should be included -+ ctxt.BuildTags = []string{} -+ p, err = ctxt.ImportDir("testdata/backendtags_system", 0) -+ if err != nil { -+ t.Fatal(err) -+ } -+ want = []string{"goexperiment.systemcrypto"} -+ if !reflect.DeepEqual(p.AllTags, want) { -+ t.Errorf("AllTags = %v, want %v", p.AllTags, want) -+ } -+ wantFiles = []string{"main.go"} -+ if !reflect.DeepEqual(p.GoFiles, wantFiles) { -+ t.Errorf("GoFiles = %v, want %v", p.GoFiles, wantFiles) -+ } -+} -diff --git a/src/go/build/testdata/backendtags_system/main.go b/src/go/build/testdata/backendtags_system/main.go -new file mode 100644 -index 00000000000000..38dd16da61accb ---- /dev/null -+++ b/src/go/build/testdata/backendtags_system/main.go -@@ -0,0 +1,3 @@ -+package main -+ -+func main() {} -diff --git a/src/go/build/testdata/backendtags_system/systemcrypto.go b/src/go/build/testdata/backendtags_system/systemcrypto.go -new file mode 100644 -index 00000000000000..eb8a026982259c ---- /dev/null -+++ b/src/go/build/testdata/backendtags_system/systemcrypto.go -@@ -0,0 +1,3 @@ -+//go:build goexperiment.systemcrypto -+ -+package main -diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go -index aa41986e8e9387..d4121357526a84 100644 ---- a/src/internal/buildcfg/exp.go -+++ b/src/internal/buildcfg/exp.go -@@ -6,6 +6,7 @@ package buildcfg - - import ( - "fmt" -+ "os" - "reflect" - "strings" - -@@ -29,6 +30,19 @@ type ExperimentFlags struct { - // default in the current toolchain. This is, in effect, the "control" - // configuration and any variation from this is an experiment. - var Experiment ExperimentFlags = func() ExperimentFlags { -+ if os.Getenv("MS_GO_NOSYSTEMCRYPTO") == "1" { -+ // If MS_GO_NOSYSTEMCRYPTO is set, ensure that nosystemcrypto is in GOEXPERIMENT. -+ // We do it here because it is the earliest point where the toolchain tries to retrive -+ // the GOEXPERIMENT value. -+ // The environment variable is updated rather than appending "nosystemcrypto" to the -+ // result of ParseGOEXPERIMENT because the latter will be moved at some point to -+ // internal/goexperiment, which can't import the os package. -+ v := os.Getenv("GOEXPERIMENT") -+ if v != "" { -+ v += "," -+ } -+ os.Setenv("GOEXPERIMENT", v+"nosystemcrypto") -+ } - flags, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT)) - if err != nil { - Error = err -@@ -69,6 +83,18 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - regabiSupported = true - } - -+ // These are the goos/goarch combinations where systemcrypto is -+ // enabled by default. -+ var systemCryptoSupported bool -+ switch goos { -+ case "windows": -+ systemCryptoSupported = goarch == "amd64" || goarch == "arm64" -+ case "linux": -+ systemCryptoSupported = true -+ case "darwin": -+ systemCryptoSupported = true -+ } -+ - // Older versions (anything before V16) of dsymutil don't handle - // the .debug_rnglists section in DWARF5. See - // https://github.com/golang/go/issues/26379#issuecomment-2677068742 -@@ -86,6 +112,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - Dwarf5: dwarf5Supported, - RandomizedHeapBase64: true, - GreenTeaGC: true, -+ SystemCrypto: systemCryptoSupported, - } - flags := &ExperimentFlags{ - Flags: baseline, -@@ -125,6 +152,10 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - // to build with any experiment flags. - flags.Flags = goexperiment.Flags{} - continue -+ } else if f == "nosystemcrypto" { -+ // GOEXPERIMENT=nosystemcrypto disables system crypto. -+ flags.Flags.SystemCrypto = false -+ continue - } - val := true - if strings.HasPrefix(f, "no") { -@@ -151,6 +182,9 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - if flags.RegabiArgs && !flags.RegabiWrappers { - return nil, fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers") - } -+ if flags.BoringCrypto { -+ return nil, fmt.Errorf("GOEXPERIMENT boringcrypto is not supported in the Microsoft build of Go") -+ } - return flags, nil - } - -diff --git a/src/internal/goexperiment/exp_cngcrypto_off.go b/src/internal/goexperiment/exp_cngcrypto_off.go -new file mode 100644 -index 00000000000000..eb879f94fa0c42 ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.cngcrypto -+ -+package goexperiment -+ -+const CNGCrypto = false -+const CNGCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_cngcrypto_on.go b/src/internal/goexperiment/exp_cngcrypto_on.go -new file mode 100644 -index 00000000000000..5b0a55d6c5772e ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.cngcrypto -+ -+package goexperiment -+ -+const CNGCrypto = true -+const CNGCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_darwincrypto_off.go b/src/internal/goexperiment/exp_darwincrypto_off.go -new file mode 100644 -index 00000000000000..331111ce4759f7 ---- /dev/null -+++ b/src/internal/goexperiment/exp_darwincrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.darwincrypto -+ -+package goexperiment -+ -+const DarwinCrypto = false -+const DarwinCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_darwincrypto_on.go b/src/internal/goexperiment/exp_darwincrypto_on.go -new file mode 100644 -index 00000000000000..4bf785b999ecce ---- /dev/null -+++ b/src/internal/goexperiment/exp_darwincrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.darwincrypto -+ -+package goexperiment -+ -+const DarwinCrypto = true -+const DarwinCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_opensslcrypto_off.go b/src/internal/goexperiment/exp_opensslcrypto_off.go -new file mode 100644 -index 00000000000000..b28c0976a94cb0 ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.opensslcrypto -+ -+package goexperiment -+ -+const OpenSSLCrypto = false -+const OpenSSLCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_opensslcrypto_on.go b/src/internal/goexperiment/exp_opensslcrypto_on.go -new file mode 100644 -index 00000000000000..154386b3de81ea ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.opensslcrypto -+ -+package goexperiment -+ -+const OpenSSLCrypto = true -+const OpenSSLCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_systemcrypto_off.go b/src/internal/goexperiment/exp_systemcrypto_off.go -new file mode 100644 -index 00000000000000..6afc2ef2c5822e ---- /dev/null -+++ b/src/internal/goexperiment/exp_systemcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.systemcrypto -+ -+package goexperiment -+ -+const SystemCrypto = false -+const SystemCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_systemcrypto_on.go b/src/internal/goexperiment/exp_systemcrypto_on.go -new file mode 100644 -index 00000000000000..fcd4cb9da0d162 ---- /dev/null -+++ b/src/internal/goexperiment/exp_systemcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.systemcrypto -+ -+package goexperiment -+ -+const SystemCrypto = true -+const SystemCryptoInt = 1 -diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index 2cfb71578b421b..a0131d7ef82343 100644 ---- a/src/internal/goexperiment/flags.go -+++ b/src/internal/goexperiment/flags.go -@@ -60,6 +60,24 @@ type Flags struct { - StaticLockRanking bool - BoringCrypto bool - -+ // SystemCrypto enables the system crypto backend for the target GOOS. -+ // The specific backend used depends on the platform: -+ // - Linux: OpenSSL -+ // - Windows: CNG -+ // - Darwin: CommonCrypto/Security.framework -+ // -+ // Platform-specific code should use build constraints like: -+ // //go:build goexperiment.systemcrypto && linux -+ // //go:build goexperiment.systemcrypto && windows -+ // //go:build goexperiment.systemcrypto && darwin -+ SystemCrypto bool -+ -+ // OpenSSLCrypto, CNGCrypto, and DarwinCrypto are deprecated. -+ // Use SystemCrypto instead. -+ OpenSSLCrypto bool -+ CNGCrypto bool -+ DarwinCrypto bool -+ - // Regabi is split into several sub-experiments that can be - // enabled individually. Not all combinations work. - // The "regabi" GOEXPERIMENT is an alias for all "working"