]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: avoid stamping runtime.defaultGOROOT when paths are being trimmed
authorBryan C. Mills <bcmills@google.com>
Tue, 15 Mar 2022 20:37:50 +0000 (16:37 -0400)
committerBryan Mills <bcmills@google.com>
Fri, 18 Mar 2022 21:55:03 +0000 (21:55 +0000)
Previously, runtime.GOROOT() would return the string "go" in a binary
build with -trimpath. This change stamps the empty string instead,
using a sentinel value passed from cmd/go that looks like the GOROOT
environment variable (either "$GOROOT" or "%GOROOT%", depending on the
platform).

Fixes #51461

Change-Id: I1f10ef2435016a7b6213bd8c547df911f7feeae7
Reviewed-on: https://go-review.googlesource.com/c/go/+/390024
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/internal/work/gc.go
src/cmd/go/testdata/script/build_trimpath_goroot.txt [new file with mode: 0644]
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/pcln.go

index a6174b2ed2891ccce318f31b0ea5dcf6ab502296..fdde3b289f51954bd00063b66f6714ae91c2ac34 100644 (file)
@@ -27,7 +27,7 @@ import (
 )
 
 // The 'path' used for GOROOT_FINAL when -trimpath is specified
-const trimPathGoRootFinal = "go"
+const trimPathGoRootFinal string = "$GOROOT"
 
 var runtimePackages = map[string]struct{}{
        "internal/abi":            struct{}{},
diff --git a/src/cmd/go/testdata/script/build_trimpath_goroot.txt b/src/cmd/go/testdata/script/build_trimpath_goroot.txt
new file mode 100644 (file)
index 0000000..277a7a4
--- /dev/null
@@ -0,0 +1,63 @@
+# Regression test for https://go.dev/issue/51461 and https://go.dev/issue/51483.
+#
+# When built with -trimpath, runtime.GOROOT() returned the bogus string "go"
+# if GOROOT was not set explicitly in the environment.
+# It should instead return the empty string, since we know that we don't
+# have a valid path to return.
+#
+# TODO(#51483): when runtime.GOROOT() returns the empty string,
+# go/build should default to 'go env GOROOT' instead.
+
+[short] skip
+
+env GOROOT=
+env GOROOT_FINAL=
+
+go run .
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+go test -v .
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+! go run -trimpath .
+stdout '^GOROOT $'
+stderr '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
+
+! go test -trimpath -v .
+stdout '^GOROOT $'
+stdout '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
+
+-- go.mod --
+module example
+
+go 1.19
+-- main.go --
+package main
+
+import (
+       "fmt"
+       "go/build"
+       "os"
+       "runtime"
+)
+
+func main() {
+       fmt.Println("GOROOT", runtime.GOROOT())
+
+       p, err := build.Default.Import("runtime", "", build.FindOnly)
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       fmt.Println("runtime", p.Dir)
+}
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestMain(*testing.M) {
+       main()
+}
index 14f83566f5f1aa3e3f291d5f7ad7266d8a721978..fa95a7acf23d5f40b5e1cde07e976a79e5387b30 100644 (file)
@@ -119,8 +119,13 @@ func Main(arch *sys.Arch, theArch Arch) {
                }
        }
 
-       final := gorootFinal()
-       addstrdata1(ctxt, "runtime.defaultGOROOT="+final)
+       if final := gorootFinal(); final == "$GOROOT" {
+               // cmd/go sets GOROOT_FINAL to the dummy value "$GOROOT" when -trimpath is set,
+               // but runtime.GOROOT() should return the empty string, not a bogus value.
+               // (See https://go.dev/issue/51461.)
+       } else {
+               addstrdata1(ctxt, "runtime.defaultGOROOT="+final)
+       }
 
        buildVersion := buildcfg.Version
        if goexperiment := buildcfg.Experiment.String(); goexperiment != "" {
index b57e212794625735471f74af83baddeefc8da0f3..a81490089f4939e636ecd264903c524d96caa3d0 100644 (file)
@@ -804,7 +804,9 @@ func gorootFinal() string {
 func expandGoroot(s string) string {
        const n = len("$GOROOT")
        if len(s) >= n+1 && s[:n] == "$GOROOT" && (s[n] == '/' || s[n] == '\\') {
-               return filepath.ToSlash(filepath.Join(gorootFinal(), s[n:]))
+               if final := gorootFinal(); final != "" {
+                       return filepath.ToSlash(filepath.Join(final, s[n:]))
+               }
        }
        return s
 }