Skip to content

Commit

Permalink
cmd/link: avoid stamping runtime.defaultGOROOT when paths are being t…
Browse files Browse the repository at this point in the history
…rimmed

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>
  • Loading branch information
Bryan C. Mills committed Mar 18, 2022
1 parent 9a932c5 commit 9ac75d3
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/cmd/go/internal/work/gc.go
Expand Up @@ -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{}{},
Expand Down
63 changes: 63 additions & 0 deletions src/cmd/go/testdata/script/build_trimpath_goroot.txt
@@ -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()
}
9 changes: 7 additions & 2 deletions src/cmd/link/internal/ld/main.go
Expand Up @@ -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 != "" {
Expand Down
4 changes: 3 additions & 1 deletion src/cmd/link/internal/ld/pcln.go
Expand Up @@ -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
}
Expand Down

0 comments on commit 9ac75d3

Please sign in to comment.